九月份校招开始多了起来,很多公司都有笔试环节。而笔试的编程题很多都需要从标准输入输出流里面读取数据,这里就总结一下怎么从标准流读取字符串,同时也是给自己做个备忘录,免得时间长忘记了。
作用是: 从istream中读取至多n个字符(包含结束标记符)保存在s对应的数组中。即使还没读够n个字符,如果遇到delim 或 字数达到限制,则读取终止,delim都不会被保存进s对应的数组中。
#include<iostream>
char str[20];
std::cin.getline(str,20);
std::cout << str << std::endl;
在控制台输入123 456,回车,程序输出字符串str的值:123 456
用法和上第一种类似,但是形式上不一样,读取的istream是作为参数is传进函数的,读取的字符串保存在string类型的str中。
is:表示输入流,例如 cin,或者文件输入流 fstream。istream&是左值引用,istream&&是右值引用。
str:string类型的引用,用来存储输入流中的流信息。
delim:char类型的变量,所设置的截断字符,默认是’\n’。
#include<string>
string str;
getline(std::cin,str);
char str[20];
std::cin >> str;
std::cout << str << std::endl;
不管字符串前面有多少回车和空格,都会被忽略,在控制台输入多个空格后再输入12345,回车,程序输出字符串str的值:12345
但是如果字符串中间有空格或者制表符tab,则读取的内容会截断。例如在控制台输入123 456,回车,程序输出字符串str的值:123
如果想要读取包含空格或者tab等分隔符的一行字符串,可以使用cin.get函数。
char str[20];
std::cin.get(str,20);
std::cout << str << std::endl;
在控制台输入123 456,回车,程序输出字符串str的值:123 456
但是这个方法和cin.getline方法还是有区别的:
cin.get读取一行时,遇到换行符时结束读取,但是不对换行符进行处理,换行符仍然残留在输入缓冲区(cin>>方法也是如此)。cin.getline读取一行字符时,默认遇到’\n’时终止,并且将’\n’直接从输入缓冲区中删除掉,不会影响下面的输入处理。我们做个测试:
char str[20] ;
char s;
std::cin.get(str,20);
std::cin.get(s);
std::cout << str << std::endl;
std::cout << (int)s << std::endl;
还是在控制台输入123 456,回车,程序输出字符串str的值:123 456的同时,还输出了10,因为换行符的ASCII码是10。
所以使用cin>>和cin.get方法读取数据的时候一定要特别小心,因为最后的换行符还留在输入缓冲区里面。再看一个例子:
int num = 0;
std::cin >> num;
char strList[5][20];
for (int i = 0; i < num; i++) {
std::cin.getline(strList[i], 20);
}
for (int i = 0; i < num; i++) {
std::cout << strList[i] << std::endl;
}
我们从第一行读取一个数字n,代表有n个字符串,然后从控制台依次读取n个字符串,并将这n个字符串输出。如果输入:
3
Zhangsan
Lisi
Wangwu
本来应该输出:
Zhangsan
Lisi
Wangwu
但是结果如下图:
输入完第二个字符串并回车之后,就输出了结果,for循环里面不是应该读取3个字符串吗?
原来strList数组已经读取了三个字符串,只是数组里第一个字符串读取的是上一个cin>>num残存的换行符,因此内容为空。
要想实现原来的功能,只需对程序稍微修改一下:
int num = 0;
char c;
std::cin >> num;
cin.get(c);
char strList[5][20];
for (int i = 0; i < num; i++) {
std::cin.getline(strList[i], 20);
}
for (int i = 0; i < num; i++) {
std::cout << strList[i] << std::endl;
}