C++混用C/C++风格输入时字符串读取失败的原因
问题描述
一段用于优化数字读取效率的代码逻辑如下:首先读取数字T(表示后续需要输入的字符串总数),之后依次读取T个字符串并输出。
实际运行时出现异常:代码无法正常输出读取到的字符串,仅会输出换行符;如果改用cin读取T,代码即可正常运行。
问题复现代码
#include <stdio.h> #include <string> #include <iostream> template <typename T> inline void read(T &f) { f = 0; T fu = 1; char c = getchar(); while (c < '0' || c > '9') { if (c == '-') { fu = -1; } c = getchar(); } while (c >= '0' && c <= '9') { f = (f << 3) + (f << 1) + (c & 15); c = getchar(); } f *= fu; } int main() { std::ios::sync_with_stdio(false); std::cout.tie(nullptr), std::cin.tie(nullptr); int T; read(T); while (T--) { std::string s; std::cin >> s; std::cout << s << "\n"; } return 0; }
异常原因
异常的核心诱因是混用C、C++两套输入接口时关闭了流同步,导致两套接口的输入缓冲区状态不一致:
- 自定义
read函数使用C标准库接口getchar()读取输入,属于C风格IO;后续读取字符串使用的std::cin属于C++风格流IO。 - 默认配置下,C++流与C标准IO保持同步状态,二者共享同一个输入缓冲区,读取指针的位置全局一致,不会出现内容错读。
- 调用
std::ios::sync_with_stdio(false)后,C++流会脱离同步状态,启用独立的私有缓冲区,不再与C标准IO共享读取位置状态:getchar()读完数字T后,C标准IO的读取指针已经移动到数字后的第一个分隔符位置,但std::cin的私有缓冲区没有同步这个偏移,会从错误的位置开始读取内容,直接跳过有效字符串段,仅读到后续的空白换行符,最终表现为只输出换行、无法读取有效字符串。 - 如果全程使用
std::cin读取T,所有输入操作都走C++流的私有缓冲区,读取指针始终自洽,就不会触发该异常。
解决方案
若需要混用C风格与C++风格输入接口,请勿调用
std::ios::sync_with_stdio(false);关闭流同步。
如果追求输入效率必须关闭同步,需要保证全程只使用同一套IO接口,不要交叉调用C标准IO和C++流IO。
内容的提问来源于stack exchange,提问作者James Eade
相关产品推荐
相关产品推荐

