【问题标题】:Why can't I read text in a file?为什么我无法读取文件中的文本?
【发布时间】:2021-04-19 13:17:22
【问题描述】:

我正在尝试打印文件中包含的内容,但是当部分代码包含在如下函数中时它不起作用:

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

main() {    
    FILE *file;
    file = fopen(path, "rt"); //Instead of "path" there is the file's path

    read(file);
    fclose(file);
    return 0;
}

void read(f) {
    int c;

    if (f) 
        while ((c = getc(f)) != EOF)
            putchar(c);

}

但是,当我像这样在 main 中编写所有内容时,它确实有效:

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

main() {    
    FILE *file;
    file = fopen(path, "rt");

    int c;

    if (file) 
        while ((c = getc(file)) != EOF)
            putchar(c);
    fclose(file);
    return 0;
}

为什么它不起作用?任何帮助将不胜感激

【问题讨论】:

  • 你的 C 编译器没有给出任何警告吗? clang 和 gcc 都会使用默认参数产生一些错误和警告。
  • 函数main()只有两个有效签名,它们是:int main( void )int main( int argc, char * argv[] )
  • 这里是函数的原型:read():ssize_t read(int fd, void *buf, size_t count);read() 是一个众所周知的 C 库函数,尝试用自己的代码替换 C 库函数是一种糟糕的编程习惯, 建议叫它MyRead()
  • 关于:file = fopen(path, "rt"); 1) 变量:path 未定义,2) 始终检查 (!=NULL) 返回值以确保操作成功,如果不成功 (== NULL) 然后调用perror( "fopen failed" ) 这样您的错误消息和系统认为发生故障的文本原因都输出到stderr
  • 关于:void read(f) { 编译器将假定参数的类型为int,这将不起作用,要更正此问题,请在 main() 之前放置一个原型,类似于:`void read(文件 f);

标签: c file


【解决方案1】:

回答你的问题, 你忘了在函数中声明 f 的类型

void read(f) {

应该是

void read(FILE *f) {

if (f) 

应该更多

if (f!=NULL) 

函数最终代码:

void read(FILE *f) {
int c;

if (f!=NULL) 
    while ((c = getc(f)) != EOF)
        putchar(c);

}

注意:您应该定义 main 的类型(因为您使用了 return 0;所以它是 int main() 最后:你应该在 main (depends on your compiler) 之前移动函数

最终代码:

#include <stdio.h>
 #include <stdlib.h>
 void read(FILE *f) {
int c;

if (f!=NULL) 
    while ((c = getc(f)) != EOF)
        putchar(c);

 }
 int main() {    
FILE *file;
file = fopen(path, "rt"); //Instead of "path" there is the file's path

read(file);
fclose(file);
return 0;
 }

【讨论】:

    【解决方案2】:

    C 编译器将假定未声明的函数参数或其类型未指定为 int 以与旧规范兼容。 在这种情况下,参数实际上应该是FILE*intFILE* 的大小在某些环境下可能会有所不同,因此让编译器做出错误的假设可能会造成麻烦。

    您应该在使用它们之前声明(或定义)函数并指定参数的类型,尤其是当您使用int以外的类型时。

    #include <stdio.h>
    #include <stdlib.h>
    
    /* add declaration of the function */
    void read(FILE* f);
    
    /* add types */
    int main(void) {
        FILE *file;
        file = fopen(path, "rt"); //Instead of "path" there is the file's path
    
        read(file);
        fclose(file);
        return 0;
    }
    
    /* add type of argument */
    void read(FILE* f) {
        int c;
    
        if (f) 
            while ((c = getc(f)) != EOF)
                putchar(c);
    
    }
    

    【讨论】:

      【解决方案3】:

      您的文件必须经过严格修复才能运行,所以恐怕您在发送之前没有测试您的代码。无论如何,我已经进行了一系列更改,我将在 diff 文件输出中对它们进行注释,以便您知道更改了什么以及如何更改。在行更改之前用- 发出替换信号,并用+ 发出信号

      --- pru4358.c-orig      2021-04-20 10:05:49.236297000 +0300
      +++ pru4358.c   2021-04-20 10:08:11.266937000 +0300
      @@ -1,7 +1,11 @@
       #include <stdio.h>
       #include <stdlib.h>
       
      +char path[] = "file.txt";
      +
      

      path 变量在 main 中没有定义。每个变量或数据对象都必须在使用前向编译器声明才能使用。

      +void read(FILE *f);
      +
      

      你需要在文件中使用后添加你实现的函数的原型,否则编译器将不知道你的代码使用什么类型的参数以及它们是什么类型。

      -main() {    
      +int main() {    
      

      从很久以前,main() 需要一个返回类型int,你需要写它。编译器允许它处理非常旧的遗留代码,但不应该在新项目中使用它。如果你不这样做,编译器会假设你的函数返回int,当你稍后将它定义为void时,编译器会大声告诉你你不同意它的定义。

           FILE *file;
           file = fopen(path, "rt"); //Instead of "path" there is the file's path
       
      @@ -10,7 +14,7 @@
           return 0;
       }
       
      -void read(f) {
      +void read(FILE *f) {
      

      如上所述,您需要告知编译器数量或参数,每个参数的名称以便能够在函数内使用它们,并且非常重要:参数的类型(在本例中为FILE *

           int c;
       
           if (f) 
      

      现在,我会照原样发布文件,但是评论你不做必要事情的地方,如果你不做,那会给你带来麻烦。

      pru4358.c(已更正)

      #include <stdio.h>
      #include <stdlib.h>
      
      char path[] = "file.txt";
      
      void read(FILE *f);
      
      int main() {    
          FILE *file;
          file = fopen(path, "rt"); //Instead of "path" there is the file's path
      

      你没有检查从fopen()返回的值,如果你从fopen()得到NULL作为返回值,这可能会导致将来出现问题(我第一次执行它时发生在我身上,因为我没有file.txt. 文件)

      
          read(file);
      

      你最好不要为你的文件读取功能选择像read这样的名字。此示例有效(因为您不必使用read(2) 系统调用),但如果您为自己的函数使用任何系统调用名称(甚至是库函数名称),则会遇到麻烦。

          fclose(file);
          return 0;
      }
      
      void read(FILE *f) {
          int c;
      
          if (f) 
      

      您最好在调用read() 之前检查NULL,就在fopen()之后。你不这么认为吗? (像我一样阅读您的代码的人会认为您没有检查函数的返回值)您实际上并没有在main() 中检查它,后来fclose() 它是NULL 或不是。

              while ((c = getc(f)) != EOF)
                  putchar(c);
      
      }
      

      最后是我认为你的代码应该是这样编写的(你已经接近它了:))

      #include <errno.h>
      #include <stdio.h>
      #include <stdlib.h>
      #include <string.h>
      
      /* static, to avoid name pollution */
      static char path[] = "file.txt";
      
      void copy_file_to_stdout(FILE *f);
      
      int main() {
          FILE *file;
          file = fopen(path, "rt");
      
          if (!file) {
              fprintf(stderr, "ERROR: %s: %s\n",
                      path, strerror(errno));
              /* don't continue if the file cannot be opened */
              exit(EXIT_FAILURE);
          }
      
          /* successfuly opened, so all that follows will have sense */
          copy_file_to_stdout(file);
      
          fclose(file);
      
          return EXIT_SUCCESS;
      }
      
      /* this is a better name for the file, as you don't just read the
       * file contents, you also write them to stdout. */
      void copy_file_to_stdout(FILE *f) {
          int c;
      
          while ((c = getc(f)) != EOF)
              putchar(c);
      
      }
      

      【讨论】:

        猜你喜欢
        • 2020-09-09
        • 2020-08-11
        • 1970-01-01
        • 2023-03-18
        • 2020-01-02
        • 2021-08-23
        • 1970-01-01
        • 2022-08-14
        • 1970-01-01
        相关资源
        最近更新 更多