代码不断崩溃(第 4.2 周已停止工作

Code keeps crashing (Week 4.2 has stopped working

我有一个程序必须从文件中获取最长的句子。 为此,我将第一个句子放在一个数组中,然后将以后的句子与当前最大句子的大小进行比较。

然而,比较两个数组的行为让我难以理解。 数组的 current_sentence 和 longest_sentence 都是 80 个字符长,但我想知道哪个实际上包含最长的句子(最长可达 80 个字符)。

我已经尝试过许多不同的解决方案(通过 google,其中大部分是 Whosebug 的结果)但每次尝试返回的值都是文件中的第一句话,这让我相信检查本身完全失败,或者两个数组的长度都返回为 80。

这些尝试包括(但不限于):

if((sizeof(current_sentence) / sizeof(char)) < (sizeof(longest_sentence) / sizeof(char))

if(sizeof(current_sentence) / sizeof(current_sentence[0])) < (sizeof(longest_sentence) / sizeof(longest_sentence[0]))

这是我的代码:

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

char *langste_regel(char *);

int main(void) {
    /*
     * stdout and stderr required for proper output
     */
    setvbuf(stdout, NULL, _IONBF, 0);
    setvbuf(stderr, NULL, _IONBF, 0);

    char *s = langste_regel("vb1.txt");
    if(s != NULL) {
        printf("\nde langste regel is: %s\n", s);
        free(s);
    }

    return 0;
}

char *langste_regel(char *filename) {
    FILE *file;
    file = fopen(filename, "r");

    if(file == NULL) {
        fprintf(stderr, "Kan bestand niet %s openen", filename);
    }

    char current_sentence[80];
    int len = 2;
    char *longest_sentence = (char *)malloc(sizeof(char) * len);

    fgets(longest_sentence, 80, file);

    while(fgets(current_sentence, 80, file)) {
        if(sizeof(current_sentence) < sizeof(longest_sentence)) {
            strncpy(longest_sentence, current_sentence, 80);
        }
    }

    fclose(file);

    return longest_sentence;
}

您想使用 strlen() 来获取行的长度,而不是 sizeof,后者 returns 对象占用的字节数。

改变

    if(sizeof(current_sentence) < sizeof(longest_sentence)) {

    if(strlen(current_sentence) < strlen(longest_sentence)) {

我看到的另一个问题是您只分配了 2 个字节,但在这里读取了多达 80 个字节:

  char *longest_sentence = (char *)malloc(sizeof(char) * len);

  fgets(longest_sentence, 80, file);

代码

sizeof(current_sentence)

并没有按照您的想法行事。要查找空终止字符串的长度,请使用

strlen(current_sentence)

你的代码有很多问题。

  file = fopen(filename, "r");

   if(file == NULL) {
       fprintf(stderr, "Kan bestand niet %s openen", filename);
   }

您检查 fopen() 调用是否不成功,但随后您继续使用 file 指针。您应该 return 向调用者指示错误。


  char current_sentence[80];
  int len = 2;
  char *longest_sentence = (char *)malloc(sizeof(char) * len);

  fgets(longest_sentence, 80, file);

您将 2 个字节分配给 longest_sentence,然后您尝试将多达 80 个字节读入缓冲区。您应该分配 80 个字节。

如果您打算根据需要动态增加缓冲区,您需要一个更复杂的解决方案。您需要:

  • 尝试分配 80 个字节。
  • 尝试读取 80 个字节。
  • 检查字符串是否以换行符结尾 (\n)。
  • 如果不是,请尝试 realloc() 缓冲区到更大的大小。
  • 继续阅读并重新分配,直到

    • 找到换行符,或者
    • 您已到达文件末尾,或者
    • 发生读取错误,或
    • 重新分配失败,或者
    • 您达到了预定义的最大长度。

你也不检查字符串是否读取成功。 fgets() 函数将在文件结束时 return NULL 或发生读取错误。您应该 return 给调用者一个错误提示。例如:

if (!fgets(longest_sentence, 80, file)) {
  free (longest_sentence);
  return NULL:
}

  while(fgets(current_sentence, 80, file)) {
      if(sizeof(current_sentence) < sizeof(longest_sentence)) {
          strncpy(longest_sentence, current_sentence, 80);
      }
  }

sizeof 运算符的结果是操作数 type 的大小,而不是字符串的长度。您应该使用 strlen()(并反转比较,正如您在别处提到的那样)。

while(fgets(current_sentence, 80, file)) {
    if(strlen(current_sentence) > strlen(longest_sentence)) {
        strncpy(longest_sentence, current_sentence, 80);
    }
}

strncpy() 的使用通常是有问题的。上面的调用将 总是 写入 80 个字节,而不管 current_sentence 的长度如何。通常,如果在输入字符串的前 80 个字节中没有找到零,它将 not 零终止输出字符串。但是,在 这种 情况下,它会,因为 fgets() 保证在这 80 个字符中有一个零字节。

一个简单的 strcpy() 在这里会更直接(在我看来)。