清除 C/C++ 中的输入缓冲区

简介: 临时存储区称为缓冲区。所有标准输入和输出设备都包含一个输入和输出缓冲区。在标准 C/C++ 中,流被缓冲,例如在标准输入的情况下,当我们按下键盘上的键时,它不会发送到您的程序,而是由操作系统缓冲直到时间分配到那个程序。

「这是我参与11月更文挑战的第8天,活动详情查看:2021最后一次更文挑战


什么是缓冲区?


临时存储区称为缓冲区。所有标准输入和输出设备都包含一个输入和输出缓冲区。在标准 C/C++ 中,流被缓冲,例如在标准输入的情况下,当我们按下键盘上的键时,它不会发送到您的程序,而是由操作系统缓冲直到时间分配到那个程序。


它如何影响编程?


在各种情况下,您可能需要清除不需要的缓冲区,以便在所需容器中而不是在前一个变量的缓冲区中获取下一个输入。比如C遇到“scanf()”后,如果需要输入字符数组或字符,而C++遇到“cin”语句后,需要输入字符数组或一个字符串,我们需要清除输入缓冲区,否则所需的输入被前一个变量的缓冲区占用,而不是被所需的容器占用。在第一次输入后在输出屏幕上按“Enter”(回车)时,由于前一个变量的缓冲区是新容器的空间(因为我们没有清除它),程序会跳过下面的输入容器。


从那些“Hello World”程序中升级。学习实现堆、堆栈、链表等数据结构!查看我们的**C 数据结构**课程,立即开始学习。


在C的情况下

#include<stdio.h>
int main()
{
  char str[80], ch;
  scanf("%s", str);
  ch = getchar();
  printf("%s\n", str);
  printf("%c", ch); 
  return 0;
}
复制代码


输入:

Haiyong
a
复制代码


输出:

Haiyong
复制代码


在C++的情况下

#include<iostream>
#include<vector>
using namespace std;
int main()
{
  int a;
  char ch[80];
  cin >> a;
  cin.getline(ch,80);
  cout << a << endl;
  cout << ch << endl;
  return 0;
}
复制代码


输入:

4 
Haiyong
复制代码


输出:

4
复制代码


在上面的两个代码中,输出都没有按需要打印。这样做的原因是一个被占用的缓冲区。“\n”字符留在缓冲区中,并作为下一个输入读取。


如何解决?


在C的情况下:  


1. 使用“ while ((getchar()) != '\n'); ”  : 输入“while ((getchar()) != '\n');” 读取缓冲区字符直到结束并丢弃它们(包括换行符)并在“scanf()”语句清除输入缓冲区并允许在所需容器中输入后使用它。

#include<stdio.h>
int main()
{
  char str[80], ch;
  scanf("%s", str);
  while ((getchar()) != '\n');
  ch = getchar();
  printf("%s\n", str);
  printf("%c", ch);
  return 0;
}
复制代码


输入:

Haiyong 
a
复制代码


输出:

Haiyong 
a
复制代码


2. 使用“ fflush(stdin) ” :在“scanf()”语句之后输入“fflush(stdin)”也会清除输入缓冲区,但避免使用它,根据C,输入流被称为“未定义” ++11 标准。


在C++的情况下:  


1. 使用“cin.ignore(numeric_limits::max(),'\n'); ”  :- 输入

“cin.ignore(numeric_limits::max(),'\n');” 在“cin”语句丢弃输入流中的所有内容之后,包括换行符。

#include<iostream>
#include<ios> 
#include<limits>
using namespace std;
int main()
{
  int a;
  char str[80];
  cin >> a;
  cin.ignore(numeric_limits<streamsize>::max(),'\n');
  cin.getline(str, 80);
  cout << a << endl;
  cout << str << endl;
  return 0;
}
复制代码


输入:

4 
Haiyong
复制代码


输出:

4 
Haiyong
复制代码


2. 使用“cin.sync()”: 在“cin”语句之后输入“cin.sync()”会丢弃缓冲区中剩余的所有内容。尽管“cin.sync()”并不适用于所有实现(根据 C++11 及以上标准)。


#include<iostream>
#include<ios> 
#include<limits>
using namespace std;
int main()
{
  int a;
  char str[80];
  cin >> a;
  cin.sync();
  cin.getline(str, 80);
  cout << a << endl;
  cout << str << endl;
  return 0;
}
复制代码


输入:

4 
Haiyong
复制代码


