C 通过引用传递流

C 通过引用传递流,c,pointers,stream,pass-by-reference,pointer-to-pointer,C,Pointers,Stream,Pass By Reference,Pointer To Pointer,我假设通过引用传递流,它是一个指针。所以我把它作为一个指针传递给一个指针。有人能验证我的代码吗 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

我假设通过引用传递流,它是一个指针。所以我把它作为一个指针传递给一个指针。有人能验证我的代码吗

    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;
}
未收到输出。

更换

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

替换

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

使用

使用


您的代码存在设计问题。你到底想要实现什么

如果只想计算行数,请将
文件*
设置为函数的本地:

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;
}
在这种情况下,在该函数之外调用
fopen
fclose
。(您不能在程序中调用
fclose
,即使操作系统确保退出后自动关闭文件,您也应该这样做。)

仅当您希望在函数中更改文件句柄本身时(例如,通过调用
fopen
),传递指向文件句柄
file**
的指针才有意义:

int fopen_to_read(FILE **FILE pstream, const char *fn) 
{
    *pstream = fopen(fn, "r");
    return (*pstream != NULL) ? 0 : -1;        
}
即使如此,最好还是像
fopen
那样返回文件句柄


您的示例代码使打开的文件句柄可以在
main
中访问,但您不使用它,甚至不关闭它。这就是你想要的吗?我对此表示怀疑。

您的代码存在设计问题。你到底想要实现什么

如果只想计算行数,请将
文件*
设置为函数的本地:

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;
}
在这种情况下,在该函数之外调用
fopen
fclose
。(您不能在程序中调用
fclose
,即使操作系统确保退出后自动关闭文件,您也应该这样做。)

仅当您希望在函数中更改文件句柄本身时(例如,通过调用
fopen
),传递指向文件句柄
file**
的指针才有意义:

int fopen_to_read(FILE **FILE pstream, const char *fn) 
{
    *pstream = fopen(fn, "r");
    return (*pstream != NULL) ? 0 : -1;        
}
即使如此,最好还是像
fopen
那样返回文件句柄



您的示例代码使打开的文件句柄可以在
main
中访问,但您不使用它,甚至不关闭它。这就是你想要的吗?我怀疑。

有人能验证我的代码吗?编译器将验证您的代码。@user3386109它没有错。我进行了测试,它可以工作。@MOehm我确实编译了,因此我声明没有收到任何输出。我正在学习。它似乎起作用,但不是因为你相信的原因。正确的代码和出于错误原因工作的代码之间存在差异<代码>while((ch=fgetc(*stream))!=EOF)是编写while循环的正确方法。有人能验证我的代码吗?编译器将验证您的代码。@user3386109它没有错。我进行了测试,它可以工作。@MOehm我确实编译了,因此我声明没有收到任何输出。我正在学习。它似乎起作用,但不是因为你相信的原因。正确的代码和出于错误原因工作的代码之间存在差异
while((ch=fgetc(*stream))!=EOF)
是编写while
while
循环的正确方法。@user3386109您想详细说明吗?@Vagish还有,您能解释我如何按值传递流吗?@user3386109您想详细说明吗?@Vagish还有,您能解释我如何按值传递流吗?是的,但是,如果不在函数外部使用创建的句柄,那么将指针传递给文件句柄又有什么好处呢?您(和OP)也应该“fclose”该文件。
while((ch=fgetc(*stream))!=EOF)
@user3386109,编辑该文件。谢谢@莫姆,也许OP有一些要求。感谢您提醒我有关
fclose
。“是的,当然,可能有一个我们不知道的特殊要求。”。现在OP已经插入了
fclose
,很明显,对于从外部传递指向内容的指针的目的,存在着一个简单的误解。你的回答回答了这个问题,但在我看来,这个问题一开始就有点错误。没关系。是的,但是如果不在函数外部使用创建的句柄,那么传递指向文件句柄的指针有什么好处呢?您(和OP)也应该“fclose”该文件。
while((ch=fgetc(*stream))!=EOF)
@user3386109,编辑该文件。谢谢@莫姆,也许OP有一些要求。感谢您提醒我有关
fclose
。“是的,当然,可能有一个我们不知道的特殊要求。”。现在OP已经插入了
fclose
,很明显,对于从外部传递指向内容的指针的目的,存在着一个简单的误解。你的回答回答了这个问题,但在我看来,这个问题一开始就有点错误。没关系。非常感谢你的详细解释。它帮助我理解了整个逻辑/概念。但很简单,我想通过引用传递“stream”。我确实忘记关闭文件(抱歉),我已更正了问题中的原始代码。是的,但您知道,在您的示例中,传递文件指针没有任何意义,因为它从未在
扫描
之外使用。这种设计甚至是危险的,因为在调用
scan
之前,
stream
是未初始化的,而在调用
scan
之后,它引用了一个关闭的文件。不过,在这两种情况下,您都可以访问
,因为它是无效的。正确的设计应该是“封装”文件句柄,并将其范围限制在其使用范围内。我将尝试更好地学习。学习C语言对我来说很难,但我正在努力理解。你能帮我解决另一个问题吗?非常感谢你的详细解释