我正在处理我对 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/