【问题标题】:Random characters at the end of C read fileC读取文件末尾的随机字符
【发布时间】:2022-01-21 07:37:14
【问题描述】:

我一直在尝试使用从this 答案中获得的代码读取文件。

这是我的代码:

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

char * readfile(FILE * f)
{
    char * buffer = 0;
    long length;
    

    if (f)
    {
        fseek(f, 0, SEEK_END);
        length = ftell (f);
        fseek(f, 0, SEEK_SET);
        buffer = malloc(length);
        if (buffer) fread(buffer, 1, length, f);
        fclose(f);
    }

    return buffer;
}

int main()
{
    FILE * f = fopen("./file.txt", "r");
    printf(readfile(f));
}

我的函数确实返回文件的内容,但它也返回随机字符。

contents╪▐>c☻ú

令人惊讶的是,每次我运行代码时它们似乎都会发生变化。

contents╗╙ÿ▓.┤

我的文件的内容是“内容”。

我的问题是:如何修复我的代码以使其不返回随机字符?

【问题讨论】:

  • C 中的字符串需要 NUL 终止。 malloc(length+1) 然后在 fread NUL 之后终止以使其成为有效的 C 字符串 buffer[length]='\0'
  • 你应该像这样在缓冲区字符数组中添加空终止字符buffer[length]='\0'
  • 另外,如果文件可能包含%s,这会带来安全风险。 printf 的第一个参数应该始终 是字符串文字,或者最坏的情况是使用字符串文字参数调用format_arg 函数的结果。

标签: c random


【解决方案1】:

C 中的字符串需要以空值结尾。当您读取内容时,您的缓冲区字符串不会终止。本质上,您是根据需要打印文件内容,但读取只是继续在连续内存中进行,直到偶然到达空字符。

【讨论】:

    【解决方案2】:

    我的函数确实返回文件的内容,但它也返回随机字符。
    如何修复我的代码以使其不返回随机字符?

    没有。该函数只返回一个指针,没有任何字符。

    printf() 调用使用了那个指针,认为它是一个指向字符串 的指针。在 C 中,string 总是包含一个最终的'\0',否则它不是一个字符串。它只是一个指向缺少 空字符 的字符数组的指针,并导致 未定义的行为,因为 printf(s) 只知道从哪里开始(s),但不知道在哪里结束。

    不要打印超过分配数据的末尾。

    更好的方法:返回一个指向字符串的指针。为数据和最后一个空字符分配足够的空间,并形成一个字符串让printf()知道在哪里停止。

    最好也添加错误检查。

    // Let calling code close the file
    char *readfile_alt(FILE * f) {
      // f invalid? fseek() fail?
      if (f == NULL || fseek(f, 0, SEEK_END)) {
        return NULL;
      }
    
      long length = ftell(f);
      rewind(f);
      // Did ftell() fail?  Is the length too long?
      if (length == -1 || length >= SIZE_MAX) {
        return NULL;
      }
    
      // Convert from long to size_t
      size_t ulength = (size_t) length;
      char *buffer = malloc(ulength + 1);
      // Allocation failed? Read incomplete?
      if (buffer == NULL || fread(buffer, 1, ulength, f) != ulength) {
        free(buffer); 
        return NULL;
      }
      buffer[ulength] = '\0'; // Now buffer points to a string
    
      return buffer;
    }
    

    另外,printf() 需要一个 format 字符串,其中"%" 具有特殊含义。最好使用printf("%s", readfile(f));

    int main() {
      FILE * f = fopen("./file.txt", "r");
      if (f) {
        char *s = readfile(f);
        if (s) {
          printf("%s\n", s);
          free(s); // Free resource when done with them.
        }
        fclose(f); // Free resource when done with them.
      }
    }
    

    更好的代码会考虑文件可能意外包含空字符。再等一天。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-04-11
      • 2011-09-16
      • 2019-01-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-27
      • 1970-01-01
      相关资源
      最近更新 更多