浅谈cin>>与cin.getline读取缓冲区中的‘\n’和空格的区别

本文通过实例探讨了C++中不同输入方式的工作机制。重点分析了getchar()、cin.getline()与cin >> 的行为差异,尤其是在处理输入缓冲区中的换行符时的不同表现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

发现一个有趣的问题,先看代码:

#include <iostream>
#include <stdio.h> //getchar()

using namespace std;

int main()
{
    int n;
    char test[100];
    cin >> n;
    getchar(); //1#
    cin.getline(test, 11); //2#
    //cin >> test; //3#
    cout << test << endl;
    return 0;
}

以上代码运行成功,但是,如果我将1#注释掉,运行程序,输入n的值之后,程序就马上结束,为什么呢?

想必大家早已知道getchar()在这里的作用:清除缓冲区中的残留的'\n'。

而'\n'正是cin.getline()的结束符,所以程序还没有等用户进行下一次输入,cin.getline就已经从缓冲区将残留的换行符'\n'读了进来,提前结束了程序


有意思的事情发生了,如果我将1#和2#同时注释掉,解除3#的注释,编译后,代码运行成功。

到这里,想必大家应该产生疑问了吧?缓冲区里不是还有1个'\n'吗?为什么没有导致cin>>的提前结束呢?'\n'换行符的确是cin>>的结束符啊!


没错,换行符的确是cin>>的结束符,但是,在cin执行的时候,它是会忽略一开始输入的所有换行符'\n'和空格的!所以它并不会将残留的'\n'当做它的结束符!

而cin.getline()是不会忽略的!


如有问题,恳请指正!





