简体   繁体   English

找出字符串中最长单词的长度。 C语言

[英]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.问题:我似乎无法让我的测试用例 4 工作。

Question:题:

Write a C function that accepts an English sentence as a parameter, and returns the length of the longest word in the sentence.写一个C函数,接受一个英文句子作为参数,返回句子中最长单词的长度。 For example, if the sentence is "I am Tim.", then the length of the longest word "time" in sentence 3 will be returned.例如,如果句子是“I am Tim.”,则返回句子3中最长的单词“time”的长度。

Test Case 1:测试案例 1:

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

Test Case 2:测试案例 2:

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

Test Case 3:测试案例 3:

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

Test Case 4:测试案例 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.那是因为您的max在该 while 循环内更新,而 while 循环在找到空字符时终止。 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.在这种边缘情况下,循环不会在最终迭代中提供执行else块的机会。

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.事实上,您的代码只会通过测试用例 2,因为所有其他用例都包含输入字符串末尾的关键字。

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.作为长度大于“Test”或“Case”长度的 5 个单词,并给出错误答案。

You may look into some library functions that C has to offer in order to help you pass all edge cases.您可以查看 C 必须提供的一些库 函数,以帮助您通过所有边缘情况。

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 :) PS 这个答案为我赢得了 1K 的声誉:)

For starters the function parameter should be declared with the qualifier const because within the function the passed string is not being changed.对于初学者来说,函数参数应该用限定符const声明,因为在函数内传递的字符串没有被改变。 And the function return type should be size_t .并且函数返回类型应该是size_t It is the return type of the function strlen or the type of the value returned by the sizeof operator.它是函数strlen的返回类型或sizeof运算符返回的值的sizeof

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' .字符串的最后一个单词不参与最大单词的计算,因为只要下一个字符是终止零字符'\\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?"例如像这样的句子"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 .您可以使用标准 C 函数(如strspnstrcspn而不是检查每个字符是否为空白。

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.另一种方法是编写两个类似于strspnstrcspn函数来处理空格和标点符号。

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.您可以通过while循环之后添加以下代码来解决您的问题。

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.如果它不是单词终止字符,则您没有将最后一个单词与循环中的当前max进行比较,因此您在循环完成后进行比较。

  • use isalpha() to check the kind of character使用isalpha()检查字符类型
  • don't forget to count the final word if it is followed by a '\\0'如果最后一个单词后跟一个'\\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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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