arrays - 第 8 章 KNK C 编程(数组和 boolean 值)中重复数字工作示例的替代解决方案

标签 arrays c boolean

我正在处理我对 KNK 的 C 编程,现代方法中第 8 章已解决问题的尝试解决方案。我理解他们提出的答案,但想知道为什么我的答案是错误的。我难住了...
我正在尝试使用数组和 getchar() 函数编写一个程序来读取一个正数并检查它是否有重复的数字。
我的程序使用 boolean 值来跟踪数字中出现的数字。名为 digit_seen 的数组索引从 0 到 9,以对应 10 个可能的数字。最初数组的每个元素都是 false .
我想编写一个程序,当给定一个数字 n 时,它从左到右一次检查一个数字。将每个检查的数字存储到 digit变量,然后将其用作 digit_seen 的索引.如 digit_seen[digit]那么为真 digit在 n 中至少出现两次。但是如果 digit_seen[digit]则为假 digit之前没见过,然后程序会更新digit_seen[digit]真实并继续前进。
这是我不完美的代码:

#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。所以我们分配digit = EOF。此时while循环没有执行。我们转到 while 循环后面的 if 语句,查看它确实为真,并打印“无重复数字”字样。
现在假设我输入数字 22 而不是 12(即 n=22)。到我们第二次读取 2 位时 digit_seen[digit]已经
是的,所以我们跳出 while 循环。然后我们遇到了if(digit == EOF)并注意,在我们跳出 while 循环的情况下(而不是 while 括号中的参数为 false)digit必须分别具有介于 0 和 9 之间的整数值。然而,EOF 在计算机上存储为 -1。所以if(digit == EOF)没有执行,而是执行 else 子句,我们让程序正确地告诉我们已经输入了“重复数字”。
有人可以告诉我我在这里缺少什么吗?我的输出总是只是“重复数字”?此外,我想补充一点,这是一个有效的示例,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]尝试使用超出数组边界的索引访问数组。这可能会导致访问包含一些不相关值的内存的某些部分。如果该值非零,则 digit_seen[digit]评估为真,break;被执行以离开循环。
然后digit == EOF不正确,并打印“重复数字”。
首先,在用 getchar 得到一个字符后,使用isdigit测试是否为数字字符在 <ctype.h> 中声明的函数.如果是数字字符,则使用 digit -= '0'; 将其转换为数字 (0-9) .然后您可以将其用作数组的索引。
如果它不是数字字符,您可能会忽略它或向用户打印警告。例如,“空白”字符(使用 isspace 函数检测)可能会被忽略。这包括用户按 Enter 或 Return 时生成的换行符。

关于arrays - 第 8 章 KNK C 编程(数组和 boolean 值)中重复数字工作示例的替代解决方案,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67035418/

相关文章:

c - 矩阵和 vector 乘法优化算法

javascript - 将输入字符串转换为数组,以便可以操作每个单词

javascript - 在特定情况下,数组中数字的总和

c - 隔行YUYV转灰度的Neon优化

c - 用 C 实现 BMI 计算器

c#-4.0 - 在运行时创建 Func<T,Bool>

ruby-on-rails - 从 Virtus.model 动态扩展时使用 boolean 属性辅助方法

java - 我正在尝试迭代数组列表,找到数组中 boolean 值为 false 的第一项,将其设置为 true 并返回它

ruby - 如何在 Ruby 中交错不同长度的数组

C - 返回指向数组的指针