簡體   English   中英

在C中打印char數組時出現異常行為

[英]Unexpected behavior in printing a char array in C

最近,我在必須編寫的一段代碼中遇到了一個有趣的問題。 盡管我使用與原始版本不同的方法解決了該問題,但我想看看是否有人對原始版本無效的想法。 以下是簡明的代碼片段。

原始代碼:

int i, j, k;
for (i=0; i!=10, (result = fgets(newline, 1024, stream))!=NULL; i++)
{
    result = strtok(newline, " ");
    for (j=0; j!=x; j++) {
        for (k=0; k!=y; k++) {
            score_matrix[i][j][k] = result;
             printf("%d ", atoi(score_matrix[i][j][k]));
            result = strtok(NULL, " ");
        }
    }
     printf("\n");
}

在上面的代碼中,“ stream”是CSV文件。 無論如何,上面的代碼將打印出CSV文件,因為它應該是:

19 17 20 18 
9 6 10 9 
12 11 10 16 
3 7 9 10 
0 5 8 6 
15 13 15 15 
20 18 18 16 
17 19 19 18 
13 15 14 12 
10 13 18 15 

但是,當我使用與上面相同的代碼時,只刪除了幾行無關的代碼

int i, j, k;
for (i=0; i!=10; i++) {
    for (j=0; j!=x; j++) {
        for (k=0; k!=y; k++) {
            printf("%d ", atoi(score_matrix[i][j][k]));
        }
    }
    printf("\n");
}

它輸出:

10 13 18 15 
10 0 3 8 
10 13 18 15 
10 0 3 18 
10 0 3 18 
10 13 18 15 
10 13 18 15 
10 13 18 15 
10 13 18 15 
10 13 18 15 

這是非常錯誤的。 固定代碼 (只不過將矩陣轉換為int並刪除atoi ):

int i, j, k;
for (i=0; i!=10, (result = fgets(newline, 1024, stream))!=NULL; i++)
{
    result = strtok(newline, " ");
    for (j=0; j!=x; j++) {
        for (k=0; k!=y; k++) {
            score_matrix[i][j][k] = atoi(result);
            printf("%d ", score_matrix[i][j][k]);
            result = strtok(NULL, " ");
        }
    }
    printf("\n");
}

int i, j, k;
for (i=0; i!=10; i++) {
    for (j=0; j!=x; j++) {
        for (k=0; k!=y; k++) {
            printf("%d ", score_matrix[i][j][k]);
        }
    }
    printf("\n");
}

現在兩者都打印正確的東西:

19 17 20 18 
9 6 10 9 
12 11 10 16 
3 7 9 10 
0 5 8 6 
15 13 15 15 
20 18 18 16 
17 19 19 18 
13 15 14 12 
10 13 18 15

也許我在這里遺漏了一些明顯的東西,但是我很好奇為什么會這樣。

編輯:

  • x >通過參數傳遞。 在這種情況下為2。
  • score_matrix >不好的代碼是char* score_matrix[10][x][y]; ,好的是int score_matrix[10][x][y];
  • newline -> char newline[1024];
  • result -> char* result;
  • 此外,結果已通過printf語句驗證。

您重復使用相同的行緩沖區是錯誤的。 第一個樣本的輸出使您陷入一種錯誤的成功感,而實際上這是正確的。 修改循環以轉儲提取並保存的令牌的地址將顯示以下信息:

score_matrix[i][j][k] = result;
printf("%p ", result);
result = strtok(NULL, " ");

您將看到輸出多維數據集中的許多令牌共享相同的緩沖區地址,這當然是因為您為每個令牌化傳遞了相同的行緩沖區newline ,並且在此過程中清除了所有先前循環中的內容。

如果您想存儲實際的char * ,則可以,但是除非需要否則不要 相反,做你的固定版本的一個作用:轉化為int和存儲int作為矩陣值。 否則,您將需要如下所示的負載:

int i, j, k;
for (i=0; i!=10, (result = fgets(newline, 1024, stream))!=NULL; i++)
{
    result = strtok(newline, " ");
    for (j=0; j!=x; j++) {
        for (k=0; k!=y; k++) {
            score_matrix[i][j][k] = strdup(result); // NOTE: POSIX strdup() function
            printf("%d ", atoi(score_matrix[i][j][k]));
            result = strtok(NULL, " ");
        }
    }
     printf("\n");
}

以后將需要對所有這些動態分配進行hella-cleanup。 可以進行單個mondo分配,將整個文件作為單個動態char緩沖區加載到內存中,並顯着改變解析循環,但是我建議使用的單令牌動態分配方法要少得多。

暫無
暫無

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

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