如何彻底清除C语言编程环境中的所有输入缓冲区残留内容?

2026-04-11 05:251阅读0评论SEO基础
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计1783个文字,预计阅读时间需要8分钟。

如何彻底清除C语言编程环境中的所有输入缓冲区残留内容?

为了在命令行程序中实现与用户的交互,我们的程序在运行过程中会频繁涉及到对标准输入/输出流的多次读写。在C语言中,这通常通过调用`scanf()`和`printf()`函数来实现。例如,接受用户输入的一个常见做法如下:

c#include

int main() { char question[100]; printf(请输入您的问题:); scanf(%99s, question); // 读取不超过99个字符的字符串

printf(您的问题是:%s\n, question); return 0;}

为了在命令行程序中实现和用户的交互,我们编写的程序的运行过程中往往涉及到对标准输入/输出流的多次读写。

在C语言中接受用户输入这一块,有着一个老生常谈的问题:“怎么样及时清空输入流中的数据?”

这也是这篇小笔记的主题内容。

先从缓冲区说起。

缓冲区是内存中划分出来的一部分。通常来说,缓冲区类型有三种:

  • 全缓冲
  • 行缓冲
  • 无缓冲
行缓冲

在C语言中缓冲区这个概念的存在感还是挺强的,比较常用到的缓冲区类型则是行缓冲了,如标准输入流 stdin 和标准输出流 stdout一般(终端环境下)就是在行缓冲模式下的。

行缓冲,顾名思义,就是针对该缓冲区的I/O操作基于行的。

  • 在遇到换行符前,程序的输入输出都会先被暂存流对应的缓冲区中

  • 而在遇到换行符后(或者缓冲区满了),程序才会进行真正的I/O操作,将该缓冲区中的数据写到对应的 (stream) 中以供后续读取

    如何彻底清除C语言编程环境中的所有输入缓冲区残留内容?

标准输入stdin而言,用户的输入首先会被存到相应的输入缓冲区中,每当用户按下回车键输入一个换行符,程序才会进行I/O操作,将缓冲区暂存的数据写入到stdin中,以供输入函数使用。

而对标准输出stdout来说,输出内容也首先会被暂存到相应的输出缓冲区中,每当输出数据遇到换行符时,程序才会将缓冲区中的数据写入stdout,继而打印到屏幕上。

这也是为什么在缓冲模式下,输出的内容不会立即打印到屏幕上:

#include <stdio.h> int main() { // 设置缓冲模式为行缓冲,缓冲区大小为10字节 setvbuf(stdout, NULL, _IOLBF, 10); fprintf(stdout, "1234567"); // 这里先向stdout对应的缓冲区中写入了7字节 getchar(); // 这里等待用户输入 printf("89"); // 再向stdout对应的缓冲区中写入了2字节 getchar(); // 接着等待用户输入 printf("Print!"); // 再向stdout对应的缓冲区中写入了6字节 getchar(); // 最后再等待一次用户输入 return 0; }

运行效果:

可以看到,直到执行到第二个getchar()时,屏幕上没有新的输出。

而在执行了printf("Print!")之后,输出缓冲区被填满了,输出缓冲区中现有的10字节的数据被写入到stdout中,继而才在屏幕上打印出123456789P

缓冲区内容被读走后,剩余的字符串rint!接着被写入输出缓冲区。程序运行结束后,输出缓冲区中的内容会被全部打印到屏幕上,所以会在最后看到rint!

C语言中常用的输入函数

输入函数做的工作主要是从文件流中读取数据,亦可将读取到的数据储存到内存中以供后续程序使用。

基于字符

// 从给定的文件流中读一个字符 (fgetc中的 f 的意思即"function") int fgetc( FILE *stream ); // 同fgetc,但是getc的实现*可能*是基于宏的 int getc( FILE *stream ); // 相当于是getc(stdin),从标准输入流读取一个字符 int getchar(void); // 返回获取的字符的ASCII码值,如果到达文件末尾就返回EOF(即返回-1) 基于行

// 从给定的文件流中读取(count-1)个字符或者读取直到遇到换行符或者EOF // fgets中的f代表“file”,而s代表“string” char *fgets( char *restrict str, int count, FILE *restrict stream ); // 返回指向字符串的指针或者空指针NULL 格式化输入

