C 编程问题(新手)

C 编程问题(新手)

我现在阅读了 Kernighan 和 Ritchie C 编程书,对“getchar”和“putchar”有一些疑问。

  1. 问题位于代码示例下方:

    #include <stdio.h>
    int main(void) {
        int c;
        c = getchar();
        while(c != EOF) {
            putchar(c);
            c = getchar();
        }
        return 0;
    }
    

当我在终端中运行此代码并输入一个符号(例如'i')然后按 Enter 键时,它会打印输入的符号:

i // 输入的符号
i // 打印的符号

之后,它会要求我输入另一个符号。如果我输入另一个符号,则该过程将重复。如果我按 Ctrl-D (EOF) 而不是输入另一个符号,程序将终止。第一个问题是,为什么当我运行此代码并在输入符号(“i”)后,我没有按 Enter 而是按 Ctrl-D,它会打印输入的符号并以这种方式打印:

ii // 输入第一个符号,按 Ctrl-D 后打印第二个符号

因此要终止程序我需要再次按 Ctrl-D。

  1. 为什么在上面的代码中我可以输入一个单词并且它会打印一个单词,而在下面的代码中即使我输入了一个单词它也只打印一个符号? 代码:

    #include <stdio.h>
    
    int main(void) {
        int c;
    
        printf("Enter a character:\n");
        c = getchar();
        printf("Entered character is:\n");
        putchar(c);
        printf("\n");
    
        return 0;
    }
    

如能提供任何帮助我将非常感激。

答案1

作为 C 语言输入的一般规则,它通常以行的形式工作 - 即,它是缓冲的。这意味着您输入的任何内容在Enter按下 之前都不会真正发送到程序。因此,对于第一个程序,它只是在请求时等待(也称为“阻塞”)getchar()直到一行数据输入。因此,在发送整行之前,它实际上看不到输入的任何内容。

该行以“This is a line[EOF]”的形式发送(其中 [EOF] 是 C 运行时定义的文字 EOF 字符)。第一个程序中的循环工作方式有点像 do/while 结构,只需从缓冲区中一次抓取一个字符并打印它们直到结束。如您所知,Ctrl+D是 EOF 的 shell 同义词。在第一个程序中,当您按下Enter它时,光标会移动到下一行的开头(请注意该程序中没有“\n”,“\n”是由用户在Enter输入行后按下的)。这就是为什么当您使用Ctrl+时D不会发生换行符,因为不是程序本身产生换行符,而是用户按下Enter产生此换行符的键。

第二个程序大致相同,但是调用时没有循环getchar()。这意味着getchar()只调用一次。它从输入缓冲区获取第一个字符,打印该字符,然后打印一个新行,然后退出。由于没有循环告诉它执行多次getchar(),这就是为什么您只看到一个字符而不是整行。

为了清楚起见,请记住输入是经过缓冲的。因此,在第二个程序中,您从输入缓冲区的开头抓取一个字符。但是,其余字符将保留在那里,直到您使用另一个调用来检索它们。开始 C/C++ 编程时的一个常见错误是忘记在完成操作后清空缓冲区。否则,该数据将保留在那里。

我记得当我第一次开始编写 C++(我的第一语言)程序时,我很困惑,我会使用类似下面的代码:

#include <iostream>

int main()
{
  std::cout << "Enter a sentence: ";
  std::string the_sentence;
  std::cin >> the_sentence;
  std::cout << "\nYou entered: " << the_sentence << std::endl;
  std::cout << "Enter another sentence: ";
  std::cin >> the_sentence;
  std::cout << "\nYou entered: " << the_sentence << std::endl;
  return 0;
}

我将得到一个运行的示例程序,如下所示:

Enter a sentence: Hi my name is Bob!
You entered: Hi
Enter a sentence: (the program would seemingly skip this input block)
You entered: my

这是因为 std::cin 调用只会读取第一个空格,其余输入则留在缓冲区中。下一次 std::cin 调用时,它会提取缓冲区中剩余的第一个内容,从而完全跳过实际输入阶段,因为缓冲区中已经有内容需要读取。

为了在 C 中刷新缓冲区,你可以使用类似

while((c = getchar()) != '\n' && c != EOF);

这只是一行 while 循环,本质上与第一个程序中的循环执行相同的操作,但它只是丢弃了输入

如果我充分回答了您的问题,请务必选择我的答案作为最佳答案。如果没有,请给我留言,我会尝试进一步扩展我的答案。

相关内容