簡體   English   中英

C中的可變大小的數組和數組指針

[英]Variable sized arrays and array pointer in C

我正在HackerRank中進行編碼練習。 在C ++的Variable Sized Arrays練習中,我嘗試用C做,但我無法做到。

我的代碼有時會傳遞簡單的測試用例0,但有時不會。 代碼完全相同,但出現了不同的答案。

int main() {
    /* Enter your code here. Read input from STDIN. Print output to STDOUT */

    int n, q;
    scanf("%d%d", &n, &q);

    int *p_arr[n];

    if (n > 0) {
        for (int i = 0; i <  n; i++) {
            int tmp;
            scanf("%d", &tmp);

            int tmp_arr[tmp];
            p_arr[i] = tmp_arr;
            for (int j = 0; j < tmp; j++) {
                int value;
                scanf("%d", &value);
                p_arr[i][j] = value;
                printf("%d ", p_arr[i][j]);
            }
            printf("\n");
        }
    }

    if (q > 0) {
        for (int i = 0; i < q; i++) {
            int row, col;
            scanf("%d%d", &row, &col);
            printf ("%d %d\n", row, col);
            int answer = p_arr[row][col];
            printf("%d\n", answer);

        }
    }
    return 0;

}

這是我得到的錯誤答案

1 5 4 

1 2 8 9 3 

0 1

21973

1 3

32764

我不知道2197332764來自哪里。

這是我預期的答案

1 5 4 

1 2 8 9 3 

0 1

5

1 3

9

有時我得到了錯誤的答案,有時我得到了正確的答案。 那是為什么? 非常感謝!

繼續注釋,如果練習涉及可變長度數組,那么它應該用C語言編寫,因為C ++標准不提供VLA(並且在添加C99后它們在C11中開始是可選的)

代碼的主要問題(除了完全分配輸入失敗之外)是它調用Undefined Behavior,因為int tmp_arr[tmp]for循環結束時超出了范圍。 p_arr[i] = tmp_arr;分配的p_arr[i] = tmp_arr; 循環外不再存在因為tmp_arr不再存在。 超出范圍后訪問值的任何嘗試都會調用未定義的行為 ,請參閱未定義,未指定和實現定義的行為

每次處理輸入時,必須驗證輸入是否成功,並且獲得的值是否在有效范圍內。 例如, nq必須是正值。 使用scanf你可以做到(最低限度)

    if (scanf("%d%d", &n, &q) != 2 || n <= 0 || q <= 0) {
        fputs ("error: invalid format or value.\n", stderr);
        return 1;
    }

以上驗證了收到2個輸入並且兩者都是正值。

為了保留用p_arr[i] = tmp_arr;分配的指針p_arr[i] = tmp_arr; tmp_arr必須是一個已分配的類型來處理一個未知的tmp數量的元素,或者它必須在循環外聲明(並且足夠大以處理所有預期值 - 假設tmp被讀作輸入 - 看起來不像預期的方法)。 你不能聲明tmp_arr靜態無論是作為只會有一個實例,並反復分配給它p_arr[i]會留下的所有元素p_arr[i]指向同一個地方。

只需為tmp_arr分配,然后對p_arr[i]的賦值將在程序的生命周期中存活或直到它被釋放,例如

        int *tmp_arr = calloc (tmp, sizeof *tmp_arr);   /* allocate */
        if (!tmp_arr) {                 /* validate every allocation */
            perror ("calloc-tmp_arr");
            return 1;
        }
        p_arr[i] = tmp_arr;

注: calloc上面用作零新分配的內存可以使用。 malloc ,而不是因為代碼分配給每個元素)

完全放入並添加(最小)驗證,您可以執行類似於以下操作:

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

int main (void) {

    int n, q;   /* validate EVERY input */
    if (scanf("%d%d", &n, &q) != 2 || n <= 0 || q <= 0) {
        fputs ("error: invalid format or value.\n", stderr);
        return 1;
    }

    int *p_arr[n];  /* array of n-pointers to int */

    for (int i = 0; i < n; i++) {
        int tmp;
        if (scanf("%d", &tmp) != 1 || tmp <= 0) {   /* validate! */
            fputs ("error: invalid input - tmp.\n", stderr);
            return 1;
        }

        int *tmp_arr = calloc (tmp, sizeof *tmp_arr);   /* allocate */
        if (!tmp_arr) {                 /* validate every allocation */
            perror ("calloc-tmp_arr");
            return 1;
        }
        p_arr[i] = tmp_arr;
        for (int j = 0; j < tmp; j++) {
            int value;
            if (scanf("%d", &value) != 1) {     /* validate! */
                fputs ("error: invalid input - value.\n", stderr);
                return 1;
            }
            p_arr[i][j] = value;
            printf ("%d ", p_arr[i][j]);
        }
        putchar ('\n');     /* no need to printf a single-character */
    }

    for (int i = 0; i < q; i++) {
        int row, col;   /* validate! */
        if (scanf ("%d%d", &row, &col) != 2 || row < 0 || col < 0) {
            fputs ("error: invalid input, row or col.\n", stderr);
            return 1;
        }
        printf ("%d %d\n%d\n", row, col, p_arr[row][col]);
    }

    for (int i = 0; i < n; i++)
        free (p_arr[i]);

    return 0;
}

注意:未經測試,因為沒有提供hackerrank輸入)

仔細看看,如果您有其他問題,請告訴我。

暫無
暫無

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

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