2017-11-22 13 views
1

いくつかのコードにいくつかの関数を実装することによって、スペルチェッカーを書くように指示する課題があります。構文エラーのためにコンパイルできません。データ割り当てと符号なしintの側面を理解する問題

まずは次のようになります。この関数から

speller.c:293:13: error: cannot increment value of type 'unsigned int (void)' 
     size++; 

speller.c:291:19: error: comparison of array 'trav_ptr->word' not equal to a null 
     pointer is always true [-Werror,-Wtautological-pointer-compare] 
    if (trav_ptr->word!=NULL) 

void count(trie *root_ptr) 
{ 
    trie *trav_ptr = root_ptr; 
    if (trav_ptr->word!=NULL) 
    { 
     size++; 
    } 
    for (int n = 0; n<26; n++) 
    { 
     if (trav_ptr->paths[n]!=NULL) 
     { 
      trav_ptr=trav_ptr->paths[n]; 
      count(trav_ptr); 
     } 
    } 
} 

私は私の問題は、どのようにmalloc作品を理解することにあると考えています。構造体トライのメモリを割り当てるとき

typedef struct trie 
{ 
    char word[MAXCHAR]; 
    struct trie *paths[26]; 
} 
trie; 

structのcharフィールドはNULLではありませんか?私は何もまだそれで満たしていないので。

私は初期化していないため、符号なしのintサイズ(グローバルに宣言されています)をインクリメントできないと思いますが、初期化すれば私に提供されるコードが混乱するでしょう。ここで

は、全体のプログラムです:

/** 
* Implements a spell-checker. 
*/ 

#include <ctype.h> 
#include <stdio.h> 
#include <sys/resource.h> 
#include <sys/time.h> 
#include <stdbool.h> 
#include <stdlib.h> 
#include <cs50.h> 
#include <string.h> 

#undef calculate 
#undef getrusage 
#define MAXCHAR 45 
// default dictionary 
#define DICTIONARY "dictionaries/large" 

typedef struct trie 
{ 
    char word[MAXCHAR]; 
    struct trie *paths[26]; 
} 
trie; 

double calculate(const struct rusage *b, const struct rusage *a); 

#define LENGTH 45 

bool check(const char *word, trie *root_ptr); 

bool load(const char *dictionary, trie *root_ptr); 

unsigned int size(trie *root_ptr); 

bool unload(void); 

void count (trie *root_ptr); 


int main(int argc, char *argv[]) 
{ 
    // check for correct number of args 
    if (argc != 2 && argc != 3) 
    { 
     printf("Usage: speller [dictionary] text\n"); 
     return 1; 
    } 

    // structs for timing data 
    struct rusage before, after; 

    // benchmarks 
    double time_load = 0.0, time_check = 0.0, time_size = 0.0, time_unload = 0.0; 

    // determine dictionary to use 
    char* dictionary = (argc == 3) ? argv[1] : DICTIONARY; 

    // load dictionary 
    trie *root = NULL; 
    trie *root_ptr = root; 
    getrusage(RUSAGE_SELF, &before); 
    bool loaded = load(dictionary, root_ptr); 
    getrusage(RUSAGE_SELF, &after); 

    // abort if dictionary not loaded 
    if (!loaded) 
    { 
     printf("Could not load %s.\n", dictionary); 
     return 1; 
    } 

    // calculate time to load dictionary 
    time_load = calculate(&before, &after); 

    // try to open text 
    char *text = (argc == 3) ? argv[2] : argv[1]; 
    FILE *fp = fopen(text, "r"); 
    if (fp == NULL) 
    { 
     printf("Could not open %s.\n", text); 
     unload(); 
     return 1; 
    } 

    // prepare to report misspellings 
    printf("\nMISSPELLED WORDS\n\n"); 

    // prepare to spell-check 
    int index = 0, misspellings = 0, words = 0; 
    char word[LENGTH+1]; 

    // spell-check each word in text 
    for (int c = fgetc(fp); c != EOF; c = fgetc(fp)) 
    { 
     // allow only alphabetical characters and apostrophes 
     if (isalpha(c) || (c == '\'' && index > 0)) 
     { 
      // append character to word 
      word[index] = c; 
      index++; 

      // ignore alphabetical strings too long to be words 
      if (index > LENGTH) 
      { 
       // consume remainder of alphabetical string 
       while ((c = fgetc(fp)) != EOF && isalpha(c)); 

       // prepare for new word 
       index = 0; 
      } 
     } 

     // ignore words with numbers (like MS Word can) 
     else if (isdigit(c)) 
     { 
      // consume remainder of alphanumeric string 
      while ((c = fgetc(fp)) != EOF && isalnum(c)); 

      // prepare for new word 
      index = 0; 
     } 

     // we must have found a whole word 
     else if (index > 0) 
     { 
      // terminate current word 
      word[index] = '\0'; 

      // update counter 
      words++; 

      // check word's spelling 
      getrusage(RUSAGE_SELF, &before); 
      bool misspelled = !check(word, root_ptr); 
      getrusage(RUSAGE_SELF, &after); 

      // update benchmark 
      time_check += calculate(&before, &after); 

      // print word if misspelled 
      if (misspelled) 
      { 
       printf("%s\n", word); 
       misspellings++; 
      } 

      // prepare for next word 
      index = 0; 
     } 
    } 

    // check whether there was an error 
    if (ferror(fp)) 
    { 
     fclose(fp); 
     printf("Error reading %s.\n", text); 
     unload(); 
     return 1; 
    } 

    // close text 
    fclose(fp); 

    // determine dictionary's size 
    getrusage(RUSAGE_SELF, &before); 
    unsigned int n = size(root_ptr); 
    getrusage(RUSAGE_SELF, &after); 

    // calculate time to determine dictionary's size 
    time_size = calculate(&before, &after); 

    // unload dictionary 
    getrusage(RUSAGE_SELF, &before); 
    bool unloaded = unload(); 
    getrusage(RUSAGE_SELF, &after); 

    // abort if dictionary not unloaded 
    if (!unloaded) 
    { 
     printf("Could not unload %s.\n", dictionary); 
     return 1; 
    } 

    // calculate time to unload dictionary 
    time_unload = calculate(&before, &after); 

    // report benchmarks 
    printf("\nWORDS MISSPELLED:  %d\n", misspellings); 
    printf("WORDS IN DICTIONARY: %d\n", n); 
    printf("WORDS IN TEXT:  %d\n", words); 
    printf("TIME IN load:   %.2f\n", time_load); 
    printf("TIME IN check:  %.2f\n", time_check); 
    printf("TIME IN size:   %.2f\n", time_size); 
    printf("TIME IN unload:  %.2f\n", time_unload); 
    printf("TIME IN TOTAL:  %.2f\n\n", 
    time_load + time_check + time_size + time_unload); 

    // that's all folks 
    return 0; 
} 



