簡體   English   中英

第 8 章中重復數字工作示例的替代解決方案,KNK C 編程(數組和 Boolean 值)

[英]Alternative Solution to repeated digit worked example in chapter 8, KNK C Programming (Arrays & Boolean Values)

我正在嘗試解決 KNK 的 C Programming, A Modern Approach 中第 8 章的已解決問題。 我理解他們提出的答案,但想知道為什么我的答案是錯誤的。 我被難住了……

我正在嘗試使用 arrays 和 getchar() function 編寫一個程序來讀取一個正數並檢查它是否有重復的數字。

我的程序使用 Boolean 值來跟蹤數字中出現的數字。 名為digit_seen的數組從 0 到 9 索引以對應 10 個可能的數字。 最初,數組的每個元素都是false

編寫一個程序,當給定一個數字 n 時,從左到右一次檢查 n 的數字。 將每個檢查的數字存儲到digit變量中,然后將其用作digit_seen的索引。 如果digit_seen[digit]為真,則digit在 n 中至少出現兩次。 但是,如果digit_seen[digit]為 false,則digit之前沒有出現過,然后程序會將digit_seen[digit]更新為 true 並繼續運行。

這是我不完美的代碼:

#include <stdbool.h>
#include <stdio.h>

int main()
{
  bool digit_seen[10] = {false};
  int digit;
  printf("Enter a positive number: ");

  while((digit = getchar()) != EOF) {
    if(digit_seen[digit])
      break;

     digit_seen[digit] = true;
  }

  if(digit == EOF)
    printf("No repeated digit\n");
  else
    printf("Repeated digit\n");
}

讓我簡要解釋一下為什么我(顯然是錯誤地)認為它應該起作用。 假設我輸入數字 12(即 n=12)。 然后getchar()取 1,放入digit 請注意 1,= EOF。 所以執行了while循環。 我們還看到digit_seen[digit]為假,因此永遠不會執行 if 語句,現在我們將digit_seen[digit]分配為真(即數字 1 現在已經“看到”了)。

對下一個數字 2 重復確切的過程。然后掃描所有可能的數字,我們到達 EOF。 所以我們分配數字= EOF。 此時沒有執行while循環。 我們 go 到 while 循環后面的 if 語句,看到它確實是真的並打印“沒有重復的數字”字樣。

現在假設我輸入數字 22 而不是 12(即 n=22)。 當我們第二次讀取 2 位時digit_seen[digit]已經為真,所以我們跳出 while 循環。 然后我們遇到if(digit == EOF)並注意,在我們跳出 while 循環的情況下(而不是 while 括號中的參數為 false), digitinteger值必須分別介於 0 和 9 之間。 然而 EOF 在計算機上存儲為 -1。 所以if(digit == EOF)沒有被執行,而是 else 子句被執行並且我們的程序正確地告訴我們已經輸入了一個“重復的數字”。

有人可以告訴我我在這里缺少什么嗎? 我的 output 總是只是“重復數字”? 此外,我想補充一點,這是一個工作示例,KNK 提供了一個解決方案,但該解決方案不涉及 getchar()。 它涉及 scanf() 然后使用模數 (%) 和除法 (/) 操作從右到左分析數字的位數。 我理解他們的解決方案,但我不滿足於理解他們的替代方法並且沒有看到我失敗的地方。 我覺得很好奇他們沒有使用 getchar() 因為這是我在查看他們的解決方案之前的第一直覺。 有沒有辦法使用我提出的方法來解決問題,通過在輸入 n 時分析它們的數字? 或者它是否需要一種不同的方法,比如書中的方法?

作為一個自學成才的程序員,沒有其他人會問這些問題,任何解釋都會非常慷慨。

回答:

在考慮了您的考慮后,我將發布我的“替代答案”。 只需要一個小調整。 我現在更加了解 getchar() 的作用和 ASCII 表。 並不是說我有充分的理由不這樣做。 我會敦促任何閱讀與 KNK 比較的人應該好奇。

#include <stdbool.h>
#include <stdio.h>

int main()
{
  bool digit_seen[10] = {false};
  int  digit;
  printf("Enter a positive number: "); 

  while((digit = getchar()) != '\n') {
    digit -= '0';
    if(digit_seen[digit])
      break; 
  
     digit_seen[digit] = true;
  }
    
  if(digit == '\n')
    printf("No repeated digit\n");
  else
    printf("Repeated digit\n");
}

getchar()不返回數字。 它返回一個字符的代碼。

在 C 實現中最常用於字符的代碼(ASCII)中,數字字符“0”到“9”的代碼是 48 到 57。然后digit_seen[digit]嘗試使用超出范圍的索引訪問數組的數組。 這可能會導致訪問包含一些不相關值的 memory 的某些部分。 如果該值非零,則digit_seen[digit]評估為 true,並且break; 被執行以離開循環。

然后digit == EOF不為真,並打印“重復數字”。

首先,通過getchar得到一個字符后,使用<ctype.h>中聲明的isdigit function 測試它是否為數字字符。 如果是數字字符,則使用digit -= '0'; . 然后,您可以將其用作數組的索引。

如果它不是數字字符,您可以忽略它或向用戶打印警告。 例如,“空白”字符(使用isspace函數檢測)可能會被忽略。 這包括用戶按下回車鍵時生成的換行符。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM