我有一个作业,要求我通过在某些给定代码中实现一些函数来编写拼写检查器。由于某些语法错误,我无法编译。
首先是:
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)
和:
speller.c:293:13: error: cannot increment value of type 'unsigned int (void)'
size++;
来自此功能:
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的工作原理。当malloc trie trie
malloctypedef struct trie
{
char word[MAXCHAR];
struct trie *paths[26];
}
trie;
我的结构的char场不是空的吗?由于我还没有填充任何东西。
至于另一个错误,我相信我不能增加unsigned 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] textn");
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 WORDSnn");
// 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] = ' ';
// 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("%sn", 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: %dn", misspellings);
printf("WORDS IN DICTIONARY: %dn", n);
printf("WORDS IN TEXT: %dn", words);
printf("TIME IN load: %.2fn", time_load);
printf("TIME IN check: %.2fn", time_check);
printf("TIME IN size: %.2fn", time_size);
printf("TIME IN unload: %.2fn", time_unload);
printf("TIME IN TOTAL: %.2fnn",
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]!=' '; j++)
{
str[j]=word[j];
}
trie *trav_ptr = root_ptr;
for(int i = 0; str[i]!=' '; 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]!=' '; 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;
}
让我们考虑表达式trav_ptr->word
。->
操作员说要做两件事:使用trav_ptr
指向的结构,并参考其成员名为word
。首先,为了使其起作用,trav_ptr
必须指向有效的分配结构。然后,结果表达式是成员word
。
接下来,word
是char
数组。在大多数表达式中,当引用数组时,它会自动转换为数组的第一个元素的地址。
因此,这就是为什么编译器警告您将trav_ptr->word
与NULL进行比较。永远不会无效;它必须始终是trav_ptr
指向的结构中word
的第一个元素的地址。
可能,您打算将trav_ptr
与NULL进行比较。trav_ptr
只是指针,而不是数组或结构成员。它可以指向结构,也可以是无效的。因此,当您获得trav_ptr
的值时,您想检查它指向结构还是包含null。
关于size
,您用unsigned int size(trie *root_ptr);
声明了它。这使其成为一个函数,该函数需要trie *
参数并返回unsigned int
。这是您调用的函数,而不是可以增加的对象。