簡體   English   中英

為c中的數組動態分配內存時的停止條件

[英]stop condition when dynamically allocating memory for an array in c

我從輸入中獲取一個數組,當沒有更多內存時,我分配更多(我不能使用 realloc)。 我的問題是我不知道該將什么作為循環的停止條件。 我希望它在我按下 Enter 時停止輸入,但它只是等待更多。(我應該使用 scanf)

我的代碼:

#include<stdio.h>
#include<stdlib.h>
#define CHUNK 5
int main()
{
    int *arr, allocate_size=0, i, j, k, temp=0, *p, len=0;
    printf("Enter array: ");
    for(i=0,j=0;temp!='\n';i++){
        if(i>=allocate_size){
            allocate_size+= ((++j)*CHUNK);
            p = (int*)malloc(sizeof(int)*allocate_size);
            if(p==NULL){
                printf("Error");
                return 1;
            }
            for(k=0;k<i && i!=0;k++){ /*copying array*/
                p[k]=arr[k];
            }
            free(arr);
            arr = p;
        }
        if(!scanf(" %d", &temp)){
            printf("Invalid input");
            return 1;
        }
        if(temp!='\n'){
            arr[i] = temp;
            len++;
        }
    }
    printf("length is %d\n", len);
    for(i=0;i<len;i++){
        printf("%d",arr[i]);
    }
    return 0;
} 

獲取用戶輸入的首選方法是使用fgets()或 POSIX getline()一次讀取整行輸入。 這樣做的原因是每次讀取都會消耗整行輸入,並且stdin中剩余的內容不依賴於使用的scanf轉換說明符 它還消除了必須記住哪些轉換說明符消耗了前導空格以及哪些不消耗並消除了匹配失敗時留在stdin字符的stdin

它還提供了便利,可以檢查緩沖區中用於保存輸入的第一個字符是否為'\\n'告訴您僅按下Enter鍵而沒有任何其他輸入。

要將fgets()sscanf()的使用合並到您的代碼中,只需聲明一個緩沖區來保存一行用戶輸入,足以滿足用戶可能輸入的任何內容(或者如果貓踩到鍵盤會產生什么結果)——不要t 節省緩沖區大小。 然后使用fgets()將輸入讀入緩沖區並檢查第一個字符是否為'\\n'以確定是否單獨按下Enter

你可以這樣做:

int main()
{
    char buf[256];
    ...
        if (!fgets (buf, sizeof buf, stdin)) {  /* read line of input/validate */
            fputs ("(user canceled input)\n", stderr);
            return 1;
        }
        if (buf[0] == '\n')     /* break loop on [Enter] alone */
            break;
        if (sscanf (buf, "%d", &temp) != 1) {
            fputs ("error: invalid integer input.\n", stderr);
            return 1;
        }
    ...

注意:檢查sscanf (buf, "%d", &temp) != 1將捕獲手動生成的EOF如果用戶按下Ctrl+d (或 Windows 上的Ctrl+z ),其中!sscanf(buf, " %d", &temp)不會)

仔細檢查一下,如果您還有其他問題,請告訴我。


編輯每條評論

由於在您的問題中您指出您必須為每個整數讀取動態分配,但您不能使用realloc來調整數組的大小,因此雙指針arrp的唯一邏輯假設是您應該通過為每個分配存儲來手動實現realloc時間與p ,通過從arr = p;賦值保存指向已分配塊的指針arr = p; 在每次迭代結束時,您可以從arr復制到您在下一次迭代中分配的新p ,然后在分配arr = p;之前釋放arr arr = p; 再次防止內存泄漏

將上述解決方案與您發布的代碼放在一起,您可以執行類似於以下操作:

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

#define CHUNK  5
#define MAXC 256

int main (void)
{
    char buf[MAXC] = "";        /* buffer to hold each line */
    int *arr = NULL,            /* pointer to block holding final array */
        *p = NULL,              /* temp pointer to allocate for each number */
        allocate_size = 0,      /* tracks length of array */
        temp = 0;               /* temp value for integer conversion */

    printf ("Enter %d elements of array:\n\n  arr[%d]: ", CHUNK, allocate_size);

    while (fgets (buf, MAXC, stdin)) {  /* read user input into buf */
        int rtn;                        /* variable to hold sscanf return */

        if (*buf == '\n')               /* check if ENTER alone */
            break;                      /* break loop if so */

        /* use sscanf to convert to int, saving return */
        if ((rtn = sscanf (buf, "%d", &temp)) == 1) {
            /* allocate new storage for allocate_size + 1 integers */
            if (!(p = malloc ((allocate_size + 1) * sizeof *p))) {
                perror ("malloc-p");
                break;
            }
            for (int i = 0; i < allocate_size; i++) /* copy arr to p */
                p[i] = arr[i];
            p[allocate_size++] = temp;  /* add new element at end */

            free (arr);                 /* free old block of memory */
            arr = p;                    /* assign new block to arr */
        }
        else if (rtn == EOF) {  /* manual EOF generated */
            fputs ("(user canceled input)\n", stderr);
            break;
        }
        else {  /* not an integer value */
            fputs ("error: invalid integer input.\n", stderr);
        }

        if (allocate_size < CHUNK)  /* if arr not full, prompt for next */
            printf ("  arr[%d]: ", allocate_size);
        else
            break;                  /* done */
    }

    /* output results */
    printf ("\nlength is %d\n", allocate_size);
    for (int i = 0; i < allocate_size; i++)
        printf (" %d", arr[i]);
    putchar ('\n');

    free (arr);     /* don't forget to free what you allocate */
}

示例使用/輸出

沒有停止或錯誤:

$ ./bin/arrnorealloc
Enter 5 elements of array:

  arr[0]: 10
  arr[1]: 20
  arr[2]: 30
  arr[3]: 40
  arr[4]: 50

length is 5
 10 20 30 40 50

提前停止:

$ ./bin/arrnorealloc
Enter 5 elements of array:

  arr[0]: 10
  arr[1]: 20
  arr[2]:

length is 2
 10 20

處理用戶錯誤:

$ ./bin/arrnorealloc
Enter 5 elements of array:

  arr[0]: 10
  arr[1]: 20
  arr[2]: dogs
error: invalid integer input.
  arr[2]: 30
  arr[3]: fish
error: invalid integer input.
  arr[3]: 40
  arr[4]: 50

length is 5
 10 20 30 40 50

內存使用/錯誤檢查

最重要的是在動態分配內存時,錯誤檢查:

$ valgrind ./bin/arrnorealloc
==5555== Memcheck, a memory error detector
==5555== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==5555== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==5555== Command: ./bin/arrnorealloc
==5555==
Enter 5 elements of array:

  arr[0]: 10
  arr[1]: 20
  arr[2]: 30
  arr[3]: 40
  arr[4]: 50

length is 5
 10 20 30 40 50
==5555==
==5555== HEAP SUMMARY:
==5555==     in use at exit: 0 bytes in 0 blocks
==5555==   total heap usage: 7 allocs, 7 frees, 2,108 bytes allocated
==5555==
==5555== All heap blocks were freed -- no leaks are possible
==5555==
==5555== For counts of detected and suppressed errors, rerun with: -v
==5555== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

始終確認您已釋放所有分配的內存並且沒有內存錯誤。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM