user3337714
user3337714

Reputation: 673

Pass stream by reference

I am suppose to pass stream, which is a pointer, by reference. So I am passing this as a pointer to a pointer. Can someone please verify my code?

    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;
}

No output received.

Upvotes: 1

Views: 1427

Answers (3)

Spikatrix
Spikatrix

Reputation: 20244

Use

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**`
}

Upvotes: 2

M Oehm
M Oehm

Reputation: 29126

Your code has design issues. What exactly do you want to achieve?

If you just want to count the lines, make the FILE * local to your function:

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;
}

If you want to do a regular file operation (read, write, seek, rewind etc.) to a file that has already been opened with fopen, just pass the handle as FILE *:

int fget_non_space(FILE *stream)
{
    int c;

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

    return c;
}

In that case, both fopen and fclose are called outside this function. (You don't call fclose in your program, which you should, even if the operating system makes sure to close the file automatically after exiting.)

Passing a pointer to the file handle, FILE **, makes sense only if you want to change that file handle itself in the function, for example by calling fopen:

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

Even then, it would be better to return the file handle, as fopen does.

Your example code leaves the open filehandle accessible in main, but you don't do anything with it, you don't even close it. Is that what you want? I doubt it.

Upvotes: 2

Vagish
Vagish

Reputation: 2547

Replace

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

with

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

Also

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

with

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

Upvotes: 1

Related Questions