<iostream>
库功能庞杂,本节仅介绍最常用的部分。下面围绕输入类 istream
展开说明。
提取运算符(>>
)
如前面课程所示,可使用提取运算符(>>
)从输入流读取数据。C++ 为所有内置类型预定义了提取操作,也可为自己的类重载该运算符。
用提取运算符读入字符串时,常遇到缓冲区溢出问题:
char buf[10]{};
std::cin >> buf;
若用户输入 18 个字符,缓冲区将溢出,导致未定义行为。一般而言,绝不要假设用户会输入多少字符。
一种解决方法是使用操控符(manipulator)。操控符是可与 >>
或 <<
联用以修改流行为的对象。你已使用过 std::endl
,它既输出换行又刷新缓冲区。C++ 提供 setw
(位于 <iomanip>
)可限制读取字符数:
#include <iomanip>
char buf[10]{};
std::cin >> std::setw(10) >> buf;
此时最多读取 9 个字符(留一个给终止符),其余字符留在流中,等待下一次提取。
提取与空白符
再次提醒:提取运算符会跳过空白符(空格、制表符、换行)。
示例程序:
int main()
{
char ch{};
while (std::cin >> ch)
std::cout << ch;
return 0;
}
输入:
Hello my name is Alex
输出:
HellomynameisAlex
若想保留空白符,可使用 istream
提供的成员函数,其中最常用的是 get()
:
int main()
{
char ch{};
while (std::cin.get(ch))
std::cout << ch;
return 0;
}
输入同上,输出:
Hello my name is Alex
get()
还有字符串版本,可指定最大读取字符数:
int main()
{
char strBuf[11]{};
std::cin.get(strBuf, 11);
std::cout << strBuf << '\n';
return 0;
}
输入:
Hello my name is Alex
输出:
Hello my n
仅读取前 10 个字符,其余字符留在流中。
注意:get()
不会读取换行符。这可能导致意外结果:
int main()
{
char strBuf[11]{};
std::cin.get(strBuf, 11); // 读取至多 10 字符
std::cout << strBuf << '\n';
std::cin.get(strBuf, 11); // 再读取至多 10 字符
std::cout << strBuf << '\n';
return 0;
}
输入:
Hello!
输出:
Hello!
随后程序结束。原因是第一次 get()
读到换行即停止,第二次 get()
看到换行也立即返回,未再读取。
因此,可使用 getline()
,它与 get()
类似,但会读取并丢弃分隔符(换行):
int main()
{
char strBuf[11]{};
std::cin.getline(strBuf, 11);
std::cout << strBuf << '\n';
std::cin.getline(strBuf, 11);
std::cout << strBuf << '\n';
return 0;
}
此代码行为符合预期,即使输入中含换行。
若需知道 getline()
上次读取了多少字符,可使用 gcount()
:
int main()
{
char strBuf[100]{};
std::cin.getline(strBuf, 100);
std::cout << strBuf << '\n';
std::cout << std::cin.gcount() << " characters were read" << '\n';
return 0;
}
gcount()
包含被提取且丢弃的分隔符。
std::string
专属 getline()
头文件 <string>
提供了非成员 getline()
,用于读取 std::string
:
#include <string>
#include <iostream>
int main()
{
std::string strBuf{};
std::getline(std::cin, strBuf);
std::cout << strBuf << '\n';
return 0;
}
更多有用的 istream
函数
ignore()
:丢弃流中第一个字符。ignore(int nCount)
:丢弃前nCount
个字符。peek()
:预览下一个字符但不提取。unget()
:将最后读取的字符放回流中,供下次读取。putback(char ch)
:将指定字符放回流中,供下次读取。
istream
还包含许多其他函数及其变体,具体需求可查阅参考网站,如 cppreference.com。