为什么我需要在这段代码中显式地putchar(' ')?

roqulrg3  于 2023-08-03  发布在  其他
关注(0)|答案(2)|浏览(92)

我正在通过Kernighan &里奇工作,必须锻炼1.9。事实上,我写了一些代码,似乎解决了这个问题,我已经在Windows(使用Git Bash和gcc)和Termux(使用clang)上测试了它,方法是在一行中输入可变数量的空格,例如。echo " one two three",并且期望的输出出来,即one two three的值。
我通过反复试验得到了这个解决方案,尽管它与Lvictor在clc wiki上提供的解决方案相同。
我自己写的代码是:

#include <stdio.h>
    
/* Write a program to copy its input to its output, replacing each string of one or more blanks by a single blank. */
    
int main () {
    int c;
    
    while ((c = getchar()) != EOF) {
        if (c == ' ') {
            while ((c = getchar()) == ' ' ) {
            }
            putchar (' ');
        }
        putchar (c);
    }
}

字符串
我发现令人困惑的是为什么我需要putchar (' ');线。我不明白为什么程序退出if语句后c的值不是' '。最初我没有这一行,但后来程序从输入中删除了所有空格,这让我很惊讶。
作为一个初学C语言的程序员,也许我对变量值的作用域有些不理解,尽管在我看来,如果在if语句开始时c的值是' ',如果在第二个while循环中是' ',那么当两者都退出时,它也应该是' ',但情况似乎并非如此。
我在谷歌上搜索了K&R练习1.9,这就是我找到上面的wiki的原因,并在Stack Overflow上查看了关于这个练习的其他问题。

q3aa0525

q3aa05251#

getchar()两个示例使正确处理EOF变得困难。
以下是一个可能更容易理解的替代方案:

#include <stdio.h>

int main( void ) {
    int c;
    int SPfound = 0;

    while( ( c = getchar() ) != EOF ) // Note single "entry point" for data
        if( c == ' ' ) // swallow and flag one or more contiguous SP's
            SPfound = 1;
        else {
            if( SPfound ) // if any SP's, output a single one.
                putchar( ' ' );
            putchar( c ); // output the non-SP character.
            SPfound = 0;
        }
}

字符串
请注意,这将“修剪”EOF之前提取的任何 * 尾随空格 *。您可以考虑是否希望程序添加单个尾随SP来表示这些。

编辑:

不高兴离开它,这里有另一个版本,使用更少的代码。

#include <stdio.h>

int main( void ) {
    for( int c, prev = 0; ( c = getchar() ) != EOF; prev = c )
        if( !( c == ' ' && prev == ' ' ) ) // output when NOT consecutive SP's
            putchar( c );
}


这输出所遇到的任何系列的SP的 * 第一个 *,但是抑制第二个、第三个、…

7vux5j2d

7vux5j2d2#

我不明白为什么程序退出if语句后c的值不是' '
程序只在c == ' '的情况下进入if块的主体,但是 * 在该块内 *,内部while循环读取c的新值,一次一个,直到c被设置为与' '不同的值。因此,当控制离开内部的while循环时,c保证 * 不 * 包含' '
你争论,
如果在if语句开始时c的值是' ',并且如果在第二个while循环中它是' ',那么当两者都退出时,它也应该是' ',但情况似乎并非如此。
该逻辑的问题在于第二个while循环中的“if it is”。这充其量是不精确的。为此,重要的不是循环体中c的值(特别是对于空循环),而是在最后一次计算循环条件之后c的值-这将是它第一次计算为false。c在每次计算表达式时更新。这个循环的等价形式会更清楚:

do {
                c = getchar();
            } while (c == ' ');

字符串

相关问题