2016-11-28 91 views
1

我想創建一個指針數組,指向我的理解。但是,我正在使用valgrind運行讀取和寫入無效。使用C創建一個動態的字符數組指針指針

char **format_file(FILE *infile) { 
    char **char_array = malloc(20 * sizeof(char*)); 
    int c; 
    int cUsed = 0; 

    while ((c = fgetc(infile)) != EOF) { 
     char_array[cUsed] = c; 
     cUsed += 1; 
    } 

    printf("%s", *char_array); 
    return char_array; 
} 

該代碼通過從已打開的文件「infile」中讀取而工作。首先我用malloc爲20個字符分配了內存,然後我試圖按字符將文件字符讀入分配的內存數組中,直至達到F到達EO。然而,的valgrind的輸出如下所示,當我使代碼:

==7379== Invalid read of size 1 
==7379== at 0x4E7CB36: vfprintf (vfprintf.c:1597) 
==7379== by 0x4E85198: printf (printf.c:35) 
==7379== by 0x400755: format_file (formatter.c:27) 
==7379== by 0x4006C1: main (format265alt.c:21) 
==7379== Address 0x6f is not stack'd, malloc'd or (recently) free'd 

線27是printf命令的valgrind稱之爲尺寸1.

formatter.c由含有所述文件的無效的讀format265alt.c是一個調用formatter.c函數並打開要讀取的文件的文件。

我對**的語法感到困惑,那就是如何訪問和讀寫分配的內存?

如果我沒有提供有關此問題的足夠信息,我表示歉意。

+1

'CHAR_ARRAY [cUsed]'是'型將char *''不過是C'型'int'的。在那裏看到問題? – kaylum

+0

沒錯,但即使我把c變成角色,它仍然不起作用。 –

+0

你爲什麼要施放它?鑄造不是魔術。除非你知道你在做什麼,否則不要這樣做。關鍵是你的類型是錯誤的。解決這個問題(並且不,鑄造不是這樣)。 – kaylum

回答

0

valgrind抱怨,因爲您存儲的字符超出了分配的對象的末尾。編譯器應該抱怨你正在將字符存儲到錯誤類型的對象中,請使用-Wall -W來啓用有用的警告。

A char **是一個指向char指針的指針,它可以指向一個char指針數組,也被稱爲字符串數組。您必須爲文件內容分配適當大小的陣列和每個字符串。

在這裏有兩種可能性:

  • 功能可以將整個文件加載到一個字符串,但就沒有必要返回一個指向一個char*,剛剛返回的字符串(char * )就足夠了。

  • 擬議API是比較合適的,如果功能是一個指針末端返回字符串,每行一個的陣列,具有一個額外的NULL,就像argv陣列作爲第二個參數main傳遞功能。

對於這一點,你更多的行會從FILE*閱讀並因爲它的增長每一行應該被重新分配必須重新分配字符串數組。在字符串數組的末尾添加一個NULL指針以指示其結束。

這裏是要做到這一點非常低效的方式:

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

char **format_file(FILE *infile) { 
     size_t lines = 0; 
     char **array = malloc(1 * sizeof(char*)); 
     size_t pos = 0; 
     char *line = malloc(1); 
     int c; 

     while ((c = getc(infile)) != EOF) { 
      if (c == '\n') { 
       line[pos] = '\0'; 
       array = realloc(array, (lines + 2) * sizeof(char *)); 
       array[lines++] = line; 
       line = malloc(1); 
       pos = 0; 
       continue; 
      } 
      line = realloc(line, pos + 2); 
      line[pos++] = c; 
    } 
    if (pos > 0) { 
     line[pos] = '\0'; 
     array = realloc(array, (lines + 2) * sizeof(char *)); 
     array[lines++] = line; 
    } else { 
     free(line); 
    } 
    array[lines] = NULL; 
    return array; 
} 
0

如果您只是創建一個字符數組,那麼一維字符數組就足夠了。不需要char**業務。但是,如果您嘗試將它作爲字符串使用,請確保您null終止數組。

+0

所以只需在最後添加'\ 0'? C不會自動執行此操作? –

+0

正確。 C一般不會爲你做任何事情。一般的口頭禪是「程序員永遠是對的」,如果你不小心,會導致各種錯誤/分段錯誤。 – th13

+0

@ th13 C&C++的哲學是「程序員負責」,這就是C&C++如此有趣且具有挑戰性的語言的原因。這就是爲什麼我不喜歡Java而不喜歡C#的原因。 – user7140484