// 按照format的格式从标准输入流stdin中读取所需的数据并储存在相应的变量中 // scanf中的f代表“format” int scanf( const char *restrict format, ... ); // 按照format的格式从文件流stream中读取所需的数据并储存在相应的变量中 // fscanf中前一个f代表“file(stream)”,后一个f代表“format” int fscanf( FILE *restrict stream, const char *restrict format, ... ); // 按照format的格式从字符串buffer中截取所需的数据并储存在相应的变量中 // sscanf中的第一个s代表“string”,字符串 int sscanf( const char *restrict buffer, const char *restrict format, ... ); // 返回一个整型数值,代表成功根据格式赋值的变量数(arguments) 最常到的输入流问题

先来个不会出问题的示例:

#include <stdio.h> int main() { char test1[200]; char test2[200]; char testChar; printf("Input a Character: \n"); testChar = getchar(); fprintf(stdout, "Input String1: \n"); scanf("%s", test1); fprintf(stdout, "Input String2: \n"); scanf("%s", test2); printf("Got String1: [ %s ]\n", test1); printf("Got String2: [ %s ]\n", test2); printf("Got Char: [ %c ]\n", testChar); return 0; }

运行效果:


出问题的示例:

#include <stdio.h> int main() { char test[200]; char testChar1, testChar2, testChar3; fprintf(stdout, "Input String: \n"); scanf("%3s", test); printf("[1]Input a Character: \n"); testChar1 = getchar(); printf("[2]Input a Character: \n"); testChar2 = fgetc(stdin); printf("[3]Input a Character: \n"); testChar3 = getchar(); printf("Got String: [ %s ]\n", test); printf("Got Char1: [ %c ]\n", testChar1); printf("Got Char2: [ %c ]\n", testChar2); printf("Got Char3: [ %c ]\n", testChar3); return 0; }

运行效果:

因为我将格式设置为了%3s,所以scanf最多接收包含三个字符的字符串。

在这个示例中,我按要求输入了一条字符串Hello,并按下回车输入一个换行符,缓冲区数据Hello\n被写入到了stdin中。而scanf只从标准流stdin中读走了Hel这一部分字符串。

此时,标准流stdin中实际上还剩3个字符:

  1. l
  2. o
  3. \n (回车输入的换行符)

于是接下来三次针对字符的输入函数只会分别stdin取走这三个字符,而不会等待用户输入,这就没有达到我想要的效果。

在基本的命令行程序中很容易遇到这类问题,这也是为什么需要及时清空输入流stdin中的数据

如何处理残余内容

本文共计1783个文字,预计阅读时间需要8分钟。

如何彻底清除C语言编程环境中的所有输入缓冲区残留内容?

为了在命令行程序中实现与用户的交互,我们的程序在运行过程中会频繁涉及到对标准输入/输出流的多次读写。在C语言中,这通常通过调用`scanf()`和`printf()`函数来实现。例如,接受用户输入的一个常见做法如下:

c#include

int main() { char question[100]; printf(请输入您的问题:); scanf(%99s, question); // 读取不超过99个字符的字符串

printf(您的问题是:%s\n, question); return 0;}

为了在命令行程序中实现和用户的交互,我们编写的程序的运行过程中往往涉及到对标准输入/输出流的多次读写。

在C语言中接受用户输入这一块,有着一个老生常谈的问题:“怎么样及时清空输入流中的数据?”

这也是这篇小笔记的主题内容。

先从缓冲区说起。

缓冲区是内存中划分出来的一部分。通常来说,缓冲区类型有三种:

  • 全缓冲
  • 行缓冲
  • 无缓冲
行缓冲

在C语言中缓冲区这个概念的存在感还是挺强的,比较常用到的缓冲区类型则是行缓冲了,如标准输入流 stdin 和标准输出流 stdout一般(终端环境下)就是在行缓冲模式下的。

行缓冲,顾名思义,就是针对该缓冲区的I/O操作基于行的。

  • 在遇到换行符前,程序的输入输出都会先被暂存流对应的缓冲区中

  • 而在遇到换行符后(或者缓冲区满了),程序才会进行真正的I/O操作,将该缓冲区中的数据写到对应的 (stream) 中以供后续读取

    如何彻底清除C语言编程环境中的所有输入缓冲区残留内容?

标准输入stdin而言,用户的输入首先会被存到相应的输入缓冲区中,每当用户按下回车键输入一个换行符,程序才会进行I/O操作,将缓冲区暂存的数据写入到stdin中,以供输入函数使用。

而对标准输出stdout来说,输出内容也首先会被暂存到相应的输出缓冲区中,每当输出数据遇到换行符时,程序才会将缓冲区中的数据写入stdout,继而打印到屏幕上。

