【问题标题】:Weird characters while getting str from a file in C从 C 中的文件中获取 str 时出现奇怪的字符
【发布时间】:2018-10-18 17:23:30
【问题描述】:

我试图获取文件的内容并将其放入一个字符串中。当我运行我的程序并打印字符串时,我得到了文件的内容以及一些奇怪的字符。

我的代码:

int size = 0;
char ch = 0;
char* content = 0;
FILE* fs = fopen(file, "r");
//getting file's content and put it into a string
while (ch != EOF)
{
    ch = (char)fgetc(fs);
    size++;
    content = myRealloc(content, size);
    content[size - 1] = ch;
} 
printf("%s", content);

我的Realloc:

char* myRealloc(char* array, int size)
{
    char* temp = 0;
    temp = realloc(array, size * sizeof(char));
    return temp;
}

文件内容:

1,2,3,4
5,6,7,8
a,b,c,d
e,f,g,h

当我打印时:

1,2,3,4
5,6,7,8
a,b,c,d
e,f,g,h ²²²²ר─

【问题讨论】:

  • 如果ch = (char)fgetc(fs); 正在读取EOF 怎么办?你也没有展示你是如何打印它的。
  • 你到底有什么不明白的?首先,没有等于EOFchar 值。它是int。所以你的while 条件永远不会成立。其次,根据EOF 将值分配到数组中测试该值。第三 - 您没有显示负责输出的代码。
  • 完全正确 - 不要试图强制理解类型,使用函数返回的类型 - 这是有原因的。有一个常见的假设“我正在使用字符,所以我的类型必须是 char”,但请记住 'A' 的类型为 int,您可以使用 sizeof('A') 进行验证。
  • 请阅读Under what circumstances may I add “urgent” or other similar phrases to my question, in order to obtain faster answers? - 总结是这不是解决志愿者的理想方式,并且可能会适得其反。请不要将此添加到您的问题中。
  • 另外,请不要add chatty material - 编辑倾向于删除它。简洁规则:-)

标签: c file debugging printing char


【解决方案1】:

循环中的语句ch = (char)fgetc(fs); 也尝试打印EOF,这是不应该的。

只需将该代码块替换为

while ( (ch = fgetc(fs)) != EOF) { /* fetch the char & check the condition */
      putchar(ch);
      size++;
      content = myRealloc(content, size);
      content[size - 1] = ch;
}
size++;
content = myRealloc(content, size);
content[size - 1] = '\0';
print("%s", content);

还要查看fgetc() 的手册页,它返回int。所以将ch 输入为int

 int fgetc(FILE *stream);

除非您没有定义print(),否则print("%s", content); 也应该是printf("%s", content);

最后也是最重要的,一旦工作完成,不要忘记通过调用 free() 函数来释放动态分配的内存。

【讨论】:

  • 投反对票,因为ch 需要输入int,如果您这样做:(ch = fgetc(fs)) != EOF。请参阅 C 常见问题解答中的 this
  • @achal 你做的时候是不是溢出来了:content[size] = '\0';?
  • 好的。看起来你编辑了你的帖子。但这仍然是错误的,伙计。
  • 这个答案不正确,你写的是你没有分配的内存。
  • 是的@JeremyPare 有效点。 OP 需要为'\0' char 分配然后终止它。
【解决方案2】:

您的字符串不是以空值结尾的。您需要分配足够的空间来保存最后一个空字符,例如temp = realloc(array, (size + 1) * sizeof(char));,最后执行类似content[size] = '\0' 的操作。然而,使用realloc 可能是最糟糕的方式来做你想做的事情。

我会使用stat 来查找文件的大小,然后使用mmap 将文件映射到内存,然后将malloc 映射到文件的大小,然后将memcpy 映射到malloced记忆。 realloc 是邪恶的,性能明智。

这是一个大大优于原始代码的替代方案:

#include <stdlib.h>
#include <stdio.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>

int main(int argc,char** argv){
    if (argc != 2){
      printf("Usage: %s {filename}\n",argv[0]);
      return 1;
    }
    int fd = open(argv[1], O_RDONLY);
    // @todo: check if fd is valid
    struct stat st;
    int ret = fstat(fd,&st);
    // @todo: check ret
    void* mapped_memory = mmap(NULL,st.st_size,PROT_READ,MAP_SHARED,fd,0);
    // @todo: check mapped_memory that is not null
    char* str = (char*)malloc(sizeof(char)*(st.st_size + 1));
    // @todo: check that str is not null
    memcpy(str,mapped_memory,st.st_size);
    str[st.st_size] = '\0';
    printf("%s",str);
    free(str);
    munmap(mapped_memory,st.st_size);
    close(fd);
    return 0;
}

【讨论】:

  • (专业提示:编写答案时,很少需要 HTML 换行符。段落更具可读性,可将同一主题的句子分组。只需使用两次 Enter/Return 键即可创建一个新段落)。
【解决方案3】:

在末尾添加空字符:

int size = 0;
int ch = 0;
char* content = 0;
FILE* fs = fopen(file, "r");
//getting file's content and put it into a string
while ((ch = fgetc(fs)) != EOF)
{
    size++;
    content = myRealloc(content, size);
    content[size - 1] = (char)ch;
}
size++;
content = myRealloc(content, size);
content[size - 1] = '\0';
print("%s", content);

编辑:另外,正如@achal 所指出的,您正在尝试添加 EOF 字符,因为当您阅读它时,您已经处于 while 循环中。我相应地修改了我的代码。

【讨论】:

    【解决方案4】:

    关于:

    printf("%s", content);
    

    填充content 内容的代码未能NUL 终止该字符数组。

    (并且分配的内存没有足够的空间来追加 NUL 字符)

    所以对printf() 的调用将继续输出字符,直到找到 NUL 字符。

    这就是输出垃圾字符的根本原因。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-07-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多