C 编译错误

C 编译错误,c,compilation,C,Compilation,我一直在创建一个函数,它应该打开一个文件catalogname[]。然而,每当我编译时,我都会遇到这两个我无法理解的错误 a3.c:在函数“openCatalog”中: a3.c:20:警告:来自不兼容指针类型的赋值 catalogname = fopen ("*catalogname", "r"); a3.c:22:警告:return从整数生成指针,但不使用强制转换 这是我的密码: FILE* openCatalog(char catalogname[]) { catalogname

我一直在创建一个函数,它应该打开一个文件catalogname[]。然而,每当我编译时,我都会遇到这两个我无法理解的错误

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

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

catalogname = fopen ("*catalogname", "r");
a3.c:22:警告:return从整数生成指针,但不使用强制转换

这是我的密码:

FILE* openCatalog(char catalogname[])
{
    catalogname = fopen ("*catalogname", "r");
    if(fopen != 0)
    {
        return 1;
    }
    else 
    {
        return 0;
    }
}
提前感谢您提供的任何见解

不兼容的指针类型

catalogname = fopen ("*catalogname", "r");
catalogname是字符char catalogname[]的数组,而fopen返回一个文件指针文件*。当然,将文件指针指定给char数组是一种不同类型的指针,而且,不可指定也没有任何意义

return从整数生成指针,不使用强制转换

您声明函数返回FILE*here:FILE*openCatalog。。。。但是,您的返回语句是return1;然后返回0;。在这里,编译器认为您希望返回值为1或0的文件指针,从而返回响应


事实上,你有很多错误,其中一些错误被兔子掩盖了

第一:

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.
}
第一个警告是:

您正在将fopen返回的文件*分配给catalogname,即char[]

第二个警告是:

当您返回整数0或1时,函数返回类型FILE*

你还想要别的吗?比如:

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

对这段代码的完整解释需要一段时间

简介如下:

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*FILE流指针。因此,让我们在此基础上对代码进行评论

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

函数中catalogname的类型为char*。在函数的参数列表中,数组大致相当于指针。我通常会编写FILE*openCatalogchar const*catalogname来强调在函数中,它是一个char const*变量。然而,使用您使用的数组表示法是100%合法的;对于我来说,使用指针符号纯粹是一种风格上的偏好

下一个可执行行有几个问题。对fopen的函数调用在技术上并没有错误,尽管它打开的文件是固定名称*catalogname,而不是变量catalogname中指定的文件。要解决这个问题,您需要删除引号。*将给您一个字符而不是字符串,并且它将是文件名的第一个字符。所以,把*也去掉

这样,fopen将返回一个值,实际上是一个文件*,然后将其分配给catalogname,即char*。这是类型不匹配,编译器会对此发出警告。如第一次重写中所示,更正常的处理方法是:

FILE *fp = fopen(catalogname, "r");
这说明了错误消息的原因:

a3.c:20: warning: assignment from incompatible pointer type
我们不知道您的目录是文本文件还是二进制文件。如果它是一个二进制文件,那么如果您在Windows上使用rb打开它,因为它确实很重要,而且在类Unix的系统上也可以使用rb打开它,因为文本文件和二进制文件之间没有区别

代码中的下一行是条件:

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

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

if (fp != 0)
然后有两个return语句,一个返回1,一个返回0。返回1的函数会引发关于将整数转换为指针的警告,因为该函数定义为返回文件*,而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));
使用errno和strerror意味着您还应该包括标题:

#include <errno.h>
#include <string.h>
总的来说,这导致:

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);
}
如果函数的目的是检查文件是否可以打开读取,那么上面提到的问题基本相同。我首先展示的修订代码有点冗长。因为假定的目的是检查文件是否 n打开时,调用代码应负责处理“无法打开的情况”;它知道要生成什么样的诊断。这是修订版的一个稍微紧凑的版本,但此版本和上面版本的目标代码是相同的

int openCatalog(char catalogname[])
{
    FILE *fp = fopen(catalogname, "r");
    if (fp != 0)
    {
        fclose(fp);
        return 1;
    }
    return 0;
}
err_report_和_exit的一个简单实现是:

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

这段代码以一个更大的包为模型,该包系统地使用err_u作为函数前缀。在该包中,此函数将是err_error。这就是为什么它是err_uuu而不是error_uuuuu——尽管解释键入比修复它花费的时间更长。这个大的包包含在文件stderr.c和stderr.h中,尽管有一个论点认为它使用std前缀是如履薄冰。然而,这是我的标准错误报告包

FILE* openCatalog(char catalogname[])
作为char*catalogname,这会更好,因为实际上并没有传递数组,而是得到一个指向字符的指针。这是C语言的一个有趣的小怪癖。当它起作用时,我发现提醒你只得到一个指针是非常受欢迎的

fopen3返回一个FILE*对象。不能将文件*分配给char[]变量

如果要在fopen3调用中使用catalogname变量,只需使用它:

FILE *f = fopen(catalogname, "r");
在这种情况下,fopen是一个函数指针。您不是将上一个fopen调用的返回值与0进行比较,而是将函数指针与0进行比较。那不是你想要的

    return 1;
您将函数声明为返回一个文件*,这是您应该返回的,而不是一个整数

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

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

这仍然是错误的。如果文件已成功打开,则会使其悬空而不关闭-1@Richard:该函数的原型是返回文件*。“当然,它仍然是开放的。”萨诺尔德看了看他重新制作的OP的功能。它返回一个int而不是文件*@Richard:在另一种情况下,检查版本时,在成功的情况下,我仍然看到fclose调用…在C中不允许创建具有相同名称的新变量。
FILE *f = fopen(catalogname, "r");
if(fopen != 0)
    return 1;
FILE* openCatalog(char *catalogname) {
    FILE *f = fopen(catalogname, "r");
    if (!f)
        perror("Unable to open file");
    return f;
}