Pass stream by reference
我想通过引用传递流,这是一个指针。 所以我将它作为指针传递给指针。 有人可以验证我的代码吗?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
   |     int main (int argc , char** argv )
{
    FILE  *stream ;
    printf("LINES: %d 
",scan (stream ));
}
int scan (FILE  *(*stream ))
{
    stream  = fopen("names.txt","r");
    int ch  = 0, lines =0;
    while (!feof(*stream ))
    {
        ch  = fgetc(*stream );
        if (ch  == ' 
')
        {
            lines ++;
        }
    }
    fclose(*stream );
    return lines ;
}  | 
 
没有收到输出。
		
		
- 
同时,FEOF文件 - 是 - 总是错的
 
- 
有人可以验证我的代码吗? 编译器将验证您的代码。
 
- 
@ user3386109没错。 我有测试,它的工作原理。
 
- 
@MOehm我做了编译,因此我声明没有收到输出。 我在学习。
 
- 
似乎有效,但不是因为你相信的原因。 正确的代码与错误原因的代码之间存在差异。 while ( (ch = fgetc(*stream)) != EOF )是编写while循环的正确方法。
 
- 
@ user3386109正如我提到的我正在学习,我从Dominic Rodger在页面链接上给出的答案中选择了这种格式
 
- 
啊,但注意代码中的所有美元符号。 这不是C代码,它是PHP。 检查问题中的标签。
 
- 
@ user3386109我会尽量小心。 你能帮我解决另一个问题请联系
 
 
	  
您的代码存在设计问题。你到底想要达到什么目的?
如果您只想计算行数,请将FILE *本地化为您的函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
   | 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  == ' 
') lines ++;
    }
    fclose(stream );
    return lines ;
}  | 
 
如果要对已经使用fopen打开的文件执行常规文件操作(读取,写入,搜索,回放等),只需将句柄作为FILE *传递:
1 2 3 4 5 6 7 8 9 10
   | int fget_non_space (FILE  *stream )
{
    int c ;
    do {
        c  = fgetc(stream );
    } while (isspace(c ));
    return c ;
}  | 
 
在这种情况下,在此函数之外调用fopen和fclose。 (您不应该在程序中调用fclose,即使操作系统确保在退出后自动关闭文件,也应如此。)
将指针传递给文件句柄FILE **只有在想要在函数中更改该文件句柄本身时才有意义,例如通过调用fopen:
1 2 3 4 5
   | int fopen_to_read (FILE  **FILE pstream , const char *fn ) 
{
    *pstream  = fopen(fn ,"r");
    return (*pstream  != NULL ) ? 0 : -1;        
}  | 
 
即使这样,最好还是返回文件句柄,如fopen那样。
您的示例代码会在main中保留打开的文件句柄,但您不会对其执行任何操作,甚至不会将其关闭。那是你要的吗?我对此表示怀疑。
		
		
- 
非常感谢您的详细解释。它帮助我理解了整个逻辑/概念。但简单地说,我想通过引用传递'stream'。我忘了关闭文件(道歉),我已经纠正了问题中的原始代码。
 
- 
是的,但是您知道在您的示例中,传递文件指针没有任何意义,因为它永远不会在scan之外使用。这种设计甚至是危险的,因为在调用scan之前,stream是未初始化的,而在callig scan之后,它指的是一个关闭文件。但是,在两种情况下都可以访问stream,它无效。正确的设计是"封装"文件句柄并将其范围限制在其使用范围内。
 
- 
我会努力学习更好。我很难学习C,但我试图理解。你能帮我解决另一个问题链接
 
 
	  
使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
   | 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  == ' 
')
        {
            lines ++;
        }
    }
    fclose(*stream ); // Close the FILE stream after use
    return lines ;
}
int main (void)
{
    FILE  *stream ;
    printf("LINES: %d 
",scan (&stream )); //Pass address of `stream`. The address is of type `FILE**`
}  | 
 
		
		
- 
是的,但如果你不在函数外部使用创建的句柄,那么将指针传递给文件句柄有什么用?你(和OP)也应该'fclose´文件。
 
- 
while ( (ch = fgetc(*stream)) != EOF )
 
- 
@ user3386109,编辑过。谢谢!
 
- 
@MOehm,也许OP有一些要求。谢谢你提醒我fclose。我添加了它。
 
- 
@CoolGuy:是的,当然,可能有一个我们不知道的特殊要求。既然OP已经插入了fclose,很明显只是误解了从外部传递指针的内容是什么。你的答案回答了这个问题,但在我看来,问题首先是一个错误的问题。没关系。
 
 
	  
 
更换
1
   | stream  = fopen("names.txt","r"); | 
 
同
1
   | *stream  = fopen("names.txt","r");  | 
 
也
1 2
   | printf("LINES: %d 
",scan (stream ));  | 
 
同
1 2
   | printf("LINES: %d 
",scan (&stream ));  | 
 
		
		
- 
@ user3386109你想详细说明吗?
 
- 
@Vagish另外,你能解释我怎么能按值传递流?