1. 程式人生 > >scanf 和 cin 對string 的輸入 和坑點

scanf 和 cin 對string 的輸入 和坑點

寫這個源於 一道題 《1028 人口普查(20)(20 分)》

前言:在網路上 我常常會看見有人說 cin>>的效率慢 不如 scanf 。經過測試 的確是這樣子。既然cin>>輸入慢 為什麼還要用呢?拋開很多很多的問題比如:

1.cin>>可以對類似string 型別進行直接輸入。

2.cin>>可以自動轉換型別,不需要像scanf寫的那麼麻煩。

3.等等

// 實驗之前 先說下一些已知的結論 因為考慮到 可能有些人不願意看我實驗的內容,可能是因為我太水了吧。--哭~

1.  string使用 scanf進行輸入是這樣輸入的:

	string s;
	scanf("%s",&s[0]);
直接
scanf("%s",s); //無法完成賦值 賦值結束後字串 s 為空

2.使用scanf給 string 直接結構體賦值後 無法傳遞給 下一 string的變數。

struct sn {
	string t;
}K,P;

void solve() {

	string s;
	scanf("%s",&K.t[0]);
	P = K;
	s = K.t;
}

答案是:當K.t被正常賦值以後P.t 為空 s也為 空


造成這個原因的是 沒有加上 resize(num);這個函式 num是正整數 表示初始化string多少空間。 

    接下來不想講太多 我還要留一些下面講 , 不想看的 可以關掉頁面了。== (今天怎麼啦?)(不說。。~)

//


那麼問題來了 我如何使用 scanf()對string進行輸入呢?又有什麼不同的地方,適不適用 gets ?

這次主要做一個實驗:


實驗工具: VS2017 , codeblock 17,VC++6.0 不一定全部用上。因為我記得 2017裡是沒辦法使用 gets的 ,它提供了一個叫做gets_s的安全函式 一會也會進行測試。


一般情況之下 我們對 string 型別的變數賦值的時候會使用 cin>> 賦值 兩個string值之間可以 使用等於號進行賦值,這個是我們的常識:

比如:

string s,t;
cin>>s;
t = s;

那麼 string 型別的資料 在輸入後其實也可以像 char 型別的陣列一樣是一個連續的空間 那麼就是因為這個特性 才能用scanf進行輸入。那麼輸入的方法是:對空間的第一個元素所在的地址進行輸入。那麼我們早就知道對char 陣列 或是 char* 空間陣列的賦值方法是

char s1[900];
scanf("%s",s1);
scanf_s("%s",s1,sizeof(s1)); // 新版編譯器  OJ 不支援
gets(s1);
gets_s(s1,sizeof(s1)); // 新版編譯器        OJ 不支援

那麼我們推出 使用 scanf對 string 進行輸入的方法:

string s;
s.resize(10000);
scanf("%s", &s[0]);

有些人會說 s.resize(10000);這條語句我不加 也可以賦值成功啊~ 他們給我看的是這樣的情況(輸入NTSD)


賦值成功!! 但是 這是很危險的 我們使用更長的字串的時候就會賦值失敗 比如:


但是我們 啟用 resize 的話情況就會不一樣。如圖:


這樣才是正規的寫法,但是我們今天不僅研究這個。我們來看看賦值的操作吧。

 直接使用等號賦值的是成功的!!!那今天的實驗到此為止麼?不是 因為賦值成功還有特例 讓它賦值不成功

我們來看 那個最特殊的 特例 讓這種方法徹底失敗。當然也是犯了一個錯誤所導致的 resize(num); 

這個最特殊的特例就是 --- 結構體的整體賦值下。或是 結構體中的string賦值給區域性(全域性)變數下。


如果不加 resize(num);就會出現賦值失敗的問題。 


加上就會好了:

RT



由於 VS2017上沒有 gets 那麼我們使用 vc++6.0來看一下吧!gets也是能正常的賦值的。


然後我使用子函式 在VS2017上模擬了一下 gets 

int gets(char *s) {

	for (char t, *p = s; t = getchar(), s!=NULL&&t != '\n'; p++, *p = 0)
		*p = t;
	return s != NULL ? strlen(s) : 0;
}

也能成功賦值。我覺得這個也是一個替代方案吧 畢竟擺著 cin>>不用 用這個還是很多坑點的啊!!~~

本來想上一下反彙編的~~~但是我也不精反彙編 怕說錯被笑 哈哈~~


好好學習,天天向上,加油哦~