【C/C++】如何帥氣地在C/C++中輸入字符串

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 處指定輸入流。

fgetsgets 有一個重要的不同。那就是它會保留輸入中的換行符

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 細節知識點

  1. 若參數num爲n,則最多讀入n-1個字符。
  2. 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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章