2016-10-26 9 views
1

(Cで)配列に格納する私は、以下からなる入力ファイルがあります。読書スペース区切り文字列のラインごととは

CREATEHALL "Red-Hall" "StarDust" 24 20 
CREATEHALL "Orange-Hall" "Last_Samurai" 10 20 

をそして私は、将来の使用のために、アレイ内の各ラインを保存したいです。

は、これまでのところ、私のコードは次のとおりです。 (デバッグ目的のためのprintfのをたくさん追加しました)

#include <stdio.h> 
#include <stdlib.h> 
struct str 
{ 
char *commands[5]; 
}; 

struct str a[]; 
int main() 
{ 
    int i=0; 
    int j=0; 
    char *token; 
    printf("Starting the program...\n"); 
    char filename[] = "input.txt"; 
    FILE *file = fopen (filename, "r"); 

    if (file != NULL) { 
     char line [1000]; 
     printf("Read a new line...\n"); 
     while(fgets(line,sizeof line,file)!= NULL) /* read a line from a file */ { 
      j=0; 
      printf("%s\n",line); 
      printf("Start token stuff...\n"); 
      /* get the first token */ 
      token = strtok(line, " "); 

      /* walk through other tokens */ 
      while(token != NULL) 
      { 
       a[i].commands[j]=token; 
       printf("Stored Command : %s\n", token); 
       token = strtok(NULL, " "); 
       j++; 
      } 
      i++; 
     } 

     fclose(file); 
    } 
    else { 
     perror(filename); //print the error message on stderr. 
    } 
    printf("Finished processing tokens...\n\n\n"); 

    printf("%s\n%s\t%s\t%s\t%s\n", a[0].commands[0], a[0].commands[1],a[0].commands[2],a[0].commands[3],a[0].commands[4]); 
    printf("%s\n%s\t%s\t%s\t%s\n", a[1].commands[0], a[1].commands[1],a[1].commands[2],a[1].commands[3],a[1].commands[4]); 
    return 0; 
} 

私はコンソールに乗る出力はこれです:

Starting the program... 
Read a new line... 
CREATEHALL "Red-Hall" "StarDust" 24 20 

Start token stuff... 
Stored Command : CREATEHALL 
Stored Command : "Red-Hall" 
Stored Command : "StarDust" 
Stored Command : 24 
Stored Command : 20 

CREATEHALL "Orange-Hall" "Last_Samurai" 10 20 
Start token stuff... 
Stored Command : CREATEHALL 
Stored Command : "Orange-Hall" 
Stored Command : "Last_Samurai" 
Stored Command : 10 
Stored Command : 20 
Finished processing tokens... 


CREATEHALL 
"Orange-Hall" l"  murai" ai" 
CREATEHALL 
"Orange-Hall" "Last_Samurai" 10  20 

I Cとはあまりよくないです(これは課題のごく一部です)。しかし、私はそのエラーがこの部分にあると信じています。

a[i].commands[j]=token; 

ライン、前にそれがうまく言葉を読み込むことから。

ありがとうございます。

+1

あなたはコマンドのためにそう – LPs

+2

