用C编写一个函数,以英语句子作为参数,并返回句子中最长单词的长度

3

我有一个作业,需要编写一个函数,接受包含英语句子的数组,并返回该句子中最长单词的长度。以下是我目前编写的代码:

int longWordLength(char *s); // Function prototype

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

    printf("Enter a string: \n");
    fgets(str, 80, stdin);

    if (p = strchr(str,'\n'))
        *p = '\0'; //converts newline to null

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

int longWordLength(char *s) {
    int count = 0, max = 0;
    while (*s++ != '\0') {
        if ((*s >= 'a' && *s <= 'z') || (*s >= 'A'&& *s <= 'Z')) {
            count++;
        } else {
            if (count > max) {
                max = count;
                count = 0;
            } else
                count = 0; // word is not the longest
        }
    }
    return max;
}

我已经长期尝试诊断这个问题,但是没有结果。

这在某些测试案例中实际运行,例如:

测试案例1:

Enter a string:  
I am happy.
longWordLength(): 5

但对于像测试用例4这样的测试案例:
Enter a string:  
Hello
longWordLength(): 4 <- it prints 4 instead of 5.

由于我是为学校任务工作,所以除了 <string.h> 库之外,我不被允许使用其他任何库。寻求任何人对我的问题的友好指导,因为我似乎真的无法找出问题所在。提前感谢您。


你不需要计算字符数,只需查找空格。删除前导空格。每次遇到一个空格,就表示一个单词已经结束了。当你到达一个空格时,要前进到下一个非空格,因为单词之间可能会有连续的空格。 - Devolus
1
while (*s != '\0') { /* ... your code ... */ s++; } - pmg
3
如果除了<string.h>以外的库中没有找到printffgets,那我建议你给教授打电话确认一下他们是否真的想让你自己编写这两个函数,因为<string.h>库中都没有这两个函数。 - WhozCraig
使用GCC编译您的C代码,命令为gcc -Wall -Wextra -g,改进您的C代码以消除警告,然后使用GDB调试器来了解程序行为。改进您的C代码(希望改进其行为),并重复以上步骤直到满意。 - Basile Starynkevitch
有趣的是:“&” 代表“and”的意思来源于拉丁语的 “et”。"&c"表示“等等”。可以将 & 视为第27个字母。 - chux - Reinstate Monica
显示剩余2条评论
1个回答

2
问题出在 while (*s++ != '\0') { 这一行:你在测试字符串指针所指向的字符之前就对它进行了递增操作。只需把代码更改为:

    for (; *s != '\0'; s++) {
        ...

请注意,如果最后一个单词没有分隔符(如空格或换行符)紧随其后,则其最大长度将不被测试。但是您应该已经去除了这些分隔符。

请注意,在进行 longWordLength()计数时,不需要去除尾部的换行符即可确定正确的计数。

以下是修改后的版本:

#include <stdio.h>

int longWordLength(const char *s); // Function prototype

int main() {
    char str[80];

    printf("Enter a string: \n");
    if (!fgets(str, sizeof str, stdin))
        return 1;

    // no need to strip the newline for this test:
    printf("longWordLength(): %d\n", longWordLength(str));
    return 0;
}

int longWordLength(const char *s) {
    int count = 0, max = 0;
    for (;; s++) {
        if ((*s >= 'a' && *s <= 'z') || (*s >= 'A'&& *s <= 'Z')) {
            count++;
        } else {
            if (count > max) {
                max = count;
            }
            if (*s == '\0')
                break;
            count = 0;  // reset the counter for the next word
        }
    }
    return max;
}

你好chqrlie,感谢您澄清我的初始错误,即在计数器开始计数之前递增字符串指针。不幸的是,我无法修改int main()函数中的代码(因为它是一项作业任务)。因此,在主代码中,它实际上将换行符转换为空字符。是否有一种方法可以检查最后一个单词的计数,假设最后一个单词中没有非字母字符。例如,只有一个“hello”输入。 - Lucas
我知道这不是最有效率的方法,但我引入了另一个指针变量,并在函数中用'\n'替换了'\0',因为我无法修改主函数。现在我的代码已经可以工作了。虽然它不是最干净的解决方案,也不是我认为正确的解决方案,但它能够工作。从这个问题中得出的关键点: 1)在计数之前不要增加指针变量。 2)空字符“附加”在最后一个单词上。因此,如果我检查空字符条件,最后一个单词将不会被计算。因此,我需要修改'/0'成为一个特殊字符。 - Lucas
@Lucas:不要修补字符串,在循环中删除对“\0”进行的测试,并在检查最大长度后检查空终止符,就像我发布的版本中一样。 - chqrlie
@Lucas:很遗憾main()函数在使用fgets(str, 80, stdin);时没有进行成功测试,而且if (p = strchr(str,'\n'))中出现了未加括号的赋值作为测试(在我看来这是一种非常粗糙的风格)。应该改为if ((p = strchr(str,'\n')) != NULL) - chqrlie
1
好的!谢谢你提供的另一个提示,即运行无限for循环,并仅在检测到下部的空字符时退出。这对我的其他任务有很大帮助!问候! - Lucas

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