2011-09-15 63 views
0
數據錄入和malloc的

我是新的C和我有一個小問題,我的代碼:問題在C

int i, n; 
int *arr; 
while(n != 0) { 
    scanf("%d", &n); 
    if(n == 0) 
     exit(1); 
    else { 
     arr = (int*) malloc(sizeof(int) * n); 
     for(i = 0; i < n; i++) 
      scanf("%d", &arr[i]); 
    } //end if 
} //end while 

我想要做的就是讓爲n的數組大小和欲停止閱讀時,我得到一個「0」,例如,如果我輸入:

3 
2 
2 
5 
2 
6 
7 
0 

我想尺寸3與值2,2,5的陣列,爲2的數組值6和7並退出,因爲0 *對不起,我忽略了一個重要的部分,我認爲...在我的代碼中調用一個calc(),我發送arr,右在scanf(「%d」,& arr [i])後,然後我會返回該值,然後如果下一個值例如2不是0我會讀取,創建一個新的數組,發送ARR,在控制檯上打印結果,如果下一個值爲0,則再次退出。 * 你們可以告訴我我錯了嗎?

+1

解釋您提交的代碼失敗的原因。在示例中輸入序列時不會退出嗎? –

+0

使用'break'語句而不是'exit'。這保證在while循環後執行任何其他代碼。 – Mahesh

回答

2

它在你的代碼是可見的問題是:
1.檢查在while未初始化的整數n。要解決此問題,請將n初始化爲非零或使用do{ ... } while()而不是while()
2.您需要驗證它是通過scanf讀取的n值。 mallocsize_t類型作爲unsigned int的參數。但n是整數可以接受負值,因此,如果輸入了負值它將作爲unsigned int傳遞給malloc,這可能導致不希望的結果(也for循環將執行次數不正確數量)。您也可以考慮從integer改變n類型unsigned int類型或改變出口條件if(n < 1)
3.程序中有內存泄漏。通過malloc分配的內存不會通過free釋放。
4.不要以爲malloc會一直成功。請通過NULL檢查即

if (NULL == arr) 
{ 
    //error handling 
} 

5. exit與非零值的malloc成功檢查通常表示異常終止。您可以使用breakreturnbreak可能是一個更好的主意,因爲它通常變得難以測試的功能在功能增加的出口點(雖然這可能不是你的情況屬實,但它是僅供參考)
6.或者,您可以檢查返回值爲scanf以確保輸入了有效的輸入。

幫助這有助於!

+0

感謝這幫助了我很多理解編程! :) –

3

你快到了!

您正在創建arr中的新陣列,但這是一個單指針,因此只能引用一塊內存。當你調用malloc時,新的內存被存儲在arr中,但舊的內存丟失。您正在「泄漏內存」,因爲機器保留了舊內存,但您沒有變量存儲它的地址,因此您無法再次找到它。

如果您只需要存儲最後一個列表,您應該在malloc創建新空間之前釋放舊內存(在arr中)。如果你需要存儲所有的數組,你將需要一個指向數組的指針。

編輯:
在分配新內存之前,您需要先釋放以前分配的內存。在第一組數據中,您沒有任何現有的'malloc',但釋放NULL指針總是安全的,因此只需在開始時將指針設置爲NULL即可。

提示:在定義它們時,將所有變量設置爲某個安全初始值總是一個好主意。

int *arr=NULL; // Mark this as pointing to no memory 

    .... 

free(arr); // first time it does nothing, afterwards it deletes the previous reserved memory 
arr = (int*) malloc(sizeof(int) * n); // as before this reserves some memory 
+0

我認爲它沒關係,因爲當我得到一個數組時,我可以調用一個我沒有添加的方法,然後在控制檯上打印該值。如果neXt值不是0,那麼我會再次調用該方法。所以我不認爲我需要一次記住所有數組......在這種情況下...我是否需要釋放(arr)? –

0

想必您以後可以訪問這些數組。

事實上,當你下一個(當然,如果它是一個更大的應用程序會導致內存泄漏),你將丟失指向前一個數組的指針。

您需要分配一個int *(一組int指針)的卡盤,然後將每個指針存儲在那裏int指針。

技巧是......如果你不知道你需要多少個數組,你需要你的代碼是動態的(例如;分配一些空間,然後分配更多,如果你用完)。

另一種選擇是,您可以限制用戶可以輸入的系列數量,並告訴他們在達到系列時已完成。

這裏的一些幫助,如果你想去後者路線:

int i; 
int n = 1; 
int **myArrayOfArrays = malloc(sizeof(int*) * 5); /* max of 5 arrays */ 

int *arr; 
int arrayCount = 0; 
while(n != 0) { 
    scanf("%d", &n); 
    if(n == 0) 
     break; 
    else { 
     if (arrayCount == 4) { 
      printf("Woah there partner! That's enough!\n"); 
      break; 
     } 
     else 
     { 
      arr = malloc(sizeof(int) * n); 
      for(i = 0; i < n; i++) 
       scanf("%d", &arr[i]); 
      myArrayOfArrays[arrayCount] = arr; 
      arrayCount++; 
     } 
    } //end if 
} //end while 

無論其...現在你不知道每個數組有多長。這是一個問題。您需要跟蹤這些信息,或者使用動態結構(如鏈接列表)。在下面的例子中,我們添加的長度每個陣列的第一個元素:

int main() 
{ 

    int i; 
    int n = 1; 
    int **myArrayOfArrays = malloc(sizeof(int*) * 5); 

    int *arr; 
    int arrayCount = 0; 
    while(n != 0) { 
     scanf("%d", &n); 
     if(n == 0) 
      break; 
     else { 
      if (arrayCount == 4) { 
       printf("Woah there partner! That's enough!\n"); 
       break; 
      } 
      else 
      { 
       arr = malloc(sizeof(int) * (n + 1)); /* one more than we need */ 
       arr[0] = n; /* store the array length in the first element */ 
       for(i = 1; i <= n; i++) 
        scanf("%d", &arr[i]); 
       myArrayOfArrays[arrayCount] = arr; 
       arrayCount++; 
      } 

     } //end if 
    } //end while 
    int j; 
    for (i = 0; i < arrayCount; i++) 
    { 
     int length = myArrayOfArrays[i][0]; /* retrieve the length */ 
     for (j = 1; j <= length; j++) 
      printf("%d ", myArrayOfArrays[i][j]); 
     printf("\n"); 
    } 
} 

動態使用數組分配/原始內存意味着你需要跟蹤的東西。更好的方法是使用鏈接列表來處理數據。在這種情況下,您可以有一個鏈接的節點列表,每個節點都包含一個整數鏈接列表。

0

你沒有初始化n,所以你可能會或可能不會進入您的while循環。開始n在-1是做一件合理的事:

int i, n = -1; 

你應該投的malloc的返回值,即可以隱藏的問題。

你也泄漏內存,因爲你不叫上free你從malloc回來,你失去跟蹤您的每一次讀到您分配一個新的價值arr。 Brian Roach和Martin Becket提到了這些事情。