2013-05-29 59 views
1

我有一些代碼的問題C:奇怪的行爲scanf函數,字符串和C

char opt, name[10], path[25]; 
printf("Things\nMore things\n"); 
printf("Even more things\n"); 
printf("\nChar: "); 
scanf("\n%c",&opt); 
printf("\nTask name: "); 
scanf("%s",name); 
printf("Name: %s\n", name); 
printf("\nFolder name: "); 
scanf("%s",path); 
printf("Name: %s\n", name); 
printf("Path: %s\n", path); 

這是在做一個「乾淨」的模式故障代碼。問題在於,當數據的大小大於10或25時,則不是切割字符串,而是混合「名稱」和「路徑」。在某些情況下甚至會將「路徑」的一部分放入「名稱」中。這是不確定的行爲,還是我失去了一些東西?

+0

是的,寫過一個數組的末尾是*未定義的行爲*,如你所懷疑的。當數組已滿時,scanf沒有自動的「停止讀取」。它不知道數組的大小時怎麼可能?可以將格式更改爲例如'%10s'來解決這個問題,但規則是icky。閱讀您友好的scanf手冊頁! – Jens

+0

PS:換行符應該在printf字符串的* end *處,而不是在開頭;否則stdout流可能不會被刷新,您將等待提示。 (或添加fflush(stdout))。 – Jens

+0

這與使用(*)scanf系列中的函數時有關溢出的其他問題非常相似,例如http://stackoverflow.com/q/16593175/1281433。 –

回答

2

如果要限制用戶輸入字符的準確數量,儘量

scanf("%24s",path); 

應該防止緩衝區超載您的字符數組。

+0

謝謝你的解決方案,不完美,但足以達到我的目的! – markmb

0

它簡單地將名稱重載到路徑,因爲它們佔用彼此相鄰的內存中的空間。

1

當您嘗試寫入name以上的10個字符以及path中的25個字符以上時,導致緩衝區溢出。

在這種特殊情況下,namepath分配在堆棧上,pathname之後。但是由於堆疊是自上而下的,如果您在path中寫入更多,則可以寫入空間name

閱讀上維基百科Buffer overflow

1

如果你不希望有任何問題,更換你的琴絃scanf到:

fgets(name, 10, stdin); 

,其中第二個參數是你的數組的大小。這樣即使你試圖寫更多的字符,他們也會被忽略。

0

您應該指定最大規模使用scanf函數時避免緩衝區溢出閱讀:

scanf("%10s", name); 
1

scanf函數不知道你的變量的大小(尤其是字符串變量)。它只是把字節放在內存空間中,你必須自己檢查是否有溢出。

由於數據結構對齊,沒有段錯誤。

2

您需要告訴scanf您的輸入字符串可以佔用多少字節。您還需要告訴scanf放棄直至行尾的所有輸入。由於你的提示並沒有以換行符結束,你應該刷新輸出。

printf("\nChar: "); 
fflush(stdout); 
scanf("\n%c%*[^\n] ",&opt); 
printf("\nTask name: "); 
fflush(stdout); 
scanf(" %9[^\n]%*[^\n] ", name); 
printf("\nFolder name: "); 
fflush(stdout); 
scanf(" %24[^\n]%*[^\n] ", path); 
+0

這個解決方案有效,但按Enter鍵顯示輸入結束時會出現奇怪的現象,所以我會應用Pablo Lemurr發佈的解決方案,這對我的目的來說已經足夠了。謝謝! – markmb