3

The problem with this function is that it looks after all the substrings, but not for words like for example if I'm looking for "hi" within "hifive to to evereyone" it returns 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;
}
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
Muhito
  • 37
  • 5
  • strtok might be useful – lulle2007200 Jul 31 '22 at 11:24
  • How would you do it on paper, elaborating *every* thing you do. Ex: You're searching for the complete-word "hi". You're given "hifive". You would look for the string and you'd find it. But, then you know it isn't a match because.... *why* ? Because the next part of the source string (a character) is not whitespace or end-of-string? yeah, that needs to be accounted for to disavow false-finds. And if you think that is tedious, it is (but not as much as mid-word false-finds, which you're going to be discovering shortly, I suspect). – WhozCraig Jul 31 '22 at 11:48
  • @WhozCraig *"mid-word false-finds"*... What do you mean? – Zakk Jul 31 '22 at 11:54
  • @lulle: I'm afraid `strtok()` would not be inappropriate for this task as it modifies the first string argument. – chqrlie Aug 26 '22 at 22:01

2 Answers2

1

Here is a function that achieves what you are looking for:

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;
}

Usage:

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);
}

Output:

There are 3 occurences.
Zakk
  • 1,935
  • 1
  • 6
  • 17
  • unfortunately this have has the same problem as mine :/ which is when your looking fr substring like "ot" in your example, it will retuned 3 but the Substring is actually not in String but sub_substring !! – Muhito Jul 31 '22 at 12:48
  • thnx alot, working now ;) – Muhito Jul 31 '22 at 13:48
1

Using your approach with the standard function strstr your function can look the following way as shown in the demonstration program below

#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 ) );
}

The program output is

0
0
1
1

If the source string can contain the new line character '\n' when within the function use isspace instead of isblank.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335