[英]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.