簡體   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