2015-03-02 145 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