2016-04-10 24 views
0

私はいくつかのファイルからデータを読み込み、それぞれに単語リストを含んでいます。私は各ファイルに単語の数を表示しようとしていますが、私は問題にぶつかっています。たとえば、コードを実行すると、次のような出力が得られます。予期せぬ出力 - 2次元配列をC言語で格納

単語が数千含まれている2つのファイルを除いて、ほぼすべての金額が正しく表示されます。他のすべてのファイルは3桁の単語しか持っていません。

私はこの問題が(どこかに十分なスペースが割り当てられていないのでしょうか)推測できますが、解決方法はわかりません。もしこれがすべて言葉に乏しいのであれば、私はお詫び申し上げます。私の脳は揚げられ、私は苦労しています。どんな助けもありがとう。

私は、私のサンプルコードを可能な限り簡潔に保つようにしました。私は、フル・プログラムに関連した多くのエラー・チェックやその他の作業を省略しました。私はできる限りコメントを追加しました。ありがとう。

StopWords.c

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

typedef struct 
{ 
    char stopwords[2000][60]; 
    int wordcount; 
} LangData; 

typedef struct 
{ 
    int languageCount; 
    LangData languages[]; 
} AllData; 


main(int argc, char **argv) 
{ 
    //Initialize data structures and open path directory 
    int langCount = 0; 
    DIR *d; 
    struct dirent *ep; 
    d = opendir(argv[1]); 

    //Count the number of language files in the directory 
    while(readdir(d)) 
     langCount++; 

    //Account for "." and ".." in directory 
    //langCount = langCount - 2 THIS MAKES SENSE RIGHT? 
    langCount = langCount + 1; //The program crashes if I don't do this, which doesn't make sense to me. 

    //Allocate space in AllData for languageCount 
    AllData *data = malloc(sizeof(AllData) + sizeof(LangData)*langCount); //Unsure? Seems to work. 

    //Reset the directory in preparation for reading data 
    rewinddir(d); 

    //Copy all words into respective arrays. 
    char word[60]; 
    int i = 0; 
    int k = 0; 
    int j = 0; 
    while((ep = readdir(d)) != NULL) //Probably could've used for loops to make this cleaner. Oh well. 
    { 
     if (!strcmp(ep->d_name, ".") || !strcmp(ep->d_name, "..")) 
     { 
      //Filtering "." and ".." 
     } 
     else 
     { 
      FILE *entry; 

      //Get string for path (i should make this a function) 
      char fullpath[100]; 
      strcpy(fullpath, path); 
      strcat(fullpath, "\\"); 
      strcat(fullpath, ep->d_name); 

      entry = fopen(fullpath, "r"); 

      //Read all words from file 
      while(fgets(word, 60, entry) != NULL) 
      { 
       j = 0; 

       //Store each word one character at a time (better way?) 
       while(word[j] != '\0') //Check for end of word 
       { 
        data->languages[i].stopwords[k][j] = word[j]; 
        j++; //Move onto next character 
       } 
       k++; //Move onto next word 
       data->languages[i].wordcount++; 
      } 

      //Display number of words in file 
      printf("%d\n", data->languages[i].wordcount); 
      i++; Increment index in preparation for next language file. 

      fclose(entry); 
     } 
    } 
} 

出力

256 //czech.txt: Correct 
101 //danish.txt: Correct 
101 //dutch.txt: Correct 
547 //english.txt: Correct 
1835363006 //finnish.txt: Should be 1337. Of course it's 1337. 
436 //french.txt: Correct 
576 //german.txt: Correct 
737 //hungarian.txt: Correct 
683853 //icelandic.txt: Should be 1000. 
399 //italian.txt: Correct 
172 //norwegian.txt: Correct 
269 //polish.txt: Correct 
437 //portugese.txt: Correct 
282 //romanian.txt: Correct 
472 //spanish.txt: Correct 
386 //swedish.txt: Correct 
209 //turkish.txt: Correct 
+0

通常のテキストエディタでファイルを正しく表示できることを確認しましたか?おそらくエンコードの問題でしょうか?改行文字を含めて、すべての単語が60バイト未満であることを確認していますか(「バイト」と「文字」ではないことに注意してください)。これは、ファイルが正しく開かれたことを前提としています( 'entry'は' NULL'ではありません)。フィールドは 'mallocを呼び出した時にメモリにある値で初期化されずに残す代わりに、 'fgets()'ループはほとんどスキップされます(そして 'ferror(entry)'は非ゼロ値を返します)。 –

+0

ファイルは標準のテキストエディタで開くことができます。すべてのファイルはUTF-8です。 finnish.txtの中で最も長い単語は "toimitusjohtaja"で、60バイトの近くではありませんが、私はそれを200に上げた場合に備えて、まったく同じ出力を受け取りました。私は入力を押すまで、一度に1つずつ読み込まれるごとに各単語を印刷する行を挿入し、ファイルは最後まで適切に読み込まれていますが、何らかの理由でカウントが間違っています。 –

答えて

0

ファイルは2000個の以上の単語を持っていますか?あなたは2000ワードのスペースしか割り当てていないので、あなたのプログラムが2001年の単語をコピーしようとすると、その配列に割り当てられたメモリの外で、おそらく "wordcount"に割り当てられたスペースにコピーされます。

また、fgetsは、行末または最大n文字(あなたの場合は60文字)のいずれか早いほうに文字列を返します。これは、あなたが読んでいるファイルに1行に1語しかない場合に見つけられます。そうでなければ、文字列内のスペースを見つけてそこから単語を数えなければなりません。

単語数を取得しようとしているだけであれば、すべての単語を最初に配列に格納する必要はありません。次は、同じようにうまく動作するはずです、1行に1つの単語と仮定すると:

char word[60]; 
while(fgets(word, 60, entry) != NULL) 
     { 
      data->languages[i].wordcount++; 
     } 

関数fgetsは、私は別の見ていたし、次のようにデータを割り当てるしようとする場合があります 更新http://www.cplusplus.com/reference/cstdio/

をreference-

typedef struct { char stopwords[2000][60]; int wordcount; } LangData; typedef struct { int languageCount; LangData *languages; } AllData; AllData *data = malloc(sizeof(AllData)); data->languages = malloc(sizeof(LangData)*langCount); 

このようにして、メモリは、言語配列に対して特別に割り当てられています。

私はlangCount = langCount - 2が合意に同意します。あなたはどんなエラーを出していますか?

+0

ファイル内の単語の最大数は1337であり、ファイルは1行に1単語しかありません。私のプログラムには、私がここで言葉を保存する必要があることを私が示していないということがもっとあります(私はそれらを後で調べる必要があります)。しかし、私は4000まで保存できる単語の数を増やそうとしましたが、60から2000までの文字の量、および前に私に問題を与えていた2つの文字が正しく表示されていますが、もう1つは間違っています。アップデート:私はそれぞれの限界を10000に上げたばかりで、今はすべて正しく表示されています。それはばかげているように見えますが、私はそれがなぜ機能するのか分かりません。 –

関連する問題