【问题标题】:C print longest wordC 打印最长的单词
【发布时间】:2019-05-06 08:42:36
【问题描述】:

我编写了这个程序来查找并打印出最长的单词([a-zA-Z] 字符的连续字符串),其中字符串是用户输入的。该代码有效,但确实有一个错误,如果我输入任何特殊字符,如“!”输出将打印出最长的单词以及其他一些奇怪的字符。如果我不输入任何特殊字符,程序将按预期工作。我确信这很简单,但我无法弄清楚是什么导致了这个错误。 任何改进代码的方法都将不胜感激。

感谢大家的宝贵时间。

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

#define MAX_INPUT 1000

void LongestWord(char sen[]);

int main(void) {
  char input[MAX_INPUT];

  LongestWord(fgets(input, MAX_INPUT, stdin));
  return 0;
}

void LongestWord(char sen[]) {
    int i, current_len, longest_len, input_length;

    input_length = strlen(sen);

    char temp_string[input_length];
    char longest_string[input_length];

    current_len = longest_len = 0;

    for (i = 0; i < input_length; i++) {
        //If it is a letter
        if ((sen[i] >= 97 && sen[i] <= 122) || (sen[i] >= 65 && sen[i] <= 90)) {
            temp_string[current_len] = sen[i];
            current_len++;
        } else {
            if (current_len > longest_len) {
                //Clear longest string
                memset(longest_string, 0, sizeof(longest_string));

                //Copy temp_string to longest string
                strcpy(longest_string, temp_string);

                //set longest length equal to current
                longest_len = current_len;

                //Clear temp_string
                memset(temp_string, 0, sizeof(temp_string));
            }
            current_len = 0;
        }
    }

    printf("Longest string: %s\n", longest_string);
}

【问题讨论】:

  • 使用函数/宏isalpha可能会使代码更易读tutorialspoint.com/c_standard_library/c_function_isalpha.htm
  • 当字符串中没有字母时,longest_string 未初始化。这就是“奇怪的字符”的来源。将memset 移到循环之前。
  • 一般不要使用“幻数”,如 92、122、65 和 90,而可以使用 'a'、'z'、'A'、'Z'。跨度>
  • 您可以在这里做的最好的事情是使用您最喜欢的调试器单步执行程序。这样做比让 SO 上的某个人为您指出问题所学到的要多得多。
  • 关于:char temp_string[input_length]; 这不会为尾随的 NUL 字节留出空间。建议:char temp_string[ input_length +1 ];

标签: c


【解决方案1】:

问题是:

  • temp_string 和最长字符串should be defined with a size ofinput_length + 1`
  • 您应该使用*longest_string = '\0';longest_string 设置为一个空字符串,以避免在行中没有字母时打印未初始化的数组。
  • 避免在代码中硬编码 ASCII 值,它不可读。您可以使用(sen[i] &gt;= 'a' &amp;&amp; sen[i] &lt;= 'z') || (sen[i] &gt;= 'A' &amp;&amp; sen[i] &lt;= 'Z') 或更好地使用&lt;ctype.h&gt; 中的isalpha((unsigned char)sen[i])
  • 如果你发现一个不是字母的字节,你只测试最长的字符串。这可以防止最后一个单词包含在搜索中。相反,您应该先找到一个字母,然后匹配所有后续字母并测试您是否找到了更长的单词。
  • memset 的调用太过分了。您应该在temp_string 中设置空终止符和temp_string[current_len] = '\0';,以便strcpy 可以将其复制为C 字符串并摆脱memset 调用。

您实际上不需要复制子字符串,只需跟踪当前和最长单词的偏移量:

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

void LongestWord(const char *sen) {
    int i, len, best_start, best_len;

    best_start = best_len = 0;
    for (i = 0; sen[i] != '\0'; i++) {
        if (isalpha((unsigned char)sen[i]) {
            // we have a letter: compute the word length
            for (len = 1; isalpha((unsigned char)sen[i + len]; len++)
                continue;
            if (len > best_len) {
                // remember the longest word's offset and length
                best_start = i;
                best_len = len;
            }
            // skip all letters (-1 because of i++ in the for loop)
            i += len - 1;
        }
    }
    // use `%.*s` to print a substring with printf
    printf("Longest string: %.*s\n", best_len, sen + best_start);
}

【讨论】:

  • 感谢您花时间指出这一切。现在更有意义了。
猜你喜欢
  • 2016-06-14
  • 1970-01-01
  • 2021-04-05
  • 2013-01-21
  • 1970-01-01
  • 2020-06-11
  • 1970-01-01
  • 2022-01-11
  • 2021-12-29
相关资源
最近更新 更多