1. C-風格字符串輸入
1.1 scanf
使用 scanf
可以輸入不帶空格的字符串。
char str[100];
scanf("%s", str);
printf("%s\n", str);
輸入: Hello World
輸入: Hello
scanf
遇到空格後就會停止讀入,餘下的部分自動留在緩衝區內。
char str[100];
int i = 1;
while (~scanf("%s", str))
printf("String %d: %s\n", i++, str);
輸入:
Hello World, Everyone!
輸入上面一行內容,按下回車鍵後,會一次性輸出三行內容。
輸出:
String 1: Hello
String 2: World,
String 3: Everyone!
1.2 gets
/fgets
gets
char* gets(char*buffer)
從鍵盤上輸入字符,直至接受到換行符或 EOF 時停止,並將讀取的結果存放在 buffer
指針所指向的字符數組中。讀入完成後自動在 buffer
末尾添加 \0
。
注意,即使最後讀取到了 \n
符號,也不會把它放入到 buffer
末尾。
返回值爲 buffer
,如果 EOF 了,返回 NULL
。
char str[100];
int i = 1;
while (gets(str))
printf("String %d: %s\n", i++, str);
輸入輸出:
Hello World! My friend.
String 1: Hello World! My friend.
Support Vector Machine
String 2: Support Vector Machine
注意到 str
末尾是沒有換行符的,gets
把換行符丟棄了!
fgets
gets
在新的 C 標準中被廢棄了,原因在於它是不安全的,可以用 fgets
替代。
char * fgets ( char * str, int num, FILE * stream );
需要在 num
參數處指定限制字符數量,然後在 stream
處指定輸入流。
fgets
和 gets
有一個重要的不同。那就是它會保留輸入中的換行符。
const int MAX_LEN = 20;
char str[MAX_LEN];
int i = 1;
//注意,換行符會被保留
while (fgets(str, MAX_LEN, stdin))
printf("String %d: %s|\n", i++, str);
輸入輸出:
Hello World!
String 1: Hello World!
|
I am a boy!
String 2: I am a boy!
|
^Z
終端將被任務重用,按任意鍵關閉。
1.3 cin >>
1.1.1 使用方式
char sz[20];
cin >> sz;
1.1.2 細節知識點
用 cin
讀取時,它會將回車鍵生成的換行符保留在緩衝區中。
這點很重要,與之後 getline()
和 get()
函數出現的問題有關。
1.1.3 存在的問題
引例
char sz[20];
char str[20];
cin >> sz;
cin >> str;
cout << sz << endl;
cout << str << endl;
輸入
hello world //按回車鍵
輸出
hello
world
原因
cin
使用空白符號來確定字符串結束的位置,這意味着字符數組在輸入時一次只讀入一個單詞。
cin
將該單詞放入數組之中,自動添加空字符,而輸入的其餘內容則留在緩衝區中。
1.4 cin.getline()
1.2.1 使用方式
istream &getline(char *buffer, streamsize num);
istream &getline(char *buffer, streamsize num, char delim);
getline()
函數用於輸入流,讀取字符到 buffer 中,直到下列情況發生:
- num - 1個字符已經讀入,
- 碰到一個換行標誌,
- 碰到一個EOF,
- 任意地讀入,直到讀到字符delim。delim字符不會被放入buffer中。
樣例
char sz[20];
char str[20];
cin.getline(sz, 20);
cin.getline(str, 20);
cout << sz;//注意沒有endl
cout << str << endl;
輸入
hello world //按回車鍵
here //按回車鍵
輸出
hello worldhere
//endl空行
1.2.2 細節知識點
- 若參數num爲n,則最多讀入n-1個字符。
getline()
函數每次讀取一行。它通過換行符確定行尾,但不會將換行符留在緩衝區中,而是將換行符用空字符替換保留在字符串中。
以上面的例子爲例,在輸入hello world之後按下了回車鍵。
hello world //回車鍵
但輸出時並沒有空行。
hello worldhere//沒有空行
空行
1.2.3 存在的問題
讀入空行
引例
對一下程序
char sz[10];
char str[20];
cin >> sz;
cin.getline(str, 20);
cout << "sz: " << sz << endl;
cout << "str: " << str << endl;
return 0;
首先以一個輸入方式爲例。
- 不會出錯的輸入
her name//按回車鍵
輸出
her
name//注意前面的空格
cin
在讀到her
後面的空格後結束,並且將空位符留在緩衝區中,由下一個字符串讀取。
由此我們可以引出一個常見的錯誤
- 會出錯的輸入
her//按回車鍵
//無法輸入下一個字符串,直接輸出
輸出
her
這是由於cin
將回車鍵產生的換行符留在緩衝區內所以直接被str
讀取。 所以str
注意,
cin >>
與cin.getline()
連用要小心
而對於cicin.getline()
的連用,由於該函數不會將換行符留在緩衝區中,因此連用時沒有讀取空行的擔憂。
也就是說
//這是可行的
cin.getline(sz, 20);
cin.getline(str, 20);
解決辦法
cin >> sz;
//法一
cin.get();
//法二,ignore()默認忽略eof標識前一個字符
cin.ignore();
字數超長問題
如果輸入行包含的字符比指定的字符數多,getline()
會將剩餘的字符留在緩衝區中,然後設置失效位,並關閉輸入。
1.5 cin.get()
1.3.1 使用方式
原型
int get();
istream &get( char &ch );
istream &get( char *buffer, streamsize num );
istream &get( char *buffer, streamsize num, char delim );
istream &get( streambuf &buffer );
istream &get( streambuf &buffer, char delim );
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
的技巧
int main()
{
string line;
ifstream in;
//每次讀取一個單詞,直到文件末尾
while (in >> word)
{
cout << word << endl;
}
return 0;
}
2.2 getline()
2.2.1 原型
istream& getline (istream& is, string& str, char delim);
istream& getline (istream&& is, string& str, char delim);
istream& getline (istream& is, string& str);
istream& getline (istream&& is, string& str);
2.2.2 使用方法
同上,遇到換行符爲止(delim
),但是終止字符delim
(默認爲換行符)並不會留在緩衝區中留給下一位來讀取,而是變成了空字符留在了字符串中,不影響輸出。(可以當作被丟棄了)
2.2.3 例子
有文件a.txt
:
Iam a boy
Helloaworld
程序如下:
int main()
{
ifstream fin("a.txt");
string str;
//每次讀取一段文字,直到文件末尾EOF
while (getline(fin, str, 'a'))
{
cout << str << endl;
}
system("pause");
return 0;
}
輸出結果:
I//遇到了a停止讀入
m//字符a沒有被讀入下一個str
boy //遇到了a停止讀入,但空格被下一個str讀入了
Hello
world