我在代码战中做一些练习,不得不做一个digital_root函数(将数字的所有数字递归加起来,直到只剩下一个数字为止)。 我相当有信心自己做对了,但是由于某种原因,即使打印显示len为1,我的while循环也不会中断。
#include <stdio.h>
#include <string.h>
int digital_root(int n) {
char number[10];
sprintf(number, "%d", n);
int len = strlen(number);
printf("Outer print: %s %d %d\n", number, n, len);
int sum = 0;
while(len > 1)
{
sum = 0;
for(int i = 0; i<len; i++)
{
sum += number[i] - '0';
}
sprintf(number, "%d", sum);
int len = strlen(getal); //!!!
printf("Inner print: %s %d %d\n", number, sum, len);
}
return sum;
}
我花了很长时间才弄清楚出了什么问题。我注意到在重新计算while循环中的len(标有!!!的行)时,我复制粘贴了'int'关键字。当我删除它时(因为不需要将它重新定义为int,它已经是),所有事情突然都按预期的方式工作。
这有点使我困惑。为什么会这样呢?我知道重新定义它是不好的做法,但是我不知道这会导致while循环不中断吗?
使用的编译器是Clan3.6 / C11。
(附言。当我在TIO中尝试相同的代码时,在两种情况下都有效...)
答案 0 :(得分:4)
您不是在重新定义现有变量,而是在定义新变量。
考虑以下示例:
#include <stdio.h>
int main(void) {
int x = 42;
printf("Outside, start. x (%p) = %d\n", (void *)&x, x);
{
printf("Inner block, start. x (%p) = %d\n", (void *)&x, x);
int x = 123;
printf("Inner block, end. x (%p) = %d\n", (void *)&x, x);
}
printf("Outside, end. x (%p) = %d\n", (void *)&x, x);
return 0;
}
示例输出:
Outside, start. x (0x7ffd6e6b8abc) = 42
Inner block, start. x (0x7ffd6e6b8abc) = 42
Inner block, end. x (0x7ffd6e6b8ab8) = 123
Outside, end. x (0x7ffd6e6b8abc) = 42
该程序输出存储器地址和x
的值。 x
的大多数用法是指在main开头声明的外部变量。但是在内部块中,在int x = 123;
之后,x
的所有出现都引用了另一个单独的变量,该变量也被称为x
(但在其他方面是独立的)。
当执行离开内部块时,外部x
变量再次变为可见。
这也称为shadowing。
在您的代码中,外部len
从未修改,因此while(len > 1)
始终为真。
顺便说一下,在大多数支持块作用域的语言中,阴影化是一个非常普遍的概念:
答案 1 :(得分:0)
您的第二个int len
创建第二个并行变量,该变量在{}块的末尾消失。然后,原始的len
恢复原状,完全没有变化。没有第二个int
,原始变量将被更改。有了它,原始的len
实际上就是一个不变的常数和无限循环。