<think>我们正在讨论C++中的输入函数:cin, cin.get(), cin.getline(), getline()。根据引用内容,我们可以总结如下: 1. **cin**: 它是C++标准输入流对象,通常用于读取输入。但是,cin在遇到空格、制表符或换行符时会停止读取。因此,它通常用于读取单个单词,而不是整行。例如: ```cpp char word[100]; cin >> word; // 遇到空格就停止 ``` 2. **cin.get()**: 这个函数有两个主要用法: - 读取单个字符:`cin.get(char&)` 或 `char ch = cin.get();` - 读取一行字符串:`cin.get(char* str, int size, char delim = '\n')`。它会读取直到遇到换行符(默认)或指定的分隔符,或者读取了size-1个字符(因为最后一个位置留给空字符'\0')。重要的是,它不会丢弃换行符,所以如果连续使用,可能需要用`cin.ignore()`来忽略换行符。 3. **cin.getline()**: 它用于读取一整行字符串,其函数签名是`cin.getline(char* str, int size, char delim = '\n')`。`cin.get()`类似,但不同之处在于,`cin.getline()`会读取并丢弃换行符(或指定的分隔符)。也就是说,输入缓冲区中的换行符被读取了,但不会存储在目标字符串中,并且被从输入流中移除。 4. **getline()**: 注意,还有一个全局函数`getline()`,它用于`std::string`对象。其用法是`getline(istream& is, string& str, char delim)`。它读取输入流`is`中的字符,直到遇到分隔符(默认是换行符),然后将读取的内容存储到`string`对象`str`中。`cin.getline()`不同的是,它处理的是`string`类型,而不是字符数组,而且它同样会丢弃换行符。 总结区别: - **cin**:遇到空白符(空格、制表符、换行符)停止,不读取空白符,也不读取换行符(换行符留在缓冲区)。 - **cin.get()**(用于字符串):可以读取整行,包括空白符,直到遇到换行符(或指定分隔符),但换行符留在输入流中(不读取到字符串,也不丢弃)。 - **cin.getline()**:读取整行,包括空白符,直到遇到换行符(或指定分隔符),并且丢弃换行符(从流中移除)。 - **getline()**(用于string):`cin.getline()`类似,但用于`string`对象,同样会丢弃换行符。 另外,引用[3]提到:使用`cin.get()`或`cin.getline()`读取字符串时,如果输入的字符数达到或超过指定大小,会导致后续读入失败。因此,在使用后可能需要检查输入流的状态,并清除错误。 下面是一个综合示例,展示这些函数的用法(参考引用[1]的示例并扩展): ```cpp #include <iostream> #include <string> // 为了使用getline(string) using namespace std; int main() { char ch; char str1[100], str2[100]; string str3; // 使用cin.get()读取单个字符 cout << "Enter a character: "; ch = cin.get(); // 读取一个字符,可能是换行符(如果前面有输入的话) cin.ignore(); // 忽略接下来的一个字符(通常是换行符) // 使用cin.get()读取一行 cout << "Enter a line (using cin.get): "; cin.get(str1, 100); // 读取一行,最多99个字符(保留一个给'\0'),遇到换行符停止,但换行符留在流中 cin.ignore(); // 忽略换行符,否则影响下一次读取 // 使用cin.getline()读取一行 cout << "Enter a line (using cin.getline): "; cin.getline(str2, 100); // 读取一行,并丢弃换行符 // 使用getline()读取一行到string cout << "Enter a line (using getline for string): "; getline(cin, str3); // 读取一行到string,丢弃换行符 // 输出结果 cout << "Character: " << ch << endl; cout << "Line (cin.get): " << str1 << endl; cout << "Line (cin.getline): " << str2 << endl; cout << "Line (getline for string): " << str3 << endl; return 0; } ``` 注意:在实际使用中,连续读取时要注意输入流中可能遗留的换行符,这会导致后续的读取函数立即遇到换行符而停止。因此,通常需要在读取字符或字符串后使用`cin.ignore()`来清除缓冲区中的换行符或其他不需要的字符。 相关问题: 1.C++中,如何安全地读取包含空格的字符串? 2. `cin.ignore()`函数的作用是什么?如何使用它? 3. 当使用`cin.get()`或`cin.getline()`读取字符数组时,如何避免缓冲区溢出? 4.C++中,为什么推荐使用`getline()`(用于string)而不是`cin.getline()`(用于字符数组)?</think>### C++输入函数区别详解 在C++中,`cin`、`cin.get()`、`cin.getline()` `getline()` 都是输入函数,但行为有显著差异: #### 1. **cin** - **行为**:遇到**空白符(空格/制表符/换行)即停止读取**,不读取空白符。 - **适用场景**:读取**单个单词**。 - **示例**: ```cpp char word[100]; cin >> word; // 输入"Hello World" → 只存储"Hello" ``` #### 2. **cin.get()** - **行为**: - 单字符版:`cin.get(char)` 读取**单个字符(包括空格/换行)**。 - 字符串版:`cin.get(char*, size)` 读取**整行(含空格)**,但**保留换行符在输入流中**。 - **风险**:需手动清除换行符(`cin.ignore()`)。 - **示例**: ```cpp char ch; cin.get(ch); // 读取单个字符(含空格) char line[100]; cin.get(line, 100); // 读取整行,换行符仍留在流中 ``` #### 3. **cin.getline()** - **行为**: - `cin.getline(char*, size)` 读取**整行(含空格)** 并**丢弃换行符**。 - 自动添加字符串结束符 `\0`。 - **安全性**:指定缓冲区大小避免溢出。 - **示例**: ```cpp char line[100]; cin.getline(line, 100); // 读取整行并丢弃换行符 ``` #### 4. **getline()(全局函数)** - **行为**: - `getline(istream, string)` 专用于 `std::string` 对象。 - 读取整行(含空格),**自动处理内存分配**,丢弃换行符。 - **优势**:最安全便捷的整行读取方式。 - **示例**: ```cpp #include <string> string str; getline(cin, str); // 读取整行到string对象 ``` --- ### 关键区别总结 | 函数 | 读取对象 | 处理空格 | 处理换行符 | 缓冲区溢出风险 | |--------------------|------------|----------|------------------|----------------| | `cin >> var` | 单词 | ✗ 停止 | 不读取 | 中 | | `cin.get(char)` | 单个字符 | ✓ 读取 | 读取 | 低 | | `cin.get(char*)` | 字符数组 | ✓ 读取 | 保留在输入流 | 高(需指定大小) | | `cin.getline()` | 字符数组 | ✓ 读取 | 读取并丢弃 | 中(需指定大小) | | `getline(cin, str)`| string对象 | ✓ 读取 | 读取并丢弃 | 无(自动管理) | > **最佳实践**: > - 读取**单个单词** → `cin` > - 读取**整行到字符数组** → `cin.getline()` > - 读取**整行到字符串** → `getline(cin, str)`(最推荐)[^1][^2][^3] --- ### 综合示例 ```cpp #include <iostream> #include <string> using namespace std; int main() { char word[100]; cout << "Enter a word: "; cin >> word; // 遇到空格停止 cin.ignore(); // 清除残留换行符 char line1[100]; cout << "Enter a line (cin.getline): "; cin.getline(line1, 100); // 读取整行并丢弃换行符 string line2; cout << "Enter a line (getline): "; getline(cin, line2); // 读取整行到string cout << "\nResults:\n"; cout << "Word: " << word << endl; cout << "Line (getline): " << line1 << endl; cout << "Line (string): " << line2 << endl; return 0; } ```
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值