我编写了一个程序,该程序使用户可以在任何文本文件中查找单词或单词集合的实例数。用户可以在命令行中输入以下内容:

$ ./wordCount Mars TripToMars.txt


在“前往火星”一书中搜索“火星”一词的实例数,或者

$ ./wordCount -f collectionOfSearchWords.txt TripToMars.txt


在collectionOfSearchWords.txt中的各个行上搜索几个单词的实例数。

为了确保程序正确,我使用了grep命令:

$ grep -o 'Mars' TripToMars.txt | wc -w




$ grep -o -w 'Mars' TripToMars.txt | wc -w


第一个命令查找任何位置的单词实例数量,其中包括“ Marsa”,“ Marseen”,“ Marses”等术语,而第二个命令仅查找“ Mars”实例作为独立单词,因此包括尾随标点符号,例如“火星”,“火星!”,“火星?”等。

这两个grep命令都返回49作为书中“火星”的实例数。

当我在下面的while循环中使用代码时(为简单起见,我仅包括相关代码),程序返回49。太棒了!

FILE *textToSearch;
char *readMode = "r";

int count;
char nextWord[100];
char d;

textToSearch = fopen(argVector[argCount-1], readMode);
if (textToSearch == NULL) {
    fprintf(stderr, "Cannot open %s to be searched\n", argVector[argCount-1]);
    return 1;
} else {
    while (fscanf(textToSearch, "%*[^a-zA-Z]"), fscanf(textToSearch, "%80[a-zA-Z]", nextWord) > 0) {

        // increment the counter if the word is a match
        if (strcmp(nextWord, argVector[word]) == 0) {
            count++;
        }
    }
}


但是,当我将此while循环替换为上一个循环时,程序返回17。

while(1) {
    d = fscanf(textToSearch, "%s", nextWord);
    if (d == EOF) break;

    // increment the counter if the word is a match
    if (strcmp(nextWord, argVector[word]) == 0) {
        count++;
    }
}


那么,两者之间的最大区别是

while (fscanf(textToSearch, "%*[^a-zA-Z]"), fscanf(textToSearch, "%80[a-zA-Z]", nextWord) > 0) {}




while(1) {
    d = fscanf(textToSearch, "%s", nextWord);
    if (d == EOF) break;
}




编辑:

我添加了以下代码:

if (strcmp(nextWordDict, nextWord) == 0 ||
     strcmp(nextWordDict, strcat(nextWord, ".")) == 0 ||
     strcmp(nextWordDict, strcat(nextWord, "?")) == 0 ||
     strcmp(nextWordDict, strcat(nextWord, "!")) == 0 ||
     strcmp(nextWordDict, strcat(nextWord, ",")) == 0) {
        count++;
 }


产生17的代码,供火星尝试处理标点符号结尾的情况,并且没有变化。还是17。

编辑2:

正如John Bollinger在下面正确指出的那样,该代码没有任何作用,因为缓冲到nextWord中的字符串已经具有结尾的标点符号,并且该代码只会添加更多内容。我这是错误的想法。

最佳答案

说命令时您不正确...

$ grep -o -w 'Mars' TripToMars.txt | wc -w


...“仅将“火星”的实例查找为独立词”,或者至少该陈述在上下文中具有误导性。该命令查找不属于较大单词的“火星”实例,其中“单词”定义为字母,数字和/或下划线的连续字符串。特别是,它将与“火星”匹配,后跟一个标点符号,该标点符号与您似乎声称的内容相冲突。

但是您的两种扫描方法有什么区别?好吧,这...

while (fscanf(textToSearch, "%*[^a-zA-Z]"),
        fscanf(textToSearch, "%80[a-zA-Z]", nextWord) > 0) { /* ... */ }


...扫描零个或多个非拉丁字母的字符,忽略是否匹配任何字符以及是否发生任何输入错误,然后扫描最多80个拉丁字母的连续序列,并将该序列记录在nextWord缓冲区中。

另一方面,这...

while(1) {
    d = fscanf(textToSearch, "%s", nextWord);
    if (d == EOF) break;
}


...忽略前导空格,然后将下一个非空格的连续字符串扫描到nextWord中。

两者在处理既不是拉丁字母也不是空格的字符方面有很大不同:前者忽略它们,而后者在nextWord中包括它们。然后,当您将nextWord与字符串"Mars"进行比较时,后者会错过


  去火星。





  名字“火星”





  火星上有水吗?


因为比较中包含了相邻的标点符号。您的文本很可能具有许多类似于这些结构的构造,并且您的grep命令没有进行其他演示。

10-07 12:07