2017-01-31 4 views
2

これは私のコードをfscanfに適合させて2回目です。出力の横にコメントを投げました。私が抱えている主な問題は、1つのヌル文字またはスペースが配列に追加されていることです。文字列変数の空文字と空白をチェックしようとしましたが、それをキャッチしません。私はちょっと立ち往生して、なぜ私のコードがその1つのヌル文字を通しているのか知りたいですか?私はその文字を処理していても、私の配列内の1文字を解読することはできません

"Pardon、O King"をスリップしている部分、出力:King - 1; - 1 ここでそれはキング単語を解析し、 "ストリップ関数を通過して\ 0になり、道路の後ろにある私のチェックがそれを許しますか?

入力:アポストロフィとカンマ(ライオンの岩。まず、ライオンは目が覚めた)

//Output: Every unique word that shows up with how many times it shows up. 
//Lion -- 1 
//s - 12 
//lion -- 8 
//tree -- 2 
//-- 1 //this is the line that prints a null char? 
//cub -- //3 it is not a space! I even check if it is \0 before entering 
     //it into the array. Any ideas (this is my 2nd time)? 
     //trying to rewrite my code around a fscanf function. 


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

//Remove non-alpha numeric characters 
void strip_word(char* string) 
{ 
    char* string_two = calloc(80, sizeof(char)); 
    int i; 
    int c = 0; 
    for(i = 0; i < strlen(string); i++) 
    { 
     if(isalnum(string[i])) 
     { 
      string_two[c] = string[i]; 
      ++c; 
     } 
    } 
    string_two[i] = '\0'; 
    strcpy(string, string_two); 
    free(string_two); 
} 

//Parse through file 
void file_parse(FILE* text_file, char*** word_array, int** count_array, int* total_count, int* unique_count) 
{ 
    int mem_Size = 8; 
    int is_unique = 1; 

    char** words = calloc(mem_Size, sizeof(char *)); //Dynamically allocate array of size 8 of char* 
    if (words == NULL) 
    { 
     fprintf(stderr, "ERROR: calloc() failed!"); 
    } 

    int* counts = calloc(mem_Size, sizeof(int)); //Dynamically allocate array of size 8 of int 
    if (counts == NULL) 
    { 
     fprintf(stderr, "ERROR: calloc() failed!"); 
    } 

    printf("Allocated initial parallel arrays of size 8.\n"); 
    fflush(stdout); 

    char* string; 

    while('A') 
    { 
     is_unique = 1; 

     fscanf(text_file, " ,"); 
     fscanf(text_file, " '"); 

     while(fscanf(text_file, "%m[^,' \n]", &string) == 1) //%m length modifier 
     { 
      is_unique = 1; 
      strip_word(string); 
      if(string == '\0') continue; //if the string is empty move to next iteration 
      else 
      { 
       int i = 0;    
       ++(*total_count); 
       for(i = 0; i < (*unique_count); i++) 
       { 
        if(strcmp(string, words[i]) == 0) 
        { 
         counts[i]++; 
         is_unique = 0; 
         break; 
        } 
       } 
       if(is_unique) 
       { 
        ++(*unique_count); 
        if((*unique_count) >= mem_Size) 
        { 
         mem_Size = mem_Size*2; 
         words = realloc(words, mem_Size * sizeof(char *)); 
         counts = realloc(counts, mem_Size * sizeof(int)); 
         if(words == NULL || counts == NULL) 
         { 
          fprintf(stderr, "ERROR: realloc() failed!"); 
         } 
         printf("Re-allocated parallel arrays to be size %d.\n", mem_Size); 
         fflush(stdout); 
        } 
        words[(*unique_count)-1] = calloc(strlen(string) + 1, sizeof(char)); 
        strcpy(words[(*unique_count)-1], string); 
        counts[(*unique_count) - 1] = 1; 
       } 
      } 
      free(string); 
     } 
     if(feof(text_file)) break; 
    } 
    printf("All done (successfully read %d words; %d unique words).\n", *total_count, *unique_count); 
    fflush(stdout); 
    *word_array = words; 
    *count_array = counts; 

} 

int main(int argc, char* argv[]) 
{ 
    if(argc < 2 || argc > 3) //Checks if too little or too many args 
    { 
     fprintf(stderr, "ERROR: Invalid Arguements\n"); 
     return EXIT_FAILURE; 
    } 

    FILE * text_file = fopen(argv[1], "r"); 
    if (text_file == NULL) 
    { 
     fprintf(stderr, "ERROR: Can't open file"); 

    } 

    int total_count = 0; 
    int unique_count = 0; 
    char** word_array; 
    int* count_array; 

    file_parse(text_file, &word_array, &count_array, &total_count, &unique_count); 

    fclose(text_file); 

    int i; 

    if(argv[2] == NULL) 
    { 
     printf("All words (and corresponding counts) are:\n"); 
     fflush(stdout); 
     for(i = 0; i < unique_count; i++) 
     { 
      printf("%s -- %d\n", word_array[i], count_array[i]); 
      fflush(stdout); 
     } 
    } 

    else 
    { 
     printf("First %d words (and corresponding counts) are:\n", atoi(argv[2])); 
     fflush(stdout); 
     for(i = 0; i < atoi(argv[2]); i++) 
     { 
      printf("%s -- %d\n", word_array[i], count_array[i]); 
      fflush(stdout); 
     } 
    } 

    for(i = 0; i < unique_count; i++) 
    { 
     free(word_array[i]); 
    } 
    free(word_array); 
    free(count_array); 

    return EXIT_SUCCESS; 
} 
+0