输出:


4
复制代码


3. 使用“cin >> ws”: 在“cin”语句后输入“cin>>ws”告诉编译器忽略缓冲区并丢弃字符串或字符数组实际内容之前的所有空格。


#include<iostream>
#include<vector>
using namespace std;
int main()
{
  int a;
  string s;
  cin >> a;
  cin >> ws;
  getline(cin, s);
  cout << a << endl;
  cout << s << endl;
  return 0;
}
复制代码


输入:

4 
Haiyong
复制代码


输出:

4 
Haiyong



目录
相关文章
|
机器人 Linux C语言
C语言, C++ IO 总结. 一篇文章帮你透析缓冲区存在的意义, C, C++ IO的常见用法
C语言, C++ IO 总结. 一篇文章帮你透析缓冲区存在的意义, C, C++ IO的常见用法
C语言, C++ IO 总结. 一篇文章帮你透析缓冲区存在的意义, C, C++ IO的常见用法
|
缓存 网络协议 Linux
C/C++零散知识点汇总之缓冲区
C/C++零散知识点汇总之缓冲区
|
Linux C++ 缓存
C/C++中printf/cout 计算顺序与缓冲区问题
1.printf/cout在同一个语句中都是从右向左计算的。 看如下的代码: 1 #include 2 int main() 3 { 4 int i=0; 5 printf("%d %d",i++,i++); 6 printf(" %d",i++); 7 return 0; 8 } 输出结果: 1 0 2 (第5行,先计算右边的i++,再计算左边的i++。
1409 0
|
C++ Windows
[c/c++]小议几个写缓冲区的函数
1. strncpychar *strncpy(char *dest, char *src, size_t num); strcpy没得说,它自动补NULL,而且你得给他足够大的空间,一般是读src的长度n然后动态分配(n + 1)大小的内存。
1048 0
|
8月前
|
编译器 C++ 开发者
【C++篇】深度解析类与对象(下)
在上一篇博客中,我们学习了C++的基础类与对象概念,包括类的定义、对象的使用和构造函数的作用。在这一篇,我们将深入探讨C++类的一些重要特性,如构造函数的高级用法、类型转换、static成员、友元、内部类、匿名对象,以及对象拷贝优化等。这些内容可以帮助你更好地理解和应用面向对象编程的核心理念,提升代码的健壮性、灵活性和可维护性。
|
4月前
|
人工智能 机器人 编译器
c++模板初阶----函数模板与类模板
class 类模板名private://类内成员声明class Apublic:A(T val):a(val){}private:T a;return 0;运行结果:注意:类模板中的成员函数若是放在类外定义时,需要加模板参数列表。return 0;
92 0
|
4月前
|
存储 编译器 程序员
c++的类(附含explicit关键字,友元,内部类)
本文介绍了C++中类的核心概念与用法,涵盖封装、继承、多态三大特性。重点讲解了类的定义(`class`与`struct`)、访问限定符(`private`、`public`、`protected`)、类的作用域及成员函数的声明与定义分离。同时深入探讨了类的大小计算、`this`指针、默认成员函数(构造函数、析构函数、拷贝构造、赋值重载)以及运算符重载等内容。 文章还详细分析了`explicit`关键字的作用、静态成员(变量与函数)、友元(友元函数与友元类)的概念及其使用场景,并简要介绍了内部类的特性。
169 0
|
6月前
|
编译器 C++ 容器
【c++11】c++11新特性(上)(列表初始化、右值引用和移动语义、类的新默认成员函数、lambda表达式)
C++11为C++带来了革命性变化,引入了列表初始化、右值引用、移动语义、类的新默认成员函数和lambda表达式等特性。列表初始化统一了对象初始化方式,initializer_list简化了容器多元素初始化;右值引用和移动语义优化了资源管理,减少拷贝开销;类新增移动构造和移动赋值函数提升性能;lambda表达式提供匿名函数对象,增强代码简洁性和灵活性。这些特性共同推动了现代C++编程的发展,提升了开发效率与程序性能。
180 12
|
7月前
|
设计模式 安全 C++
【C++进阶】特殊类设计 && 单例模式
通过对特殊类设计和单例模式的深入探讨,我们可以更好地设计和实现复杂的C++程序。特殊类设计提高了代码的安全性和可维护性,而单例模式则确保类的唯一实例性和全局访问性。理解并掌握这些高级设计技巧,对于提升C++编程水平至关重要。
130 16