2016-11-24 3 views
0

トークンを2D配列に移動するのに苦労します。 アイデアは、複数の行を持つファイルを読み込み、行数を取得し、それに基づいてメモリを賢明に使用するために2次元配列を作成することです(100 x 3配列を作成する必要はありません)。mallocを使用してトークンを2D配列にコピー

私は2次元配列は、別の目的球に初期化されてしまったと思いますが、私はstrtokは(から読み出されたデータを入力しようとすると)、私はエラーを取得しています:ここで

error: 'arr' undeclared (first use in this function) 
       strcpy(&arr[s2][c2],token); 

は私のコードです:

#include <stdio.h> 
#include <string.h> 
int ch, lines; 

int no_of_lines(char* fp) 
{ 
    while(!feof(fp)) { 
     ch = fgetc(fp); 
     if(ch == '\n') { 
      lines++; 
     } 
    } 
    lines++; 
    return lines; 
} 

void declare_space_array(int size) 
{ 
    char* arr = (char*)malloc(size * 3 * sizeof(char)); 
    return; 
} 

int main(void) 
{ 
    int c2 = 0; 
    int s2 = 0; 
    int len; 
    // char data[10][4]; 
    static const char filename[] = "C:\\Users\\PC\\Documents\\Assignments\\stringops\\test.txt"; 
    FILE* file = fopen(filename, "r"); 

    no_of_lines(file); 
    printf("No of lines in file = %d", lines); 
    printf("\n"); 
    // Closing file because it was read once till the end of file 
    fclose(file); 
    // Opening file again to read for parsing 

    file = fopen(filename, "r"); 
    declare_space_array(lines); 

    char* token; 

    if(file != NULL) { 
     char line[128];        
     while(fgets(line, sizeof line, file) != NULL) 
     { 
      len = strlen(line); 
      printf("%d %s", len - 1, line); 

      const char s = ","; 

      token = strtok(line, ","); 

      while(token != NULL) { 
       strcpy(arr[s2][c2], token); 
       // printf("%s\n", token); 

       token = strtok(NULL, ","); 
       c2++; 
      } 
      s2++; 
     } 
     fclose(file); 
    } else { 
     perror(filename); /* why didn't the file open? */ 
    } 

    for(r1 = 0; r1 < lines; r1++) { 
     for(c1 = 0; c1 < 3; c1++) { 
      printf("%s", &arr[r1][c1]); 
     } 
    } 
    return 0; 
} 

ファイルのようなものです:OUTPUTは次のようにSOMETHIGNすることが期待

A1,B1,C1 
A2,B2,C2 
A3,B3,C3 

A1 
B1 
C1 
A2 
B2 
C2 
A3 
B3 
C3 
+4

'declare_space_array()'関数は単にメモリを割り当ててリークします。変数 'arr'はその関数に対してローカルです。その機能の外ではアクセスできません。 –

+0

@JonathanLefflerグローバルにすることはできますか?または他の方法がありますか? – Fenomatik

+0

['while(!feof(file)) 'は常に間違っていることに注意してください](http://stackoverflow.com/questions/5431941/while-feof-file-is-always-wrong)。 –

答えて

1

チャットなどで議論した結果、このようなコードになる可能性があります。これは、グローバル変数arrを使用します。このグローバル変数は、配列の配列に3 char *の値を指すポインタです。

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

static int lines = 0; 
static char *(*arr)[3] = 0; // global definition. 

static int no_of_lines(FILE *fp) 
{ 
    lines = 0; 
    int ch; 
    while ((ch = fgetc(fp)) != EOF) 
    { 
     if (ch == '\n') 
      lines++; 
    } 
    return ++lines;  // Allow for last line possibly not having a newline 
} 

static void declare_space_array(int size) 
{ 
    arr = calloc(size, 3 * sizeof(char *)); // zeroed memory allocation 
    if (arr == 0) 
    { 
     fprintf(stderr, "Failed to allocate memory\n"); 
     exit(1); 
    } 
} 

int main(void) 
{ 
    int c2 = 0; 
    int s2 = 0; 
    int len; 
    // char data[10][4]; 
    // static const char filename[] = "C:\\Users\\PC\\Documents\\Assignments\\stringops\\test.txt"; 
    const char *filename = "data"; 
    FILE *file = fopen(filename, "r"); 
    if (file == 0) 
    { 
     fprintf(stderr, "Failed to open file '%s' for reading\n", filename); 
     exit(1); 
    } 

    no_of_lines(file); 
    printf("No of lines in file = %d\n", lines); 
    rewind(file); 

    declare_space_array(lines); 

    const char delims[] = ",\n"; 

    char line[128]; 
    while (fgets(line, sizeof line, file) != NULL) 
    { 
     char *token; 
     c2 = 0; 
     len = strlen(line); 
     printf("%d [%.*s]\n", len - 1, len - 1, line); 

     token = strtok(line, delims); 

     while (token != NULL) 
     { 
      arr[s2][c2] = strdup(token); // copy token (from strtok) into newly allocated string. 
      token = strtok(NULL, delims); 
      c2++; 
     } 
     s2++; 
    } 
    fclose(file); 

    for (int r1 = 0; r1 < lines; r1++) 
    { 
     if (arr[r1][0] != 0) 
     { 
      for (int c1 = 0; c1 < 3; c1++) 
       printf(" %-10s", arr[r1][c1]); 
      putchar('\n'); 
     } 
    } 
    return 0; 
} 

割り当てられたメモリが解放されません - 私は怠け者になりました。

サンプルデータ(名前が2文字以上であり、可変長のものであることに注意):

server1,Phoenix,Windows 
server2,Dallas,Linux 
server-99,London,z/OS 

サンプル出力:

No of lines in file = 4 
23 [server1,Phoenix,Windows] 
20 [server2,Dallas,Linux] 
21 [server-99,London,z/OS] 
server1 Phoenix Windows 
server2 Dallas  Linux  
server-99 London  z/OS  

'ファイル= 4の行数'最後の行の最後に改行がない可能性があります。印刷ループ内のコードは、最後に改行があった可能性を考慮しているため、数が過大評価されています。障害が回線の最初のフィールドにある限り、メモリ割り当てはstrdup()になります。 2番目または3番目のフィールドが正常にコピーされなかった場合、クラッシュする可能性があります。

+0

Holy Crap!これを詳細に研究して、2Dポインタ配列で概念を明確にする – Fenomatik

関連する問題