在一个字符串中计算特定单词出现的次数。

3
这个函数的问题在于它查找所有的子字符串,但并不适用于单词。例如,如果我在"hifive to to evereyone"中寻找"hi",它会返回1。
int HowManyString(char *satz,char *word) {
    int coun = 0;
    while (strlen(word)<strlen(satz)) {
        if (strstr(satz,word)==NULL) {
            return coun;
        } else {
            satz=strstr(satz,word)+strlen(word);
            if(*(satz)==' '||*(satz)=='\0'){
                coun++;
            } else {
                return coun;
            }
        }
    }
    return coun;
}

strtok可能会有用。 - lulle2007200
你会如何在纸上进行,并详细说明你所做的每一件事情。例如:你在搜索完整单词“hi”。给出了“hifive”。你将寻找该字符串并找到它。但是,接下来你会知道它不匹配,因为......为什么?因为源字符串的下一个部分(一个字符)不是空格或字符串结尾?是的,这需要考虑到以排除错误的查找。如果你认为这很繁琐,那就是(但不像你即将发现的中间错误查找那么麻烦)。 - WhozCraig
@WhozCraig "mid-word false-finds" 是什么意思? - Zakk
@lulle: 我担心strtok()不适合这个任务,因为它会修改第一个字符串参数。 - chqrlie
2个回答

1
这里有一个函数可以实现你所需要的功能:
int count_words(const char *sentence, const char *word)
{
    int counter = 0;
    
    for (const char *p = sentence; *p; ++p) {
        // Skip whitespaces
        if (isspace(*p))
            continue;
        
        // Attempt to find a match
        const char *wp = word, *sp = p;
        while (*wp != '\0' && *sp != '\0' && *wp == *sp) {
            ++wp;
            ++sp;
        }
        
        // Match found AND a space after AND a space before
        if (*wp == '\0' && (isspace(*sp) || *sp == '\0') && (p == sentence || isspace(*(p-1)))) {
            ++counter;
            p = sp - 1;
        }
        
        // End of sentence reached: no need to continue.
        if (*sp == '\0')
            return counter;
    }
    
    return counter;
}

使用方法:

int main(void)
{
    const char sentence[] = "I is Craig whoz not me, not him, not you!";
    const char word[] = "not";
    
    int occ = count_words(sentence, word);
    
    printf("There are %d occurences.\n", occ);
}

输出:

There are 3 occurences.

不幸的是,这个问题和我的一样:/ 当你在例子中寻找像“ot”这样的子字符串时,它会返回3,但实际上子字符串并不在字符串中,而是在子子字符串中!! - Muhito
非常感谢,现在可以工作了 ;) - Muhito

1

如果使用标准函数strstr,您的函数可以像下面的演示程序一样编写:

#include <stdio.h>
#include <string.h>
#include <ctype.h>

size_t HowManyString( const char *s1, const char *s2 )
{
    size_t count = 0;

    size_t n = strlen( s2 );

    for ( const char *p = s1; ( p = strstr( p, s2 ) ) != NULL; p += n )
    {
        if ( ( p == s1 || isblank( ( unsigned char )p[-1] ) ) &&
             ( p[n] == '\0' || isblank( ( unsigned char )p[n] ) ) )
        {
            ++count;
        }            
    }

    return count;
}

int main( void )
{
    const char *s1 = "hifive";
    const char *s2 = "hi";

    printf( "%zu\n", HowManyString( s1, s2 ) );

    s1 = "fivehi";

    printf( "%zu\n", HowManyString( s1, s2 ) );

    s1 = "hi five";

    printf( "%zu\n", HowManyString( s1, s2 ) );

    s1 = "five hi";

    printf( "%zu\n", HowManyString( s1, s2 ) );
}

程序的输出为:
0
0
1
1

如果源字符串可能包含换行符'\n',则在函数内部使用isspace而不是isblank

它工作了!!!非常感谢 xD - Muhito
1
@Muhito 没有关系。不客气。:) - Vlad from Moscow

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接