繁体   English   中英

编译错误

[英]Compilation errors

我一直在创建一个应该打开文件的函数(catalogname []) 但是,每当我编译时,我都会得到我无法弄清的两个错误。

a3.c:在函数“ openCatalog”中:

a3.c:20:警告:来自不兼容指针类型的赋值

a3.c:22:警告:return使指针从整数开始而不进行强制转换

这是我的代码:

FILE* openCatalog(char catalogname[])
{
    catalogname = fopen ("*catalogname", "r");
    if(fopen != 0)
    {
        return 1;
    }
    else 
    {
        return 0;
    }
}

在此先感谢您提供的任何见解。

有关此代码的完整解释,需要一些时间。

简短的版本是:

FILE *openCatalog(char catalogname[])
{
    FILE *fp = fopen(catalogname, "r");
    return(fp);
}

这将打开已命名的文件以供读取,并返回文件流指针。

另一个简短版本检查文件是否可以打开:

int openCatalog(char catalogname[])
{
    FILE *fp = fopen(catalogname, "r");
    if (fp != 0)
    {
        fclose(fp);
        return 1;
    }
    else 
    {
        return 0;
    }
}

注释

原始代码是:

FILE* openCatalog(char catalogname[])
{
    catalogname = fopen ("*catalogname", "r");
    if(fopen != 0)
    {
        return 1;
    }
    else 
    {
        return 0;
    }
}

除了“打开文件”之外,我们没有其他规范。 给定函数签名后,您似乎希望返回打开文件的FILE * (文件流指针)。 因此,让我们在此基础上对代码进行评论。

  • 功能原型行可以; 可以使用char const catalogname[]来强调该函数不会修改文件名,但这只是一种改进,而不是错误修复的更改。

  • 该类型的catalogname在功能char * 在函数的参数列表中,数组大致等同于指针。 我通常会写FILE *openCatalog(char const *catalogname)来强调函数内,它是char const *变量。 但是,使用您使用的数组符号是100%合法的。 对我而言,使用指针表示法纯粹是一种风格偏好。

  • 下一个可执行行有两个问题。 fopen()的函数调用在技术上没有错,尽管它会打开一个具有固定名称*catalogname的文件,而不是使用变量catalogname指定的文件。 要解决此问题,您需要删除引号。 *将给您一个字符而不是一个字符串,它是文件名的第一个字符。 因此,也请删除*

  • 这使您留给fopen()返回一个值,实际上是一个FILE * ,并将其分配给catalogname ,一个char * 这是类型不匹配,编译器会警告该类型不匹配。 如第一次重写所示,更一般的处理方法是:

     FILE *fp = fopen(catalogname, "r"); 

    这说明了您的错误消息:

     a3.c:20: warning: assignment from incompatible pointer type 
  • 我们不知道您的目录是文本文件还是二进制文件。 如果它是一个二进制文件,那么如果您在Windows上(它确实很重要),则应该使用"rb"将其打开,并且在类似Unix的系统上也可以正常工作(在文本和二进制文件之间没有区别)文件)。

  • 代码中的下一行是有条件的:

     if (fopen != 0) 

    这实际上检查函数fopen()的函数指针是否为null。 C标准保证在托管环境(您正在使用)中,没有任何函数指针为null。 因此,编译器可以优化该测试以假定条件始终为真。

    您实际需要的是对结果的测试:

     if (fp != 0) 
  • 然后,您有两个return语句,一个返回1,一个返回0。一个返回1引发有关将整数转换为指针的警告,因为该函数已定义为返回FILE *并且1是整数。

    这说明了您的其他警告消息:

     a3.c:22: warning: return makes pointer from integer without a cast 
  • 返回值为0的返回值不会产生警告,因为0是一个空指针常量,并且对于像这样的函数来说,这是一个有效值。

  • 代码可能应该简单地从fopen()返回值。 在此函数或调用函数中的某处测试该值是正确的,以确保打开成功。 您可以在这里进行测试:

     if (fp == 0) err_report_and_exit("Failed to open file %s (%d: %s)\\n", catalogname, errno, strerror(errno)); 

    使用errnostrerror()意味着还应该包含标题:

     #include <errno.h> #include <string.h> 
  • 该代码应从fopen()返回文件流:

     return fp; 

总体而言,这导致:

FILE *openCatalog(char catalogname[])
{
    FILE *fp = fopen(catalogname, "r");
    if (fp == 0)
        err_report_and_exit("Failed to open file %s (%d: %s)\n",
                            catalogname, errno, strerror(errno));
    return(fp);
}

