2016-03-18 150 views
0

我試圖做一個簡單的程序,使用scanf將標準輸入中的字符串讀入並放入字符串數組中(現在我只是使用它進行測試3個單詞,因此最後只有3個打印語句)。我能夠繼續閱讀,直到沒有更多的字符串,但是我遇到了一個錯誤,在循環完成後,數組中的所有字符串都是最後一個讀入的字符串。我試着把一個print語句放在循環進行調試,並且正在讀取正確的字符串。但是,當循環結束時,數組中的所有字符串都是最後一個讀入的字符串。有誰能指出我在哪裏出錯嗎?謝謝。使用scanf將字符串讀取到字符串數組中

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



int main(void) { 
    int c = 0; 
    char** w_arr = malloc(3*sizeof(char*)); 
    char* w = malloc(10*sizeof(char)); 

    while (scanf("%s", w) == 1) { 
     w_arr[c] = w; 
     //printf("%s", w_arr[c]); debug print statement 
     c++; 
    } 

    printf("%s, %s, %s\n", w_arr[0], w_arr[1], w_arr[2]); 
    return 0; 
} 
+0

您需要'malloc'一個新的'w'緩衝每'scanf'(或得到一個新的緩衝液如某種其他方式'w_arr並[c] =的strdup(W)')。就像這樣,所有數組條目都指向同一個緩衝區,其內容被每個scanf所覆蓋。 – kaylum

+0

啊。對不起,我是新來的c。所以基本上,我所有的數組中的條目都不是指向一個字符串,而是指向一個指針。所以當循環完成時,它們都指向相同的指針,這是最後一個字符串的地址? – PCR

+0

@PCR它不是「字符串的地址」 - 它是內存中某個空間的地址。然後你讀入該空間的第一個字符串,並使'w_arr [0]指向該空間。然後你讀第二個字符串進入該空間,並讓'w_arr [1]'指向那個空間。然後你讀入第三個字符串,並使'w_arr [2]'指向那個空間。最終結果是'w_arr [0]','w_arr [1]'和'w_arr [2]'都指向該空間,並且該空間包含第三個字符串(因爲您覆蓋了前兩個字符)。 – immibis

回答

1

您正在爲每個w_arr元素重複使用w(即它們都指向相同的位置)。您需要分配爲每個字符串

變化:

w_arr[c] = w; 

要:

w_arr[c] = strdup(w); 
+0

1)strdup()不是標準C. 2)如果OP在Linux上會發生什麼? – Michi

+0

@Michi strdup符合POSIX 1003.1標準。自1980年以來,POSIX [來自IEEE]和ISO已經並行運行。大約20年前,ISO失去了對「libc規範」的控制。大多數libc堅持POSIX而不是ISO。至於linux,strdup工作正常 –

0
w_arr[c] = w; 

至於w_arr[c]w,其在環的末端內容是最後一次讀取串,讓您得到最後打印的字符串。

您在w_arr分配內存以每個指針 -

char** w_arr = malloc(3*sizeof(char*));  //allocated memory for 3 char * 

while (scanf("%s", w) == 1 && c<3) { 
     w_arr[c]=malloc(10*sizeof(**w_arr)); // allocate memory to each char * 
     strcpy(w_arr,w);      //copy string 
    //printf("%s", w_arr[c]); debug print statement 
     c++; 
} 

,然後閱讀後使用strcpy -

注意 - 改變你的scanfwhile (scanf("%9s", w) == 1) {以免高於所需的字符越來越w

1

聲明

w_arr[c] = w; 

可以確保w_arr點的所有元素的相同的指針,w。在while循環結束後,在w處保存的數據是所讀取的最後一個輸入。因此,您會看到w_arr的所有元素都有相同的輸出。

我可以想出幾種方法來解決這個問題。

  1. 使用strdup分配給w_arr[c]

    w_arr[c] = strdup(w); 
    

    時如果strdup不可用你的平臺上,這是很容易實現的。

    char* strdup(char const* in) 
    { 
        char* ret = malloc(strlen(in)+1); 
        strcpy(ret, in); 
        return ret; 
    } 
    
  2. while環爲第二分配內存爲w,第三等輸入。

    而不是

    char* w = malloc(10*sizeof(char)); 
    while (scanf("%s", w) == 1) { 
        w_arr[c] = w; 
        //printf("%s", w_arr[c]); debug print statement 
        c++; 
    } 
    

    使用

    char* w = malloc(10*sizeof(char)); 
    while (scanf("%s", w) == 1) { 
        w_arr[c] = w; 
        //printf("%s", w_arr[c]); debug print statement 
        c++; 
        w = malloc(10*sizeof(char)); 
    } 
    

確保添加通話功能月底前解除分配mmory。

free(w); 
    for (int i = 0; i < 3; ++i) 
     free(w_arr[i]); 
+0

「分配給w_arr [c]時使用strdup」如果OP在Linux上,strdup()將無濟於事。 – Michi

0

你最好使用strdup和包括string.h

w_arr[c] = w; 

要:

w_arr[c] = strdup(w); 

而且strcpy是不是安全,你最好使用strncpy代替;

+0

strdup()不是標準C. OP沒有提到他是否在windows上。如果他在Linux上,這個答案不會幫助他解決問題。 – Michi

1

您正在將w_arr的每個元素設置爲僅分配一次的單個緩衝區w

printf("Addresses of strings: %p, %p, %p\n", w_arr[0], w_arr[1], w_arr[2]); 

您會看到類似以下的輸出:你可以通過你的循環後,加入這一行看到打印出的w_arr內容

[[email protected] tmp]$ ./strings 
123 
456 
789 
Addresses of strings: 0x1b0b030, 0x1b0b030, 0x1b0b030 <-- Same address! 
Contents of strings: 789, 789, 789 

正如你所看到的每一個元素w_arr指向內存中的相同地址。要解決這個問題,您需要每次分配w,然後將新的字符數組分配給w_arr。

#define NUM_OF_STRINGS 3 
#define MAX_CHARS  10 

int main(void) { 
    char** w_arr = malloc(NUM_OF_STRINGS * sizeof(char*)); 

    for (int i = 0; i < NUM_OF_STRINGS; ++i) { 
     w_arr[i] = malloc(MAX_CHARS * sizeof(char)); // allocate a new buffer for each element in w_arr 
     scanf("%s", w_arr[i]); 
    } 

    printf("%s, %s, %s\n", w_arr[0], w_arr[1], w_arr[2]); 
    return 0; 
} 
相關問題