简体   繁体   中英

Find the length of the longest word in a string. C language

Problem: I can't seem to get my test case 4 to work.

Question:

Write a C function that accepts an English sentence as a parameter, and returns the length of the longest word in the sentence. For example, if the sentence is "I am Tim.", then the length of the longest word "time" in sentence 3 will be returned.

Test Case 1:

Enter a string: I am lee.
longWordLength(): 3

Test Case 2:

Enter a string: There are two disciples in the class.
longWordLength(): 9

Test Case 3:

Enter a string: Good night!
longWordLength(): 5

Test Case 4:

Enter a string: Jovial
longWordLength(): 6 

This is the code I have so far:

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

int longWordLength(char *s);

int main()
{
 char str[80], *p;

 printf("Enter a string: \n");
 fgets(str, 80, stdin);
 if (p=strchr(str,'\n')) *p = '\0';

 printf("longWordLength(): %d\n", longWordLength(str));

 return 0;
}
int longWordLength(char *s)
{
    int i, count, max;
    max = 0;
    count = 0;

    while( *(s) != '\0' )
    {
        if ( *(s) != '\0' && *(s) != ' ' && *(s) != '.' )
        {
            count++;
            printf("current count is %d\n", count);
        }
        else
        {
            if(count>max)
            {
                max = count;
                printf("There is a new max! It is %d\n", max);
                count = 0;
            }
            count = 0;
            printf("count is resetted!\n");
        }

        s++;
        printf("reach the end of the while loop\n");
    }

    printf("current max outside while loop is: %d\n", max);
    printf("exited\n");
    return max;
}

Problem:

Your code does not work when the key word is at the end of a line .

That is because your max is updated inside that while loop and the while loop terminates when the null character is found. Since the null character is always appended to the end of your input string, the last word in a string does not contribute to the output. In this edge case, the loop does not give a chance to execute that else block in the final iteration.

In fact, your code will pass only Test Case 2 because all other cases contain the key word at the end of the input string.

Solution:

Even if you rectify that, your code may still fail if the sentence contains a punctuation mark other than the period .

For example: "Test Case!"

The new code will count "Case!" as a word of length 5 which is greater than the length of "Test" or "Case", and give a wrong answer.

You may look into some library functions that C has to offer in order to help you pass all edge cases.

If you need more assistance, I have made the required modifications to your code:

while( *(s) != '\0' )
{
    // if ( *(s) != '\0' && *(s) != ' ' && *(s) != '.' )
    // Why check the null character again?
    // Spaces and period will not be the only punctuation marks
    // You can check for all punctuation marks using ispunct() from <ctype.h>
    if (!isspace(*s) && !ispunct(*s))
    {
        count++;
        printf("current count is %d\n", count);
        // You can update max here
        if(count > max)
        {
            max = count;
            printf("There is a new max! It is %d\n", max);
        }
    }
    /*
    Now you can eliminate this block of code
    else
    {
        if(count>max)
        {
            max = count;
            printf("There is a new max! It is %d\n", max);
            count = 0;
        }
        count = 0;
        printf("count is resetted!\n");
    }
    */
    // You can reset count after all that
    else
    {
        count = 0;
        printf("count is resetted!\n");
    }

    s++;
    printf("reach the end of the while loop\n");
}

The code assumes that the input will be a proper English sentence.

PS This answer earned me the 1K reputation :)

For starters the function parameter should be declared with the qualifier const because within the function the passed string is not being changed. And the function return type should be size_t . It is the return type of the function strlen or the type of the value returned by the sizeof operator.

size_t longWordLength( const char *s);

The last word of a string does not take part in the calculation of the maximum word because the loop stops its iterations as soon as the next character is the terminating zero character '\\0' .

It will be a bad idea to process the size of the last word outside the loop. All processing should be done within the loop.

Also your function does not take into account punctuation characters except the point.

For example for a sentence like this "How are you?" your function will give incorrect result.

Instead of checking each character whether it is for example a blank or not you could use standard C functions like strspn and strcspn .

Here is a demonstrative program that shows how the function can be implemented.

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

size_t longWordLength( const char *s )
{
    const char *delim = " \t";

    size_t max = 0;

    while ( *s )
    {
        s += strspn( s, delim );

        if ( *s )
        {
            const char *first = s;

            s += strcspn( s, delim );

            const char *last = s;

            while ( last != first && ispunct( ( unsigned char )*( last - 1 ) ) )
            {
                --last;
            }

            if ( max < last - first ) max = last - first;
        }
    }

    return max;
}

int main(void) 
{
    const char *s = "Why are not you using string functions?!";

    printf( "The size of the longest word is %zu\n", longWordLength( s ) );

    return 0;
}

The program output is

The size of the longest word is 9

Another approach is to write two functions similar to strspn and strcspn that deal with blank and punctuation symbols.

Here is a demonstrative program.

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

size_t count_non_alpha( const char *s )
{
    size_t n = 0;

    while ( isblank( ( unsigned char )s[n] ) || ispunct( ( unsigned char )s[n] ) )
    {
        ++n;
    }

    return n;
}

size_t count_alpha( const char *s )
{
    size_t n = 0;

    while ( s[n] && !isblank( ( unsigned char )s[n] ) && !ispunct( ( unsigned char )s[n] ) )
    {
        ++n;
    }

    return n;
}

size_t longWordLength( const char *s )
{
    size_t max = 0;

    while ( *s )
    {
        s += count_non_alpha( s );

        if ( *s )
        {
            const char *first = s;

            s += count_alpha( s );

            if ( max < s - first ) max = s - first;
        }
    }

    return max;
}

int main(void) 
{
    const char *s = "Why are not you using string functions?!";

    printf( "The size of the longest word is %zu\n", longWordLength( s ) );

    return 0;
}

The program output is the same as shown above.

Please refer to my comment to your original question .
You can resolve your problem by adding the following code, after your while loop.

if (*(s - 1) != ' ' && *(s - 1) != '.' )
{
    if(count>max)
    {
        max = count;
        printf("There is a new max! It is %d\n", max);
    }
}

The code checks the last character in the input string. If it is not a word terminating character, then you didn't compare the last word with the current max in the loop and hence you do it after the loop completes.

  • use isalpha() to check the kind of character
  • don't forget to count the final word if it is followed by a '\\0'

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

unsigned longest_word(char *str)
{
unsigned length,longest;

for(longest=length = 0; ; str++) {
    if (isalpha(*str)) { length++; continue; }
    if (length > longest) longest = length;
    length = 0;
    if (!*str) break;
    }
return longest;
}

int main(void)
{
char * string1 = "The longest word is short";
char * string2 = "The longest word is unbelievable";

printf("%s: %u\n", string1, longest_word( string1) );
printf("%s: %u\n", string2, longest_word( string2) );

return 0;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM