2015-03-02 182 views
0

我想通過引用傳遞流,這是一個指針。所以我將它作爲指針傳遞給指針。有人可以驗證我的代碼嗎?通過引用傳遞流

int main(int argc, char** argv) 
{ 
    FILE *stream; 

    printf("LINES: %d\n",scan(stream)); 
} 

int scan(FILE *(*stream)) 
{ 
    stream = fopen("names.txt", "r"); 

    int ch = 0, lines=0; 

    while (!feof(*stream)) 
    { 
     ch = fgetc(*stream); 
     if (ch == '\n') 
     { 
      lines++; 
     } 
    } 
    fclose(*stream); 
    return lines; 
} 

未收到輸出。

+1

[while-feof-file-is-always-wrong](http://stackoverflow.com/a/5432517/3386109) – user3386109 2015-03-02 07:10:32

+1

_可以讓別人驗證我的代碼嗎?_編譯器會驗證你的代碼。 – 2015-03-02 07:13:05

+0

@ user3386109這沒有錯。我有測試,它的工作原理。 – user3337714 2015-03-03 02:39:43

回答

1

更換

stream = fopen("names.txt", "r"); 

*stream = fopen("names.txt", "r"); 

而且

printf("LINES: %d\n",scan(stream)); 

printf("LINES: %d\n",scan(&stream)); 
+0

@ user3386109你想說明一下嗎? – user3337714 2015-03-02 07:18:52

+0

@Vagish另外,你能解釋我怎樣才能通過價值傳遞流? – user3337714 2015-03-02 07:22:19

2

使用

int scan(FILE **stream) //no need for brackets 
{ 
    *stream = fopen("names.txt", "r"); //* is for dereferencing 

    if(*stream==NULL) // Checking the return value of fopen 
    { 
     printf("An error occured when opening 'names.txt'"); 
     return -1; 
    } 

    int ch = 0, lines=0; 

    while ((ch = fgetc(*stream))!=EOF) //while(!feof) is wrong 
    { 

     if (ch == '\n') 
     { 
      lines++; 
     } 
    } 
    fclose(*stream); // Close the FILE stream after use 
    return lines; 
} 

int main(void) 
{ 
    FILE *stream; 

    printf("LINES: %d\n",scan(&stream)); //Pass address of `stream`. The address is of type `FILE**` 
} 
+0

是的,但是如果不在函數外部使用創建的句柄,將指針傳遞給文件句柄有什麼好處?你(和OP)也應該'fclose'這個文件。 – 2015-03-02 07:20:55

+1

'while((ch = fgetc(* stream))!= EOF)' – user3386109 2015-03-02 07:22:04

+0

@ user3386109,編輯它。謝謝! – 2015-03-02 07:49:05

2

您的代碼有設計問題。你想要達到什麼目的?

如果你只是想算的線條,使FILE *您的本地功能:

int count_lines(const char *filename) 
{ 
    FILE *stream = fopen(filename, "r"); 

    int lines = 0; 

    while (1) { 
     int c = fgetc(stream); 

     if (c == EOF) break; 
     if (c == '\n') lines++; 
    } 
    fclose(stream); 

    return lines; 
} 

如果你想要做一個普通的文件操作(讀,寫,查找,快退等)到已經被打開了fopen文件,只需通過手柄爲FILE *

int fget_non_space(FILE *stream) 
{ 
    int c; 

    do { 
     c = fgetc(stream); 
    } while (isspace(c)); 

    return c; 
} 

在這種情況下,無論是fopenfclose正在調用該函數之外。 (您不要在程序中調用fclose,即使操作系統確保在退出後自動關閉文件,也應該這樣做)。

將指針傳遞給文件句柄FILE **只有在您要通過調用fopen更改文件句柄本身的功能,例如:

int fopen_to_read(FILE **FILE pstream, const char *fn) 
{ 
    *pstream = fopen(fn, "r"); 
    return (*pstream != NULL) ? 0 : -1;   
} 

即使這樣,倒不如返回文件句柄,如fopen一樣。

您的示例代碼在main中保留了可打開的文件句柄,但您對此無能爲力,甚至沒有關閉它。那是你要的嗎?我對此表示懷疑。

+0

非常感謝您的詳細解釋。它幫助我理解整個邏輯/概念。但簡單地說,我想通過引用傳遞'流'。我沒有忘記關閉文件(道歉),我已經糾正了問題中的原始代碼。 – user3337714 2015-03-02 07:46:08

+0

是的,但您知道在您的示例中,傳遞文件指針沒有任何意義,因爲它永遠不會在'scan'之外使用。這種設計甚至是危險的,因爲在調用'scan'之前,'stream'是未初始化的,在callig' scan'之後,它指向一個關閉文件。儘管如此,你還是可以在兩種情況下訪問'stream',它們是無效的。正確的設計將是「封裝」文件句柄並將其範圍限制在其使用範圍內。 – 2015-03-02 07:56:29

+0

我會盡力學習更好。我很難學習C,但我正在努力去理解。你能幫助我的另一個問題[鏈接](http://stackoverflow.com/questions/28823218/load-text-file-in-struct) – user3337714 2015-03-03 04:01:35