C++IO操作(2)成员函数getline读取一行
今天我们的介绍的getline是std::basic_istream<CharT,Traits>的成员函数,
basic_istream& getline( char_type* s, std::streamsize count );
(1)
basic_istream& getline( char_type* s, std::streamsize count, char_type delim );
(2)
这个函数是从流中提取字符,直到行尾或者遇到指定的分隔符 delim。
第一个重载函数相当于使用 getline(s, count, widen(‘\n’))。其中,s 是输入流,count 是用来存储提取的字符的字符串对象,widen(‘\n’) 是将换行符 ‘\n’ 转换成与字符流相匹配的宽字符。
该函数的行为类似于 UnformattedInputFunction。简单来说,这个函数用于从输入流中提取字符,并将它们存储到指定的数组中,直到以下任一情况发生(按照给出的顺序进行测试):
1、输入序列已经到达文件结尾;
2、下一个可用的字符是指定的分隔符 delim ;
3、已经提取了 count - 1 个字符(如果 count 是非正数,也会发生这种情况)。
在执行该函数之前,会构造并检查 sentry 对象,以确保输入流处于可用状态。在提取每个字符时,会增加 gcount() 计数器的值,以记录已经提取的字符数量。如果遇到了第三种情况,则会调用 setstate(failbit) 函数设置 failbit 标志位,表示提取操作失败。
需要注意的是,函数只是将字符存储到指定的数组中,而并不会添加字符串终止符。如果需要将提取的字符组成一个字符串,请根据需要手动添加终止符。
如果该函数没有提取任何字符,那么在调用 setstate() 函数之前,会在本地错误状态中设置 failbit。
无论如何,如果 count > 0,函数会将一个空字符 CharT() 存储到数组的下一个连续位置,并更新 gcount() 计数器。也就是说,即使没有提取任何字符,函数仍然会在数组中存储一个空字符,并且 gcount() 的值会相应增加。这样做的目的是确保在任何情况下,gcount() 都能正确记录已提取的字符数量,即使为零。
注意,CharT() 表示类型 CharT 的默认构造值,对于 char 类型来说,它是 ‘\0’(空字符),对于 wchar_t 类型来说,它是 L’\0’(宽字符空字符)。
由于条件 #2 在条件 #3 之前进行测试,因此正好填满缓冲区的输入行不会触发 failbit。
在这个函数中,分隔符被视为一个已提取的字符,并计入 gcount() 计数器。因此,如果输入行恰好填满了缓冲区,并以分隔符作为结束符,则输入行的大小等于 count。在这种情况下,虽然提取了 count - 1 个字符,但并不会触发 failbit,因为分隔符被视为已提取的字符。只有当提取的字符数量超过 count - 1 个时,才会触发 failbit。
同样地,对于空的输入行(没有提取任何字符),由于分隔符(通常是换行符)被视为已提取的字符,所以也不会触发 failbit。即使输入行为空,分隔符也会被提取和计数,并更新到 gcount() 中。只有当尝试提取超过 count - 1 个字符时,才会触发 failbit。
例子:
#include <array>
#include <iostream>
#include <sstream>
#include <vector>
int main()
{
std::istringstream input("abc|def|gh");
std::vector<std::array<char, 4>> v;
// note: the following loop terminates when std::ios_base::operator bool()
// on the stream returned from getline() returns false
for (std::array<char, 4> a; input.getline(&a[0], 4, '|');)
v.push_back(a);
for (auto& a : v)
std::cout << &a[0] << '\n';
}
更多推荐
所有评论(0)