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

har*_*ski 1 c kernighan-and-ritchie

我正在通过 Kernighan & Ritchie 进行工作,并且必须练习 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);
    }
}
Run Code Online (Sandbox Code Playgroud)

我感到困惑的是为什么我需要这putchar (' ');条线。' '我不明白为什么程序退出if语句后c的值不是。最初我没有这一行,但令我惊讶的是,程序从输入中删除了所有空格。

由于我是一个初级C程序员,也许我对变量值的范围有些不理解,尽管在我看来,如果c的值是在' 'if语句开始时,并且如果是' '在第二个while中循环,当两者都退出时也应该是这样' ',但情况似乎并非如此。

我在 Google 上搜索了 K&R 练习 1.9,这就是我找到上面 wiki 的方式,并在 Stack Overflow 上查看了有关此练习的其他问题。

Fe2*_*2O3 5

两个实例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;
        }
}
Run Code Online (Sandbox Code Playgroud)

请注意,这将“修剪”在 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 );
}
Run Code Online (Sandbox Code Playgroud)

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

  • *count* 用作标志,而不是计数器。作为计数器,它可能会溢出。非常极端的情况,但只做“count=1”或者更好的“space_found=1”也没什么坏处。 (2认同)