1. C-风格字符串输入
1.1 scanf
使用 scanf
可以输入不带空格的字符串。
1 | char str[100]; |
输入: Hello World
输入: Hello
scanf
遇到空格后就会停止读入,余下的部分自动留在缓冲区内。
1 | char str[100]; |
输入:
Hello World, Everyone!
输入上面一行内容,按下回车键后,会一次性输出三行内容。
输出:
String 1: Hello
String 2: World,
String 3: Everyone!
1.2 gets
/fgets
gets
1 | char* gets(char*buffer) |
从键盘上输入字符,直至接受到换行符或 EOF 时停止,并将读取的结果存放在 buffer
指针所指向的字符数组中。读入完成后自动在 buffer
末尾添加 \0
。
注意,即使最后读取到了 \n
符号,也不会把它放入到 buffer
末尾。
返回值为 buffer
,如果 EOF 了,返回 NULL
。
1 | char str[100]; |
输入输出: 1
2
3
4Hello World! My friend.
String 1: Hello World! My friend.
Support Vector Machine
String 2: Support Vector Machine
注意到 str
末尾是没有换行符的,gets
把换行符丢弃了!
fgets
gets
在新的 C 标准中被废弃了,原因在于它是不安全的,可以用 fgets
替代。
1 | char * fgets ( char * str, int num, FILE * stream ); |
需要在 num
参数处指定限制字符数量,然后在 stream
处指定输入流。
fgets
和 gets
有一个重要的不同。那就是它会保留输入中的换行符。
1 | const int MAX_LEN = 20; |
输入输出: 1
2
3
4
5
6
7
8
9Hello World!
String 1: Hello World!
|
I am a boy!
String 2: I am a boy!
|
^Z
终端将被任务重用,按任意键关闭。
1.3 cin >>
1.1.1 使用方式
1 | char sz[20]; |
1.1.2 细节知识点
用 cin
读取时,它会将回车键生成的换行符保留在缓冲区中。
这点很重要,与之后 getline()
和 get()
函数出现的问题有关。
1.1.3 存在的问题
引例
1 | char sz[20]; |
输入
1 | hello world //按回车键 |
输出
1 | hello |
原因
cin
使用空白符号来确定字符串结束的位置,这意味着字符数组在输入时一次只读入一个单词。
cin
将该单词放入数组之中,自动添加空字符,而输入的其余内容则留在缓冲区中。
1.4 cin.getline()
1.2.1 使用方式
1 | istream &getline(char *buffer, streamsize num); |
getline()
函数用于输入流,读取字符到 buffer 中,直到下列情况发生:
- num - 1个字符已经读入,
- 碰到一个换行标志,
- 碰到一个EOF,
- 任意地读入,直到读到字符delim。delim字符不会被放入buffer中。
样例
1 | char sz[20]; |
输入
1 | hello world //按回车键 |
输出
1 | hello worldhere |
1.2.2 细节知识点
- 若参数num为n,则最多读入n-1个字符。
getline()
函数每次读取一行。它通过换行符确定行尾,但不会将换行符留在缓冲区中,而是将换行符用空字符替换保留在字符串中。
以上面的例子为例,在输入hello world之后按下了回车键。
hello world //回车键
但输出时并没有空行。
1 | hello worldhere//没有空行 |
1.2.3 存在的问题
读入空行
引例
对一下程序 1
2
3
4
5
6
7char sz[10];
char str[20];
cin >> sz;
cin.getline(str, 20);
cout << "sz: " << sz << endl;
cout << "str: " << str << endl;
return 0;
首先以一个输入方式为例。
- 不会出错的输入
1
her name//按回车键
输出 1
2her
name//注意前面的空格
cin
在读到her
后面的空格后结束,并且将空位符留在缓冲区中,由下一个字符串读取。
由此我们可以引出一个常见的错误
- 会出错的输入
1
2her//按回车键
//无法输入下一个字符串,直接输出
输出 1
her
这是由于cin
将回车键产生的换行符留在缓冲区内所以直接被str
读取。 所以str
注意,
cin >>
与cin.getline()
连用要小心
而对于cicin.getline()
的连用,由于该函数不会将换行符留在缓冲区中,因此连用时没有读取空行的担忧。
也就是说 1
2
3//这是可行的
cin.getline(sz, 20);
cin.getline(str, 20);
解决办法
1 | cin >> sz; |
字数超长问题
如果输入行包含的字符比指定的字符数多,getline()
会将剩余的字符留在缓冲区中,然后设置失效位,并关闭输入。
1.5 cin.get()
1.3.1 使用方式
原型
1 | int get(); |
get()函数被用于输入流,和以下这些:
- 读入一个字符并返回它的值,
- 读入一个字符并把它存储在ch,
- 读取字符到buffer直到num - 1个字符被读入, 或者碰到EOF或换行标志,
- 读取字符到buffer直到已读入num - 1 个字符,或者碰到EOF或delim(delim直到下一次不会被读取),
- 读取字符到buffer中,直到碰到换行或EOF,
- 读取字符到buffer中,直到碰到换行,EOF或delim。(相反, delim直到下一个get()不会被读取 ).
1.3.2 细节问题
2. string
输入
2.1 cin >>
2.1.2 使用方法
同上,一次只能读取一个单词。
注意这里读取时利用while
的技巧 1
2
3
4
5
6
7
8
9
10
11int main()
{
string line;
ifstream in;
//每次读取一个单词,直到文件末尾
while (in >> word)
{
cout << word << endl;
}
return 0;
}
2.2 getline()
2.2.1 原型
1 | istream& getline (istream& is, string& str, char delim); |
2.2.2 使用方法
同上,遇到换行符为止(delim
),但是终止字符delim
(默认为换行符)并不会留在缓冲区中留给下一位来读取,而是变成了空字符留在了字符串中,不影响输出。(可以当作被丢弃了)
2.2.3 例子
有文件a.txt
:
Iam a boy
Helloaworld
程序如下: 1
2
3
4
5
6
7
8
9
10
11
12int main()
{
ifstream fin("a.txt");
string str;
//每次读取一段文字,直到文件末尾EOF
while (getline(fin, str, 'a'))
{
cout << str << endl;
}
system("pause");
return 0;
}
输出结果:
1 | I//遇到了a停止读入 |