【问题标题】:Another question about fopen in C from a beginner初学者关于 C 语言中 fopen 的另一个问题
【发布时间】:2011-06-12 18:15:17
【问题描述】:

我是 C 和一般编程的新手。我想编写一个 C 程序来读取文本文件的内容并将其打印到控制台。我有一个名为 test.txt 的文本文件,其中包含字符串“Hi”。我用以下代码创建了一个 C 程序:

#include <stdio.h>

main()
{
  FILE *myfile;
  myfile=fopen("test.txt", "r");
  printf("%s", myfile);
  fclose(myfile);
}

这个程序编译正常(至少使用默认设置),但是当我运行程序时,字符串“Hi”没有出现。你能帮我看看我做错了什么吗?谢谢。

另外,你有什么推荐的 C 参考网站吗?我正在寻找一个包含 C 语言规范的网站,可能包括如何使用库函数的示例。

非常感谢您的宝贵时间。

安德鲁

卡内基梅隆大学

【问题讨论】:

    标签: c printf fopen


    【解决方案1】:

    您正试图将myfile 值指向的位置的字符串打印到控制台。这显然是不正确的(如果你不知道为什么,那是因为 %s 需要 char*,而不是 FILE*,并且 FILE* 不指向文件的内容。)。

    要从文件中读取数据,请使用fread

    char buf[80] = {0}; // fill buf with NULLs
    fread(buf, sizeof(char), 2, myfile); // read 2 bytes 
    

    如果你想将整个文件读入缓冲区,事情会稍微复杂一些,因为你必须确定文件的长度,然后在正确大小的堆上动态分配内存来保存文件。 the fread page at cplusplus.com上有很好的教程。

    【讨论】:

    • sizeof(char) 按定义为 1。
    【解决方案2】:

    这是因为您没有读取该文件。要读取文件,可以使用freadfgets方法

    【讨论】:

      【解决方案3】:

      要读取一行,使用fgets 会更有意义,因为它会读取到行终止符 (\n)。

      char line[256]
      fgets(line, sizeof(line), file);
      printf("%s", line);
      

      【讨论】:

        【解决方案4】:

        这是最安全的方法。

        #include <stdio.h>
        #include <string.h>
        
        main()
        {
          FILE *myfile;
          char buf[80];
          myfile=fopen("test.txt", "r");
          while(!feof(myfile)){
            memset(buf, 0, 80);
            fread(buf, sizeof(char), sizeof(char)*79, myfile);
            printf("%s", buf);
          }
          fclose(myfile);
        }
        

        feof 检查以确保尚未到达文件末尾。 memset,将缓冲区中的所有内容设置为 0。fread 将从文件中读取多达 79 个字符到缓冲区中。请注意,最大大小应为 79 而不是 80,即缓冲区的大小。这是因为数组中的最后一个位置应该为空字符 '\0' 保留,它向 C 表明字符串已经结束。

        不要使用fgets。此函数被认为是不安全的,因为它可能导致缓冲区溢出,其中字符写入超出为字符串分配的内存空间。

        如果您是一般编程新手,我建议您在学习 C 之前先学习一种对初学者更友好的语言,例如 Python。C 对新程序员来说被认为是棘手的,因为它没有自动内存管理、面向对象编程功能或大型标准库。

        【讨论】:

          【解决方案5】:

          问题是您试图打印 FILE 指针而不是文件的内容 - 您需要一个变量来存储它。

          看到其他方法很有趣。这是 fscanf() 的实现 -

          #include <stdio.h>
          #define FILENAME "test.txt"
          
          int main(void)
          {
              FILE *myfile;
              char string[81] = {'\0'};
          
              myfile=fopen(FILENAME , "r");
              if(myfile == NULL)
              {
                  printf("The file test.txt could not be found! Exiting...\n");
                  return -1;
              }
              while(fscanf(myfile, " %80[^\n]s", string) != EOF)
              {
                  printf("%s\n", string);
              }
              fclose(myfile);
          
              return 0;
          }
          

          当您打开文件时,如果操作失败将返回 NULL,最好明确检查这一点,以便您知道出了什么问题。

          fscanf() 返回成功读取的次数(此处为 1,对于 1 次转换为字符串),如果已到达文件末尾,则返回 EOF。格式字符串首先使用空格来删除输入流中的所有前面的空格(换行符、空格、制表符)。

          在 scanf() 函数中使用字段宽度说明符(80)意味着只能读取这么多字符,因此输入不能超出分配的空间 - 很有用!

          [^] 表示流将被读取,直到遇到指定的字符。 [^\n] 是一种获取带有空格的字符串的方法,因为 scanf() 系列通常只读取遇到字符串的空格。请注意,不会删除换行符(它仍然是流中的第一个)。

          然后打印字符串,并添加一个换行符。该程序将遍历文件中的行数(最多 80 个字符,由换行符分隔)。如果您想保留这些行,您可以将 string 设置为 char 数组并每次递增。这是 fscanf() 格式字符串中的第一个空格派上用场的地方,它将删除仍在流开头的换行符(以及任何其他前面的空格)。

          我还没有找到任何在线学习 C 的权威教程,但是有很多可用的。当前的标准对初学者不友好,但可以免费获得一个草稿:http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf

          另一个很好的资源(但不是教程)是http://c-faq.com/

          关于标准库函数的来龙去脉,我发现的最佳参考是 Harbison & Steele 的 C: A Reference Manual - 但遗憾的是它不是免费的。

          【讨论】:

            猜你喜欢
            • 2011-05-06
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-01-12
            • 2018-01-08
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多