如果该功能旨在检查文件是否可以打开以供读取,则上面引用的问题几乎相同。 我首先显示的修订代码有些冗长。 由于假定的目的是检查文件是否可以打开,因此调用代码应负责处理“无法打开的情况”; 它知道要生成哪种诊断。 这是该修订版的紧凑版本,但是this和上面的那个的目标代码是相同的。

int openCatalog(char catalogname[])
{
    FILE *fp = fopen(catalogname, "r");
    if (fp != 0)
    {
        fclose(fp);
        return 1;
    }
    return 0;
}

err_report_and_exit()简单实现是:

#include "errreport.h"
#include <stdio.h>
#include <stdlib.h>
#include <starg.h>

void err_report_and_exit(char const *format, ...)
{
    va_list args;
    va_start(args, format);
    vfprintf(stderr, format, args);
    va_end(args);
    exit(EXIT_FAILURE);
}

“ errreport.h”标头可能是:

#ifndef ERRREPORT_H_INCLUDED
#define ERRREPORT_H_INCLUDED

#ifdef __GNUC__
#define PRINTFLIKE(n,m) __attribute__((format(printf,n,m)))
#define NORETURN()      __attribute__((noreturn))
#else
#define PRINTFLIKE(n,m) /* If only */
#define NORETURN()      /* If only */
#endif /* __GNUC__ */

extern void err_report_and_exit(char const *format, ...) PRINTFLIKE(1,2) NORETURN();

#endif /* ERRREPORT_H_INCLUDED */

特定于GCC的位意味着您将获得与直接使用printf()相同级别的格式错误报告。

(此代码以更大的程序包为模型,该程序包系统地使用err_作为函数前缀。在该程序包中,该函数将是err_error() 。这就是为什么它是err_而不是error_ -尽管解释输入的时间比输入的时间长大文件包包含在文件stderr.cstderr.h ,尽管有一个论点说使用std前缀它已经stderr.c stderr.h 。但是,这是我的标准错误报告包。)

  • 指针类型不兼容

     catalogname = fopen ("*catalogname", "r"); 

    catalogname是一个chars数组( char catalogname[] ),而fopen()返回一个文件指针( FILE* )。 自然地,将文件指针分配给char数组(这是另一种类型的指针,而且是无法分配的)没有任何意义。

  • return使指针从整数开始而无需强制转换

    您在此处声明函数返回FILE*FILE* openCatalog(...) 但是,您的return语句为return 1; return 0; 在那里,编译器认为您想返回值为1(或0)的文件指针,从而返回响应。

FILE* openCatalog(char catalogname[])

最好使用char *catalogname ,因为实际上并没有传递数组 -您正在获得指向字符的指针。 (这是对C的一个有趣的小怪癖。)尽管如此,但我发现提醒您,只得到一个指针是非常受欢迎的。

catalogname = fopen ("*catalogname", "r");

fopen(3)返回FILE*对象。 您不能将FILE*分配给char []变量。

如果要在fopen(3)调用中使用catalogname变量,请使用它:

FILE *f = fopen(catalogname, "r");
if(fopen != 0)

在这种情况下, fopen是一个函数指针 您不是将前一个fopen()调用的返回值与0 ,而是将函数指针0 那不是你想要的。

    return 1;

您声明了要返回FILE *函数,这就是应该返回的内容-而不是整数。

重新编写的版本如下所示:

FILE* openCatalog(char *catalogname) {
    FILE *f = fopen(catalogname, "r");
    if (!f)
        perror("Unable to open file");
    return f;
}

实际上,您有很多错误,其中一些已被掩盖

第一:

catalogename = fopen("*catalogname", "r");

是错的。 我认为您想要的是:

FILE *fPtr = fopen(catalogname, "r");

然后,之后,函数的主体发生了很大变化:

if (fPtr == NULL || ferror(fPtr) != 0) // if the file isn't NULL or if there is no errors with opening the file...
{
    if (fPtr != NULL) // never try to close a NULL file ...
        fclose(fPtr);

    return NULL; // best way to report an error in C - return NUL or set errno
}

else
{
     return fPtr; // return the file we just made.
}

第一个警告:

您正在将FILE*fopen返回的内容)分配给catalogname名称char []

第二个警告:

当您返回整数01该函数返回FILE*类型

您还想要其他东西吗? 喜欢:

FILE* openCatalog(char catalogname[])
{
   FILE* file = fopen (catalogname, "r");

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM