#include <stdio.h> int main() { int c, prevchar; while ((c = getchar()) != EOF) { if (c != prevchar || prevchar != ' ') putchar(c); prevchar = c; } }
字符串这段代码是如何工作的?代码运行良好。我只需要了解它的工作原理。
qco9c6ql1#
你的方法很好,但是你必须将prevchar初始化为任何不同于' '的东西。如果你将prevchar初始化为' ',初始空格将从流中删除,这不是赋值的一部分。以下是修改后的版本:
prevchar
' '
#include <stdio.h> int main(void) { int c, prevchar = 0; while ((c = getchar()) != EOF) { if (c != prevchar || prevchar != ' ') putchar(c); prevchar = c; } return 0; }
字符串
代码的逻辑是,如果从输入流读取的每个字节与前一个字节不同,或者前一个字节不是空白(空格字符' '),则将其复制到输出流。表示为(c != prevchar || prevchar != ' ')的条件等价于
(c != prevchar || prevchar != ' ')
(!(c == prevchar && prevchar == ' '))
型除非它与前一个字节相同并且前一个字节也是空的,否则复制可读取为c的。将此条件表示为
c
(c != ' ' || prevchar != ' ')
型例如:c不是空白或前一个字节不是空白。
r7knjye22#
这本书在很多方面都有问题--最糟糕的问题是它积极地教导了一些糟糕的做法,比如在if语句中赋值,这反过来又是一个令人难以置信的众所周知的bug来源。这在1989年也是众所周知的糟糕做法。但是,如果在C89编译器上执行,代码不会从main()调用未定义的行为,这是K&R的目标编译器。我们不应该编写具有未定义行为错误的代码。这在1989年也是众所周知的坏习惯。在现代C中,我们可以跳过main()中的return 0;,但在旧的C89中从来不允许这样做。prevchar也必须在使用前初始化。将其初始化为0或EOF将有效,因为这两个都不是有效的字符串输入形式stdin。一个无bug,无不良实践,C89兼容版本的代码:
if
return 0;
0
EOF
stdin
#include <stdio.h> int main (void) { int prevchar = 0; for(int c=getchar(); c != EOF; c=getchar()) { if (c != prevchar || prevchar != ' ') { putchar(c); } prevchar=c; } return 0; }
字符串说明:
int
for
c != prevchar
prevchar != ' '
为了增加可读性和减少晦涩,我们也可以这样写:
if (c == ' ' && prevchar == ' ') ; /* do nothing */ else putchar(c);
型这是更清晰和自我文档化,所以它比原来的编程好得多。我们也可以在这个表达式上应用 * 德摩根定律 *,尽管我不认为它提高了可读性:
if (c != ' ' || prevchar != ' ') putchar(c);
型
2条答案
按热度按时间qco9c6ql1#
你的方法很好,但是你必须将
prevchar
初始化为任何不同于' '
的东西。如果你将prevchar
初始化为' '
,初始空格将从流中删除,这不是赋值的一部分。以下是修改后的版本:
字符串
代码的逻辑是,如果从输入流读取的每个字节与前一个字节不同,或者前一个字节不是空白(空格字符
' '
),则将其复制到输出流。表示为
(c != prevchar || prevchar != ' ')
的条件等价于型
除非它与前一个字节相同并且前一个字节也是空的,否则复制可读取为
c
的。将此条件表示为
型
例如:
c
不是空白或前一个字节不是空白。r7knjye22#
这本书在很多方面都有问题--最糟糕的问题是它积极地教导了一些糟糕的做法,比如在
if
语句中赋值,这反过来又是一个令人难以置信的众所周知的bug来源。这在1989年也是众所周知的糟糕做法。但是,如果在C89编译器上执行,代码不会从main()调用未定义的行为,这是K&R的目标编译器。我们不应该编写具有未定义行为错误的代码。这在1989年也是众所周知的坏习惯。
在现代C中,我们可以跳过main()中的
return 0;
,但在旧的C89中从来不允许这样做。prevchar
也必须在使用前初始化。将其初始化为0
或EOF
将有效,因为这两个都不是有效的字符串输入形式stdin
。一个无bug,无不良实践,C89兼容版本的代码:
字符串
说明:
c
连续地从标准输入中逐字符阅读。它必须是int
,因为常量EOF
是int
。EOF
,循环会立即中断。请注意,for
循环总是在执行循环体之前检查循环条件。prevchar
存储前一个字符。c != prevchar
,意思是:c
是空格,要么prevchar
不是,反之亦然。在任何一种情况下,它都不是一行中的两个空格。c
不是一个空格,而prevchar
是,反之亦然。在这种情况下,输入它在空格和其他字符之间进行转换,所以也不是一行中的两个空格。c
和prevchar
相等,在这种情况下,一行中可能有2个空格,需要prevchar != ' '
检查来排除这种情况。为了增加可读性和减少晦涩,我们也可以这样写:
型
这是更清晰和自我文档化,所以它比原来的编程好得多。我们也可以在这个表达式上应用 * 德摩根定律 *,尽管我不认为它提高了可读性:
型