为什么这两种计算单词的方法差别很大?

时间:2015-01-28 18:55:08

标签: c regex text scanf text-parsing

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

$ ./wordCount Mars TripToMars.txt

搜索单词" Mars"的实例数量。在火星旅行中,或

$ ./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作为" Mars"的实例数。在书中。

当我在下面的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岁。

EDIT2

正如John Bollinger在下面正确指出的那样,这段代码什么都不做,因为缓冲到nextWord的字符串已经有了尾随标点符号,而代码只会添加更多。这是我的错误思考。

1 个答案:

答案 0 :(得分:1)

当你说命令......

时你不正确
$ grep -o -w 'Mars' TripToMars.txt | wc -w

..."只找到' Mars'作为一个单独的单词",或者至少该声明在上下文中具有误导性。该命令查找" Mars"的实例。这不是一个更大的词的一部分,其中一个"字"被定义为连续的字母,数字和/或下划线字符串。特别是,它将匹配" Mars"它后面跟着一个标点符号,与你似乎声称的内容相冲突。

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

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

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

另一方面,这......

nextWord

...忽略前导空格,然后将下一个连续的非空白字符串扫描到while(1) { d = fscanf(textToSearch, "%s", nextWord); if (d == EOF) break; }

两者对于既不是拉丁字母也不是空格的字符有很大不同:前者忽略它们,后者则将它们包括在nextWord中。然后,当您将nextWord与字符串nextWord进行比较时,后者错过了

  

去火星。

  

名称" Mars"

  

火星上有水吗?

因为相邻的标点符号包含在比较中。您的文本很可能有许多与此类似的构造,并且您的"Mars"命令不会以其他方式演示。