2012-10-09 38 views
0

所以我不能真正弄清楚爲什麼scanf搞亂了一個[0]。當我打印出數組時,一個[0]是空的,我想要一個[0]它存儲在[1]中。使用scanf for循環與fgets返回一個[0]爲空

#include <stdio.h> 
#include <stdlib.h> 

int main(int argc, char *argv[]) 
{ 
    char *a[128]; 
    int i; 
    int num; 

    scanf("%d", &num); 

    for (i = 0; i < 2; i++) { 
     a[i] = malloc(50*sizeof(char)); 
     fgets(a[i], 100, stdin); 
    } 

    printf("[0] = %s [1] = %s", a[0], a[1]); 

    return 0; 
} 
+0

您的輸入是什麼? –

+0

說我輸入:1 [enter]這是一個字符串[enter] – user1455112

回答

3

scanf()搞亂你a[0],至少不是在你似乎認爲,通過某種方式破壞其存儲區域的方式。混合輸入的不同「方法」,這是一個非常重要的問題。

你的scanf/fgets組合實際發生的事情是,scanf獲取整數,但沒有讀取在該數字末尾輸入的換行符,因此第一個fgets選擇了這個。

ISO標準狀態它因而(在指定的序列中):

輸入的空白​​字符(由isspace爲函數指定)被跳過,除非本說明書中包括[,C或N中符。

從流中讀取輸入項目,除非規範包含n說明符。輸入項被定義爲輸入字符的最長序列,其不超過任何指定的字段寬度,並且是匹配輸入序列的或者是匹配輸入序列的前綴。

輸入項目保持未讀狀態後的第一個字符(如果有的話)。

第一段和最後一段很重要。第一種意思是跳過前導空格,最後意思是尾隨空格留在輸入流中以待稍後讀取。


不過,我會告訴你什麼可能搞砸了(根據您輸入線的長度),這是事實,你分配每個a[i] 50個字符空間,然後讀取最多100個字符進去。這就是未定義的行爲。


如果你想正確處理緩衝區的大小強大的輸入解決方案,檢測太長線,扔掉那些線的餘等見this answer

另外,如果你想模仿與非基於行的scanf線爲基礎的行爲(而你確定你的線總是小於100字節),你可以改變:

scanf("%d", &num); 

納入:

char junk[100]; 
scanf ("%d", &num); 
fgets (junk, sizeof (junk), stdin); 

因此它抓住並拋棄其餘的線。

而且您應確保fgets的最大大小參數與可用內存量相匹配(例如在上面的代碼中使用sizeof)。

另外一件事,請不要將代碼乘以sizeof(char) - 該值爲總是 1按照標準複雜化。