理解C++代码 - "获取int中数字的数量"

33

我很难理解这段代码的确切作用:

int length = 1;
int x = 234567545;
while (x /= 10)
   length++;

它应该计算int变量中数字的数量。我不明白while循环是如何工作的。这个循环只是默认地到零并停止吗?另外,为什么长度从1开始?


15
使用调试器逐步执行您的程序,并“观察”变量“x”的值。顺便提一下,“/=”表示“ x = x / 10”。 - Thomas Matthews
5
顺便提一下:获取正数的位数的一个更简单的方法是 ceil(log10(x)) - user149341
4
当 x <= 0 时会崩溃,当 x = 10、100、1000 等时得到错误的答案。 - alephzero
4
为什么这个问题不适合讨论? - Peter Mortensen
3
我同意。如果说什么的话,给出的理由与主题无关。原帖并没有要求关于书籍或工具等方面的建议。 - Ted Lyngmo
显示剩余4条评论
6个回答

57

如果你是C++初学者,以下三个方面可能会让你感到困惑:

首先是运算符/=,它将整数除法(即没有余数)与赋值结合在一起。所以x /= 10实际上等同于x = x / 10

其次,在C++中,每个表达式在被评估后都有一个值。对于像(x = 0)这样的赋值语句,结果是赋值后x的值,即在本例中为0

第三个方面是,当x是整型时,类似if (x) ...的条件在C++中与if(x != 0)有着相同的意义,即如果x等于0,则为false;否则,为任何不为0的值,则为true

综上所述:while ( x /= 10 )表示先将x除以10并将商赋值给x,然后与0进行比较。当达到0时,循环结束。

顺便说一下:length1开始,因为任何数字,甚至是0,都至少包含一个数字。


3
我怀疑第三点的解释会让一些人感到不太舒服,因为它稍微歪曲了事实,但就个人而言,我认为这种抽象在这个难度级别上是可以接受的。 - Lightness Races in Orbit
3
在这种情况下,只需添加“对于类型为int的x”即可。 - user202729

27

x /= 10会不断地将x除以10,最终使它变成0,这样while循环就会因为0被解释为假(任何非0值均为真)而终止。

它从长度1开始的原因是因为数字中至少有1个数字: 如果x是从0到9(包括0和9)的数字,则x /= 10会立即将x变为0,意味着循环内部不会执行任何操作。因此,如果长度从0开始,它永远不会增加到1,这对于x只有一位数字的情况是错误的。

手动计算该示例:

  1. 234567545 / 10 = 23456754,为真,所以while循环继续执行,并且长度变为2。

  2. 23456754 / 10 = 2345675,为真,长度变为3。

  3. 2345675 / 10 = 234567,为真,长度变为4。

  4. 234567 / 10 = 23456,为真,长度变为5。

  5. 23456 / 10 = 2345,为真,长度变为6。

  6. 2345 / 10 = 234,为真,长度变为7。

  7. 234 / 10 = 23,为真,长度变为8。

  8. 23 / 10 = 2,为真,长度变为9。

  9. 2 / 10 = 0,为假。while循环停止,长度等于9。


8
循环
while (x /= 10) {
  length++;
}

程序将一直执行,直到执行x /= 10后的结果为false,因为0代表false,所以它将一直执行,直到x /= 10 的结果是 0为止。整数除法会截断小数部分,确保达到终止条件。可以通过添加一个简单的调试语句来说明这一点,例如:

while (x /= 10) {
  length++;
  std::cout << length << " " << x << std::endl;
}

需要输出哪些内容?

2 23456754
3 2345675
4 234567
5 23456
6 2345
7 234
8 23
9 2

6

整数除法将截断余数,因此不断使用整数除法将不可避免地导致结果为零。

将数字n除以10,同时每当所得商(存回n)不为零时增加计数器i一次,将导致i包含n的十进制表示中数字的数量。


5
我可以翻译这段文字。以下是您需要翻译的内容:

理解两个部分很有帮助:

  • 什么是"/="
  • 循环何时终止

解释"/="

这个符号:

x /= 10

与以下代码等效:

x = x / 10

解释循环何时终止

while 循环当条件为 false 时终止。而且 0 等同于 false。

while (condition) {
    length++;
}

每次循环中,x 都会除以 10,直到它变为 0。这终止了循环。

所以,条件同时满足两个方面:

  • 它是一个值,与 0 进行比较。循环将继续执行,直到此值评估为 0。
  • 它是一个赋值操作:x 在每次评估时都会获得新值。它被除以 10,因此收敛到 0。

-11

这是在C/C++中经常看到的一些愚蠢的行为,利用了TRUE被实现为非零,FALSE被实现为零的事实。所以x被重复除以10,表达式最终变成零,循环停止。

虽然令人困惑,但这种方法是可行的 - 直到有一天有人匆忙地将x从int更改为double :-) 写"while (x /= 10 >= 1)"或甚至将数学放入循环体内而不是条件内,会更清晰并且更少出错。

*我认为C的少数缺点之一是它没有明确的逻辑类型,而FORTRAN则有。


12
请不要在你的回答中涉及关于你不喜欢C++的抱怨。 - user202729
14
1)态度过于主观。2)这并不仅限于C/C++,而是很多编程语言都常见的问题。3)为了避免类似“某人匆忙更改类型”的情况(你永远不应该匆忙更改工作中的代码),我们正在编写和执行测试。4)将逻辑缩减到条件语句中对于任何有编程经验的人来说都不会感到困惑,只会让初学者感到困惑。(下一件你可能会争论的事情是零基索引…)5)问题是关于C++,而不是C,C++ 确实有一个明确的逻辑类型(C99以后的版本中C也有)。 - DevSolar
5
  1. 你的“修复”不能处理负数。
  2. 代码计算整数的位数,对于双精度浮点数来说这是未定义的。
- pipe
6
你的更改无效,因为 >= 的优先级比 /= 高 (https://en.cppreference.com/w/cpp/language/operator_precedence)。 因此,10 >= 1 被评估为 1,而 x /= 1 不会改变 x 的值,导致一个无限循环。 - kfx

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接