行うには、[のstrdup](https://linux.die.net/man/3/strdup)を使用することができる[5]配列あなたはすべての要素のためのスペースを割り当てる必要があります。 mallocを使い、文字列をコピーするにはstrcpyを使用してください。値の割り当てを使わないでください –

+0

デバッグ用にたくさんのprintfsを追加するのではなく、デバッガを使うべきです。 –

答えて

0

the Manから

戻り値

はstrtok()、それ以上のトークンが存在しない場合はstrtok_r()関数は次のトークン、またはNULLへのポインタを返します。

したがって、保存しているポインタはchar lib[1000]のアドレスであり、処理の最後には最後に読み込まれた行が含まれます。


も次元ずに、あなたが悪いの配列を定義したことに注意してください:

struct str a[]; 

は最速の補正をすることができ、少なくとも、

struct str a[2]; 

、する必要があります

#define _BSD_SOURCE 

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

struct str 
{ 
char *commands[5]; 
}; 

struct str a[2]; 
int main() 
{ 
    int i=0; 
    int j=0; 
    char *token; 
    printf("Starting the program...\n"); 
    char filename[] = "input.txt"; 
    FILE *file = fopen (filename, "r"); 

    if (file != NULL) { 
     char line [1000]; 
     printf("Read a new line...\n"); 
     while(fgets(line,sizeof line,file)!= NULL) /* read a line from a file */ { 
      j=0; 
      printf("%s\n",line); 
      printf("Start token stuff...\n"); 
      /* get the first token */ 
      token = strtok(line, " "); 

      /* walk through other tokens */ 
      while(token != NULL) 
      { 
       char *temp = strdup(token); 
       if (temp != NULL) 
       { 
        a[i].commands[j]=temp; 
       } 
       else 
       { 
        fprintf(stderr, "No memory available to store string\n"); 
        return 1; 
       } 
       printf("Stored Command : %s\n", token); 
       token = strtok(NULL, " "); 
       j++; 
      } 
      i++; 
     } 

     fclose(file); 
    } 
    else { 
     perror(filename); //print the error message on stderr. 
    } 
    printf("Finished processing tokens...\n\n\n"); 

    printf("%s\n%s\t%s\t%s\t%s\n", a[0].commands[0], a[0].commands[1],a[0].commands[2],a[0].commands[3],a[0].commands[4]); 
    printf("%s\n%s\t%s\t%s\t%s\n", a[1].commands[0], a[1].commands[1],a[1].commands[2],a[1].commands[3],a[1].commands[4]); 
    return 0; 
} 

より複雑なプロジェクトでは、strdupによって実行されるヒープ割り当てのために、複製された文字列はfree dでなければなりません。


別の解決策はmallocを用いて各要素のためのスペースを割り当て、トークンをコピーするstrcpyを使用して実施することができます。ここ

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

struct str 
{ 
    char *commands[5]; 
}; 

struct str a[2]; 

int main() 
{ 
    int i=0; 
    int j=0; 
    char *token; 
    printf("Starting the program...\n"); 
    char filename[] = "input.txt"; 
    FILE *file = fopen (filename, "r"); 

    if (file != NULL) { 
     char line [1000]; 
     printf("Read a new line...\n"); 
     while(fgets(line,sizeof line,file)!= NULL) /* read a line from a file */ { 
      j=0; 
      printf("%s\n",line); 
      printf("Start token stuff...\n"); 
      /* get the first token */ 
      token = strtok(line, " "); 

      /* walk through other tokens */ 
      while(token != NULL) 
      { 
       a[i].commands[j] = malloc(strlen(token)+1); 
       if (a[i].commands[j] != NULL) 
       { 
        strcpy(a[i].commands[j], token); 
       } 
       else 
       { 
        fprintf(stderr, "No memory available to store string\n"); 
        return 1; 
       } 
       printf("Stored Command : %s\n", token); 
       token = strtok(NULL, " "); 
       j++; 
      } 
      i++; 
     } 

     fclose(file); 
    } 
    else { 
     perror(filename); //print the error message on stderr. 
    } 
    printf("Finished processing tokens...\n\n\n"); 

    printf("%s\n%s\t%s\t%s\t%s\n", a[0].commands[0], a[0].commands[1],a[0].commands[2],a[0].commands[3],a[0].commands[4]); 
    printf("%s\n%s\t%s\t%s\t%s\n", a[1].commands[0], a[1].commands[1],a[1].commands[2],a[1].commands[3],a[1].commands[4]); 
    return 0; 
} 

同じこと、あなたがd malloc atedメモリをfree必要があります。

+0

なぜ 'struct str a [2];'の代わりに 'struct str a [1];'を設定するのですか? –

+0

ありがとう、それは私の問題を解決しました。 – Aguen

1

@LPsが示すように、ちょうど(のstrdupを追加するには)あなたの配列に格納する際に抽出された文字列を維持するために呼び出します。しかし前に、あなたがあなたのstruct str a []を割り当てていることを確認してください。

ステップ1置き換える:

struct str a[]; 

によって:

#define MAX_NB_LINES (100) 
struct str a[MAX_NB_LINES]; 

ステップ2で(のstrdupを追加)アレイに格納する場合:

while(token != NULL) 
{ 
    a[i].commands[j]=strdup(token); 
    printf("Stored Command : %s\n", token); 
    token = strtok(NULL, " "); 
    j++; 
    if (j >= 5) break; // stop extraction when 5 commands are stored 
} 

構造体STRの使用を開始する前a []、charポインタを に初期化します。

for(i=0;i<MAX_NB_LINES;i++) { 
    for(j=0;j<5;j++) { 
     a[i].commands[j]=NULL; 
    } 
} 

[] STR構造体を使用した後、単に割り当てられたメモリを解放します。

for(i=0;i<MAX_NB_LINES;i++) { 
    for(j=0;j<5;j++) { 
     // free only the allocated char pointer 
     if (a[i].commands[j]!=NULL) free(a[i].commands[j]); 
     a[i].commands[j]=NULL; 
    } 
} 
+0

そして、 'strdup'は' malloc'を呼び出しているので、メモリリークを防ぐために何をする必要がありますか?動的割り当てには何も問題はありませんが、データが既知の最大サイズのものであれば(例えば、各 'command''16-char'以下で' struct str'の静的配列を使うことも別のオプションです - 学習レベルに合わせて) –

+0

@ DavidC.Rankin答えが更新されました –

関連する問題