いくつかのコードにいくつかの関数を実装することによって、スペルチェッカーを書くように指示する課題があります。構文エラーのためにコンパイルできません。データ割り当てと符号なし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;
}
> "私の構造体のcharフィールドはNULLではありませんか?まだ何も入力していません。" Mallocはゼロなどでメモリを埋めるわけではありません。メモリの一部の領域が安全に使用できることを保証し、それをあなたに提供します。その中にゼロを入れたい場合は、自分自身を置くか、 'calloc()'を使います。 –