'strip_word()'関数で単に 'char string_two [80];'を使用し、 'calloc()'と 'free()'を避けるのはなぜですか?とにかくこの分析をやっていない、組み込みシステムの中で最も小さいものを除いて、スタック上の約80バイトを心配する必要はありません。また、原則として、for(i = 0; i

+0

あなたは決して 'string'のためのメモリを割り当てませんでした。 'string 'は文字ではなくポインタであるため、' if(* string ==' \ 0 ') ' – Barmar

+1

@Barmar: fscanf(text_file、%m [^、 '\ n] "、&string)' 'm'はメモリを割り当てることを意味します(' 'fscanf()'のPOSIX拡張子(http://pubs.opengroup .org/onlinepubs/9699919799/functions/fscanf.html)を参照してください)。 –

答えて

1

私はあなたのコードで間違って起こってかなりよく分からない。私は、GCC 6.3.0とMacOSのシエラ10.12.3に取り組んでいる、とローカルfscanf()m修飾子をサポートしていないため、固定長の80バイトの文字列を使用するようにコードを修正しました。 「ライオンの岩」を入力してください。まず、ライオンは「目が覚めた)。

また、私はそれがすべてで使用されている場合、従来while (1)書かれるべきwhile ('A')ループ()が望ましくないことだと思う。私は次の 『単語』を取得する機能read_word()を書きました、スキップ空白、カンマや引用符を含めて、ループを制御するためにそれを使用私は変わらずfile_parse()であなたのメモリ割り当てを左に、私は(最終的には - あまりにも書かれて、それはOK働いていた)strip_word()でメモリ割り当てを取り除くでした。。。

それは私を残しました:

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

static void strip_word(char *string) 
{ 
    char string_two[80]; 
    int i; 
    int c = 0; 
    int len = strlen(string); 
    for (i = 0; i < len; i++) 
    { 
     if (isalnum(string[i])) 
      string_two[c++] = string[i]; 
    } 
    string_two[c] = '\0'; 
    strcpy(string, string_two); 
} 

static int read_word(FILE *fp, char *string) 
{ 
    if (fscanf(fp, " ,") == EOF || 
     fscanf(fp, " '") == EOF || 
     fscanf(fp, "%79[^,' \n]", string) != 1) 
     return EOF; 
    return 0; 
} 

static void file_parse(FILE *text_file, char ***word_array, int **count_array, int *total_count, int *unique_count) 
{ 
    int mem_Size = 8; 

    char **words = calloc(mem_Size, sizeof(char *)); 
    if (words == NULL) 
    { 
     fprintf(stderr, "ERROR: calloc() failed!"); 
    } 

    int *counts = calloc(mem_Size, sizeof(int)); 
    if (counts == NULL) 
    { 
     fprintf(stderr, "ERROR: calloc() failed!"); 
    } 

    printf("Allocated initial parallel arrays of size 8.\n"); 
    fflush(stdout); 

    char string[80]; 

    while (read_word(text_file, string) != EOF) 
    { 
     int is_unique = 1; 
     printf("Got [%s]\n", string); 
     strip_word(string); 
     if (string[0] == '\0') 
      continue; 
     else 
     { 
      int i = 0; 
      ++(*total_count); 
      for (i = 0; i < (*unique_count); i++) 
      { 
       if (strcmp(string, words[i]) == 0) 
       { 
        counts[i]++; 
        is_unique = 0; 
        break; 
       } 
      } 
      if (is_unique) 
      { 
       ++(*unique_count); 
       if ((*unique_count) >= mem_Size) 
       { 
        mem_Size = mem_Size * 2; 
        words = realloc(words, mem_Size * sizeof(char *)); 
        counts = realloc(counts, mem_Size * sizeof(int)); 
        if (words == NULL || counts == NULL) 
        { 
         fprintf(stderr, "ERROR: realloc() failed!"); 
         exit(EXIT_FAILURE); 
        } 
        printf("Re-allocated parallel arrays to be size %d.\n", mem_Size); 
        fflush(stdout); 
       } 
       words[(*unique_count) - 1] = calloc(strlen(string) + 1, sizeof(char)); 
       strcpy(words[(*unique_count) - 1], string); 
       counts[(*unique_count) - 1] = 1; 
      } 
     } 
    } 
    printf("All done (successfully read %d words; %d unique words).\n", *total_count, *unique_count); 
    fflush(stdout); 
    *word_array = words; 
    *count_array = counts; 
} 

int main(int argc, char *argv[]) 
{ 
    if (argc < 2 || argc > 3) 
    { 
     fprintf(stderr, "ERROR: Invalid Arguements\n"); 
     return EXIT_FAILURE; 
    } 

    FILE *text_file = fopen(argv[1], "r"); 
    if (text_file == NULL) 
    { 
     fprintf(stderr, "ERROR: Can't open file"); 
     return EXIT_FAILURE; 
    } 

    int total_count = 0; 
    int unique_count = 0; 
    char **word_array = 0; 
    int *count_array = 0; 

    file_parse(text_file, &word_array, &count_array, &total_count, &unique_count); 

    fclose(text_file); 

    if (argv[2] == NULL) 
    { 
     printf("All words (and corresponding counts) are:\n"); 
     fflush(stdout); 
     for (int i = 0; i < unique_count; i++) 
     { 
      printf("%s -- %d\n", word_array[i], count_array[i]); 
      fflush(stdout); 
     } 
    } 
    else 
    { 
     printf("First %d words (and corresponding counts) are:\n", atoi(argv[2])); 
     fflush(stdout); 
     for (int i = 0; i < atoi(argv[2]); i++) 
     { 
      printf("%s -- %d\n", word_array[i], count_array[i]); 
      fflush(stdout); 
     } 
    } 

    for (int i = 0; i < unique_count; i++) 
     free(word_array[i]); 
    free(word_array); 
    free(count_array); 

    return EXIT_SUCCESS; 
} 

データファイル上で実行する場合:

the lion's rock. First, the lion woke up 

出力した:

$ echo '"Pardon, O King,"' | cw37 /dev/stdin 
Allocated initial parallel arrays of size 8. 
Got ["Pardon] 
Got [O] 
Got [King] 
Got ["] 
All done (successfully read 3 words; 3 unique words). 
All words (and corresponding counts) are: 
Pardon -- 1 
O -- 1 
King -- 1 
$ 

それをこのようなコードは、二重引用符を含め、テキスト上で実行された

Allocated initial parallel arrays of size 8. 
Got [the] 
Got [lion] 
Got [s] 
Got [rock.] 
Got [First] 
Got [the] 
Got [lion] 
Got [woke] 
Got [up] 
All done (successfully read 9 words; 7 unique words). 
All words (and corresponding counts) are: 
the -- 2 
lion -- 2 
s -- 1 
rock -- 1 
First -- 1 
woke -- 1 
up -- 1 

、コードをちょっとした。アルファベット文字がない場合、コードではまだカウントされます(strip_word()の微妙な問題のため)。それはより慎重にstrip_word()をチェックすることによって処理する必要があります。文字列が空であるかどうかをテストするためにif (string[0] == '\0')が必要な場所にメモリが割り当てられているかどうかを(後で)チェックするif (string == '\0')をテストします。

行内に2つのカンマがある場合は、read_word()のコードが混乱します。アポストロフィとそれに続くカンマが付いていれば、EOFの報告に混乱することに注意してください。それは固定的です。おそらくgetc()というループを使って文字列を読む方が良いでしょう。別のstrip_word()機能を使わなくても、アルファベット以外の文字を取り除くためにそのループを使用することもできます。

まだ構造をまだカバーしていないと仮定しています。構造体をカバーしていた場合は、struct Word { char *word; int count; };のような構造体の配列を使用し、2つの並列配列を必要とせずにメモリを1回割り当てます。

関連する問題