[英]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));
使用errno
和strerror()
意味着还应该包含标题:
#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.c
和stderr.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 []
。
第二个警告:
当您返回整数0
或1
该函数返回FILE*
类型
您还想要其他东西吗? 喜欢:
FILE* openCatalog(char catalogname[])
{
FILE* file = fopen (catalogname, "r");
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.