最近在跟一門北大C++程序設計的慕課,openjudge上做到一道題,要求定義一種能夠輸入輸出學生姓名,年齡,學號和學年成績的類。比較特別的是輸入的形式是以逗號隔開的一長串字符串。
我用的方法通過是通過了,但可能比較笨,主要使用getline獲取指定字符之前的字符串,使用強制轉換函數stoi()轉換成數字。
#include <iostream> #include <string> #include <cstdio> #include <cstring> #include <sstream> #include <cstdlib> using namespace std; class Student { private: string m_name, m_id; unsigned m_age; double m_av, n[4]; public: void input() { string ts = {}; getline(cin, m_name, ','); //從流中獲取姓名的字符串,遇到逗號結束 getline(cin, ts, ','); //從流中獲取年齡的字符串 m_age = stoi(ts); //強制轉化為整型賦給成員變量m_age getline(cin, m_id, ','); //從流中獲取學號的字符串,賦給成員變量m_id for (int i = 0; i < 3; i++) //獲取前三個學年的成績,同樣用強制轉換存值 { getline(cin, ts, ','); n[i] = stoi(ts); } getline(cin, ts, '\n'); //獲取最后一個學年的成績,遇到換行符結束 n[3] = stoi(ts); } void calculate() { m_av = (n[0] + n[1] + n[2] + n[3]) / 4; //計算四個學年成績的平均值 } void output() { cout << m_name << "," << m_age << "," << m_id << "," << m_av; } }; int main() { Student student; // 定義類的對象 student.input(); // 輸入數據 student.calculate(); // 計算平均成績 student.output(); // 輸出數據 system("pause"); return 0; }
這里總結一下我迄今使用的字符串輸入輸出的方式。
1.cin
cin會從流中取數據,遇到空格或者換行符都會停止,所以不適合讀數據串。一般用來取單個變量的數據。
int a; int b; cin >> a; cin >> b; cout << "a:" << a << endl; cout << "b:" << b << endl;
輸入:
2 3(回車)
或
2(回車) 3(回車)
輸出:
a:2 b:3
第一種輸入會把換行符之前,即“2+空格+3+\n”的數據都存入緩沖區。程序執行到cin>>a,去緩沖區取數據,碰到空格停止,所以就取走了一個2賦給了a,然后繼續執行cin>>b,此時緩沖區如果還殘留數據,程序會從緩沖區取數據而不是要求用戶輸入,所以重復相同的步驟取走了剩余的3。最后,留下一個換行符在緩沖區內。
2.cin.get()
cin.get()如果不加任何參數的話,只會每次從緩沖區取一個數據,同樣也會留下換行符。要注意的是,cin.get()遇到換行符就會停止,意思是緩沖區如果留有換行符,此時程序執行cin.get()會被直接跳過。cin.get()返回的值可以直接賦給變量。
int a; int b; a = cin.get(); b = cin.get(); cout << "a:" << a << endl; cout << "b:" << b << endl;
輸入:
abc(回車)
輸出:
a:97 b:98
發現cin.get()取的實際是單個字符,如果賦給整型的話就會轉化成對應的ASCII值。
再如:
char a, b; cin >> a; b = cin.get(); cout << "a:" << a << endl; cout << "b:" << b << endl;
輸入:
1(回車)
輸出:
a:1 b:
剛才說過cin>>a讀取了回車之前的數據給了a,但會緩沖區留下個換行符。然后cin.get()從緩沖區取數據,遇到換行符直接就跳過了,所以沒有提示用戶輸入,b沒有賦值。
如果不把cin.get()的返回值賦給誰,自成一句,那么cin.get()就可以用來清除掉緩沖區的字符。
如:
char a[10]; a[0] = cin.get(); a[1] = cin.get(); cin.get(); cin.get(); a[2] = cin.get(); cout << a[0] << a[1] << a[2] << endl;
輸入:
abcde
輸出:
abe
cd被推走了,所以只有abe賦了值。
利用這一特性,常留一句cin.get()清掉緩沖區殘留的換行符,或者無效的輸入。
cin.get()加參數的話,第一項填數據名,第二項填其長度,就可以給特定字符變量輸入字符串了。
如:
char a[10]; cin.get(a,10);
3.getline
getline可以給字符串string對象賦值,用法如下:
#include<iostream> #include<string> using namespace std; int main() { char str1[10]; string str2; cin.get(str1, 10); cin.get(); //清除換行符 getline(cin,str2); cout << "str1:" << str1 << endl; cout << "str2:" << str2 << endl; system("pause"); }
輸入:
abcd(回車)
hijk(回車)
輸出:
str1:abcd
str2:hijk
getline可以指定第三項參數,即遇到特定的字符停止,默認是‘\n’,可以手動寫成如‘,’,也就是我在上面例題程序里使用的。
值得注意的是將string轉換成int的函數 stoi() 還是挺有用的,需要包含頭文件<string>。
string str; int a ; cin >> str; a = stoi(str); cout << "a:" << a << endl;
輸入:
100(回車)
輸出:
a:100