这也是为什么在缓冲模式下,输出的内容不会立即打印到屏幕上:

#include <stdio.h> int main() { // 设置缓冲模式为行缓冲,缓冲区大小为10字节 setvbuf(stdout, NULL, _IOLBF, 10); fprintf(stdout, "1234567"); // 这里先向stdout对应的缓冲区中写入了7字节 getchar(); // 这里等待用户输入 printf("89"); // 再向stdout对应的缓冲区中写入了2字节 getchar(); // 接着等待用户输入 printf("Print!"); // 再向stdout对应的缓冲区中写入了6字节 getchar(); // 最后再等待一次用户输入 return 0; }

运行效果:

可以看到,直到执行到第二个getchar()时,屏幕上没有新的输出。

而在执行了printf("Print!")之后,输出缓冲区被填满了,输出缓冲区中现有的10字节的数据被写入到stdout中,继而才在屏幕上打印出123456789P

缓冲区内容被读走后,剩余的字符串rint!接着被写入输出缓冲区。程序运行结束后,输出缓冲区中的内容会被全部打印到屏幕上,所以会在最后看到rint!

C语言中常用的输入函数

输入函数做的工作主要是从文件流中读取数据,亦可将读取到的数据储存到内存中以供后续程序使用。

基于字符

// 从给定的文件流中读一个字符 (fgetc中的 f 的意思即"function") int fgetc( FILE *stream ); // 同fgetc,但是getc的实现*可能*是基于宏的 int getc( FILE *stream ); // 相当于是getc(stdin),从标准输入流读取一个字符 int getchar(void); // 返回获取的字符的ASCII码值,如果到达文件末尾就返回EOF(即返回-1) 基于行

// 从给定的文件流中读取(count-1)个字符或者读取直到遇到换行符或者EOF // fgets中的f代表“file”,而s代表“string” char *fgets( char *restrict str, int count, FILE *restrict stream ); // 返回指向字符串的指针或者空指针NULL 格式化输入

// 按照format的格式从标准输入流stdin中读取所需的数据并储存在相应的变量中 // scanf中的f代表“format” int scanf( const char *restrict format, ... ); // 按照format的格式从文件流stream中读取所需的数据并储存在相应的变量中 // fscanf中前一个f代表“file(stream)”,后一个f代表“format” int fscanf( FILE *restrict stream, const char *restrict format, ... ); // 按照format的格式从字符串buffer中截取所需的数据并储存在相应的变量中 // sscanf中的第一个s代表“string”,字符串 int sscanf( const char *restrict buffer, const char *restrict format, ... ); // 返回一个整型数值,代表成功根据格式赋值的变量数(arguments) 最常到的输入流问题

先来个不会出问题的示例:

#include <stdio.h> int main() { char test1[200]; char test2[200]; char testChar; printf("Input a Character: \n"); testChar = getchar(); fprintf(stdout, "Input String1: \n"); scanf("%s", test1); fprintf(stdout, "Input String2: \n"); scanf("%s", test2); printf("Got String1: [ %s ]\n", test1); printf("Got String2: [ %s ]\n", test2); printf("Got Char: [ %c ]\n", testChar); return 0; }

运行效果:


出问题的示例:

#include <stdio.h> int main() { char test[200]; char testChar1, testChar2, testChar3; fprintf(stdout, "Input String: \n"); scanf("%3s", test); printf("[1]Input a Character: \n"); testChar1 = getchar(); printf("[2]Input a Character: \n"); testChar2 = fgetc(stdin); printf("[3]Input a Character: \n"); testChar3 = getchar(); printf("Got String: [ %s ]\n", test); printf("Got Char1: [ %c ]\n", testChar1); printf("Got Char2: [ %c ]\n", testChar2); printf("Got Char3: [ %c ]\n", testChar3); return 0; }

运行效果:

因为我将格式设置为了%3s,所以scanf最多接收包含三个字符的字符串。

在这个示例中,我按要求输入了一条字符串Hello,并按下回车输入一个换行符,缓冲区数据Hello\n被写入到了stdin中。而scanf只从标准流stdin中读走了Hel这一部分字符串。

此时,标准流stdin中实际上还剩3个字符:

  1. l
  2. o
  3. \n (回车输入的换行符)

于是接下来三次针对字符的输入函数只会分别stdin取走这三个字符,而不会等待用户输入,这就没有达到我想要的效果。

在基本的命令行程序中很容易遇到这类问题,这也是为什么需要及时清空输入流stdin中的数据

如何处理残余内容