【问题标题】:Reading the files contents to the allocated string读取文件内容到分配的字符串
【发布时间】:2021-03-14 21:02:32
【问题描述】:

我正在尝试读取文件的内容并将这些内容复制到具有动态内存的字符串中。然而,我的程序一直只为 x 分配 8 个字节。最终,我试图创建一个通用函数,它可以从文件中读取内容,然后将内容作为字符返回。任何帮助表示赞赏。

char* readFile(unsigned long size, char *fileName) {

FILE *file = fopen(fileName, "r");
int c;
if(file != NULL)
{
    while(c != EOF){ //calculate size of file
        c = fgetc(file); //store character
        size++;
    }
    char *x = (char *)malloc((size) * (sizeof(char))); // Size of x = 8 and I'm not sure why
    rewind(file);
    printf("\n");

    int i = 0;
    while(size - 1 > i){ //Reading the files contents to the allocated string
        c = fgetc(file); //store character
        if(c == EOF){
            break;
        }
        x[i] = c;
        i++;
    }

    fclose(file);
    printf("Done Reading");
 }
else
{
 printf("\nError: Unable to open the file for Reading.\n");
}
rewind(file);
return 0;

}

我在运行时遇到分段错误

char* str = readFile(size, originalFile);

【问题讨论】:

  • fgetc() 返回int,而不是char。将从fgetc() 返回的int 值填塞到char 中意味着您将无法可靠地检测到EOF - 因为EOF 不是char。跨度>
  • 您如何准确测量您分配的内存?
  • while(c != EOF) 在第一次迭代中 c 未初始化使用。
  • readFile 返回 char * 但其中唯一的 return 语句是:return 0;(即)它返回 NULL想要返回什么?
  • 为什么要传递size 作为参数?它被 添加 到函数中,但您必须依靠调用者传递 0。您可能想要的是:size_t readFile(const char *fileName) 作为签名并想要做:return size; 您需要一个局部变量:函数中的size_t size = 0;。实际上,您可能希望 off_t 而不是 size_t 来处理非常大的文件。

标签: c file malloc


【解决方案1】:

我会使用stat 首先获取文件的大小

stat() 检索有关指向的文件的信息 按路径名;

然后我对您的函数进行了一些微小的修改以使其工作:

#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>

char* readFile(char *fileName) {
    FILE *file;
    struct stat st;

    if (!(file = fopen(fileName, "r")))
        return NULL;
    stat(fileName, &st);
    unsigned long size = st.st_size;
    char *x;
    if (!(x = (char *)malloc((size + 1) * (sizeof(char))))) // Size of x = 8 and I'm not sure why
        return NULL;
    unsigned long i = 0;
    while (i < size) //Reading the files contents to the allocated string
        x[i++] = getc(file);
    x[i] = '\0';
    fclose(file);
    printf("Done Reading\n");
    return x;
}

int main(void) {
    char *fileName = "a.txt";

    char *res = readFile(fileName);
    printf("%s\n", res);
    return 0;
}

别忘了在 C strings are NULL terminated 中,你需要 malloc size+1 来添加最后的 '\0'。

【讨论】:

  • 我会用if (!(x = malloc(size + 1))) ,当前的表达式是不必要的复杂,char 普遍是 1 个字节,i 也应该是unsigned long,避免比较无符号和有符号类型。
  • 是的,用 C# 技巧来克服 Windows Unicode 混乱。
【解决方案2】:

这是(恕我直言)查找文件大小的更简单方法:

char *readFile(const char *fileName)
{

    unsigned long size = 0;
    char *x;
    FILE *file = fopen(fileName, "r");
    int c;
    if (file != NULL)
    {
        fseek(file, 0, SEEK_END);            /* SET the position at EOF */
        size = ftell(file);                  /* Record the position at EOF to return size of file */
        rewind(file);                        /* SET position back to Origin */
        printf("size detected %ld\n", size); // reads correct size

        x = (char *)malloc((size) * (sizeof(char)));
        rewind(file);
        printf("\n");

        int i = 0;
        while (size - 1 > i)
        {                    //Reading the files contents to the allocated string
            c = fgetc(file); //store character
            if (c == EOF)
            {
                break;
            }
            x[i] = c;
            i++;
        }

        fclose(file);
        printf("Done Reading\n");
    }
    else
    {
        printf("\nError: Unable to open the file for Reading.\n");
        return NULL;
    }
    rewind(file);

    return x; // * you need to return x not zero
}

成功读取文件内容:

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

int main()
{
    char *data;
    data = readFile("records.txt");
    printf("%s\n", data);
    return 0;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-10-23
    • 2019-11-02
    • 1970-01-01
    • 2022-09-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多