我是C编程的初学者。我正在尝试学习如何编写一个拼写检查器来查看字典文件中的所有单词,将它们与文章进行比较,将字典文件中不存在的所有单词打印到控制台上。由于我在课堂上学习malloc,我已经小写了每个单词,删除了文章中的所有标点符号,并将字符串复制到malloc中。我不知道下一步该怎么办,有人会给我一个提示吗?感谢
MAIN.C
#include <stdio.h>
#include <stdlib.h>
char dictionary[1000000];
char article[100000];
void spellCheck(char[], char[]);
int main(void) {
FILE* dict_file;
FILE* article_file;
int bytes_read;
char* p;
dict_file = fopen("american-english.txt", "r");
if (dict_file == 0) {
printf("unable to open dictionary file \"american-english.txt\"\n");
return -1;
}
article_file = fopen("article.txt", "r");
if (article_file == 0) {
printf("unable to open file \"article.txt\"\n");
return -1;
}
/* read dictionary */
p = dictionary;
p = fgets(p, 100, dict_file);
while (p != 0) {
while (*p != '\0') {
p += 1;
}
p = fgets(p, 100, dict_file);
}
/* read article */
p = article;
bytes_read = fread(p, 1, 1000, article_file);
p += bytes_read;
while (bytes_read != 0) {
bytes_read = fread(p, 1, 1000, article_file);
p += bytes_read;
}
*p = 0;
spellCheck(article, dictionary);
}
PROJECT.C
void spellCheck(char article[], char dictionary[]) {
int len = strlen(article) + 1;
int i;
char* tempArticle;
tempArticle = malloc(len);
if (tempArticle == NULL) {
printf("spellcheck: Memory allocation failed.\n");
return;
}
for(i = 0; i < len; i++)
tempArticle[i] = tolower(article[i]);
i=0;
while (article[i] != '\0'){
if (article[i] >= 33 && article[i] <= 64)
article[i] = ' ';
}
printf("%s", tempArticle);
free(tempArticle);
}
答案 0 :(得分:3)
如何组织数据结构非常重要。
您可能不仅要像Zareth所提到的那样将字典放入二叉树中,而且要对文章执行相同的操作,这样您就可以删除所有重复的单词并对其进行排序。
这种方式当你开始搜索字典时,如果你翻过你的单词开头的字母,那么你可以退出,因为字典是排序的。
答案 1 :(得分:1)
您的代码的下一步是将每个文章词与词典中的每个词进行比较。使用strcmp可以很容易地进行比较,但是存储字典的方式将迫使您乱用指针来查找字典中每个新单词的开头。
如果没有任何重大更改,您可以进行这样的比较,但是它会要求您以某种方式确定何时比较字典中的所有单词,例如通过计算字典中有多少单词从文件中读取它。
char* dictionary_word = dictionary;
int not_found = 1;
int i = 0;
for (; i < dictionary_word_count; ++i) {
if ((not_found = strcmp(tempArticle, dictionary_word)) == 0) {
break; /* Word found, we're done */
}
/* Add code to move dictionary_word to the next word here */
}
您当前程序的问题是将dictionary_word以一种好的方式移动到下一个单词。只需将指针一次推进一个字符并检查是否找到了下一个字,就可以这样做。我建议你创建另一个char指针数组,让它们指向每个单词的开头,并在读取字典文件中的单词时分配它们。这会让你做类似的事情
在for循环开始时dictionary_word = dictionary_word_pointers[i];
使其指向正确的单词,而不是使用while循环来查找下一个单词的开头。它还具有易于排序的额外好处。
您可以预先对字典进行排序,如果字典很大并使用线性搜索进行搜索太慢,则可以使用binary search来加速字典查找。
答案 2 :(得分:1)
恭喜,您已将数据加载到内存中,并通过检查系统调用的状态完成了所有操作。现在你需要用字典数据做更多的事情:
创建一个char *
指针数组,一个指向每个单词。
char * words [100000]; / *确保你有足够的空间。 * /
对于词典中的每个单词,请在words
中输入一个条目。有多种方法可以执行此操作,例如,您可以使用strndup
在使用dictionary
或isspace
查找其长度后复制strcspn
中的每个单词。
words
(请参阅qsort
)。bsearch
)以获取单词。words
的数组中。如果您想获得幻想,可能需要尝试使用stat
来获取文件的大小,并使用dictionary
为article
和malloc
分配内存而不是使用“魔术数字”或“非常大的数字”。对于工业强度C,你肯定需要这样做。
答案 3 :(得分:0)
'词典'是否按每行一个单词组织?您可以合理地使用'strlen()`而不是'p + = 1'的循环。据推测,字典也是排序的?
在内存中有字典后,您无需将整篇文章读入内存。您可以使用'fscanf()'一次读取一个单词,然后消除任何标点符号,因此“t'other”显示为单词“t”,“other”和“not not”显示为“doesn”和“t” - 如果你喜欢。或者您可以认为这没有帮助。另一方面,您可能希望删除问号和双引号等字符。
您的词典是否提供单词的所有变体,或者您是否需要参与词干?作为一个例子,“反教育法”可以被制定为“反”,“不”,“建立”,“心灵”,“阿里安”,“主义”等。
您还需要考虑降低所有内容是否正确。例如,您可能认为“IBM”没有问题,“ibm”也没有;同样“ICBM”和“icbm”(“Ibm”和“Icbm”都在“正确拼写”的任何合理定义下都很糟糕。)
你应该利用这样一个事实,即你的字典被排序以使用二进制搜索或类似的机制来减少搜索时间。