/** 
* Returns number of seconds between b and a. 
*/ 
double calculate(const struct rusage *b, const struct rusage *a) 
{ 
    if (b == NULL || a == NULL) 
    { 
     return 0.0; 
    } 
    else 
    { 
     return ((((a->ru_utime.tv_sec * 1000000 + a->ru_utime.tv_usec) - 
       (b->ru_utime.tv_sec * 1000000 + b->ru_utime.tv_usec)) + 
       ((a->ru_stime.tv_sec * 1000000 + a->ru_stime.tv_usec) - 
       (b->ru_stime.tv_sec * 1000000 + b->ru_stime.tv_usec))) 
       /1000000.0); 
    } 
} 
bool check(const char *word, trie *root_ptr) 
{ 
    char str[MAXCHAR]; 
    for(int j = 0; word[j]!='\0'; j++) 
    { 
     str[j]=word[j]; 
    } 
    trie *trav_ptr = root_ptr; 
    for(int i = 0; str[i]!='\0'; i++) 
    { 
     if (trav_ptr->paths[str[i] - 'a']==NULL) 
     { 
      return false; 
     } 
     else 
     { 
      trav_ptr=trav_ptr->paths[str[i] - 'a']; 
     } 
    } 
    if (str==trav_ptr->word) 
    { 
     return true; 
    } 
    return false; 
} 
/** 
* Loads dictionary into memory. Returns true if successful else false. 
*/ 
bool load(const char *dictionary, trie *root_ptr) 
{ 
    FILE *file_ptr; 
    char str[MAXCHAR]; 
    file_ptr = fopen(dictionary, "r"); 
    if (file_ptr == NULL){ 
     printf("Could not open file %s", dictionary); 
     return false; 
    } 

    trie *trav_ptr = root_ptr; 
    while (fgets(str, MAXCHAR, file_ptr) != NULL) 
    { 
     for(int i = 0; str[i]!='\0'; i++) 
     { 
      if (trav_ptr->paths[str[i] - 'a']==NULL) 
      { 
       trie *next_trie = malloc(sizeof(trie)); 
       trav_ptr->paths[str[i]-'a'] = next_trie; 
       trav_ptr = next_trie; 
      } 
      else 
      { 
       trav_ptr=trav_ptr->paths[str[i] - 'a']; 
      } 
     } 
     strcpy(trav_ptr->word, str); 
    } 
    return true; 
} 

/** 
* Returns number of words in dictionary if loaded else 0 if not yet loaded. 
*/ 
void count(trie *root_ptr) 
{ 
    trie *trav_ptr = root_ptr; 
    if (trav_ptr->word!=NULL) 
    { 
     size++; 
    } 
    for (int n = 0; n<26; n++) 
    { 
     if (trav_ptr->paths[n]!=NULL) 
     { 
      trav_ptr=trav_ptr->paths[n]; 
      count(trav_ptr); 
     } 
    } 
} 
unsigned int size(trie *root_ptr) 
{ 
    count(root_ptr); 
    return 0; 
} 

/** 
* Unloads dictionary from memory. Returns true if successful else false. 
*/ 
bool unload(void) 
{ 
    // TODO 
    return false; 
} 
+0

> "私の構造体のcharフィールドはNULLではありませんか?まだ何も入力していません。" Mallocはゼロなどでメモリを埋めるわけではありません。メモリの一部の領域が安全に使用できることを保証し、それをあなたに提供します。その中にゼロを入れたい場合は、自分自身を置くか、 'calloc()'を使います。 –

答えて

1

はの式trav_ptr->wordを考えてみましょう。 ->オペレータは、2つのことを実行すると言っています。trav_ptrが指し示す構造を使用し、wordという名前のメンバーを参照してください。まず、これを有効にするには、trav_ptrが有効な割り当て構造を指している必要があります。そして、結果式は、メンバーwordです。

次に、wordは、charアレイである。ほとんどの表現では、配列が参照されると、配列の最初の要素のアドレスに自動的に変換されます。

これは、コンパイラがtrav_ptr->wordをNULLに比較することについて警告する理由です。 nullになることはありません。 は、trav_ptrが指し示す構造の中で、常にwordの最初の要素のアドレスでなければなりません。

おそらくtrav_ptrとNULLを比較するつもりでした。 trav_ptrは単なるポインタであり、配列や構造体のメンバーではありません。構造体を指すことも、NULLにすることもできます。したがって、trav_ptrの値を取得した場合、それが構造体を指しているのか、NULLを含んでいるのかをチェックしたいとします。

sizeについては、unsigned int size(trie *root_ptr);と宣言しました。これは、trie *引数をとり、unsigned intを返す関数になります。あなたが呼び出すことのできる関数ではなく、インクリメントできるオブジェクトです。

+0

本質的に、配列をNULLにすることはできず、関数をインクリメントすることはできません。 – jwdonahue

+0

ありがとう、これは私の構文エラーを修正しました。 – Fooping

関連する問題