differenct semantics between basic_istream::get and basic_istream::getline
basic_istream<Elem, Tr>& get(
Elem *str,
streamsize num,
Elem delim
);
basic_istream<Elem, Tr>& getline(
Elem *str,
streamsize num,
Elem delim
);
他们有着完全不同的语义.
#include <iostream>
using namespace std;
static const size_t Size = 5;
int main()
{
char buf[Size] = {'\0'};
int cnt = 0;
while (++cnt,
cin.get(buf, sizeof(buf)/sizeof(buf[0]))) // 每次读取 num - 1 个字符.
{
cout <<cnt <<": " <<buf <<endl;
}
cin.clear(); // 清除 ios_base::failbit. 使以后可以继续从 input stream 中读取数据.
cin.get(); // 手动清楚 input stream 中取出尚未取出的 '\n'
return 0;
}
(图 一 )
get 每次读取 num -1 个字符, 且不读取 delimiter. 如果没有遇到 delimiter, 就返回.
执行过程解释:
程序通过 while 循环读取, 每次读取 4(Size - 1) 个字符. 刚开始 input stream 中有 "12345678901234\n"
....
直到第 4 次循环时, input stream 中剩下了 "34\n" 这三个字符.
get 函数执行读取, 当遇到 delmiter(即 '\n') 后不读取这个 delimiter 而直接返回, 并输出第 4 行读取结果: 34.
此时 input stream 中只剩下了一个 "\n". 当再次执行 cin.get, input stream 中除了一个 delimiter("\n") 之外无其它数据, 这是导致 cin.get 出错的唯一条件. ios_base::failbit 被置位并返回. 此时 input stream 中 failbit 被设置. 为了今后继续读取
- 首先需要调用 cin.clear() 清除标记位
- 最后别忘了使用 cin.get() 手动清除 input stream 中的 delimiter.
// getline.cc
//
#include <iostream>
using namespace std;
static const size_t Size = 5;
int main()
{
char buf[Size] = {'\0'};
int cnt = 0;
while (++cnt,
cin.getline(buf, sizeof(buf)/sizeof(buf[0])))// 1.
{
cout <<cnt <<": " <<buf <<endl;
}
cin.clear(); // reset input state.
cout <<"place '1' has read: " <<buf <<endl;
cin.getline(buf, sizeof(buf)/sizeof(buf[0])); // 2.
cout <<"place '2' has read: " <<buf <<endl;
return 0;
}
(图 二)
(图 三)
getline 每次读取 num-1 或 num 个字符.
当 delimiter 位于 [0, num], 则读取至 delimiter 元素(包括 delimiter), 并去除读入的 delimiter, 添加 '\0' 至结果字串尾. 函数成功返回. (图二) 中 1, 2 输出.
当 delimiter 位于 (num, ∞), 则读取 num - 1 个元素, 并将 '\0' 添加至结果字串尾. 函数失败, 置位 ios_base::failbit. (图二) 中 3 输出, 以及(图三).
summary
函数名 | 读取字符 | 成功条件 | 失败条件 | 失败的标志位 | 特性 |
get | num - 1 | 第一个字符不是 delimiter | 第一个字符是 delimiter | ios_base::failbit | 不会取出 input stream 中的 delimiter |
getline |
|
delimiter 存在于 [0, num] 位置 | delimiter 存在于 (num, ∞) | ios_base::failbit | 会取出 input stream 中的 delimiter |