Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use of fseek with stdout

Tags:

c

Is it possible to use fseek when the file pointer arg is stdout?

I have tried it in a scenario when I was attempting to overwrite the last "," in a comma separated list with a ")"

e.g.

fprintf(stdout, "1,2,3,4,");

fseek(stdout, -1, SEEK_CUR);

fprintf(stdout, ")");

to achieve:

1,2,3,4)

as opposed to

1,2,3,4,)

unfortunately I output the latter

like image 232
bph Avatar asked Aug 15 '14 15:08

bph


2 Answers

You can successfully use fseek on stdout if and only if stdout refers to a seekable stream.

If your program's standard output is going to a terminal or something similar (which is typically the default) or to a pipe, then fseek will fail. If it's going to a file because you executed the program with its output redirected, then fseek can work as it would for any other file.

Any time you call fseek, you should check its return value to see whether it succeeded or failed.

Assuming that stdout is seekable is probably bad practice, because it's very commonly a bad assumption.

Your goal is to print a sequence of items with ", " between items, but not before the first or after the last. Neither fseek nor printing a '\b'is a a good approach for what you're trying to do. Rather than printing the final comma and then trying to erase it, you should print the comma only if you haven't just printed the last item in the list. Detecting this can be non-trivial.

But an easier approach is to precede each item with a comma unless it's the first one. You can't always tell whether you're printing the last value of a sequence. You can always tell whether you're printing the first.

Pseudo-code:

bool is_first_item = true
for each item
    if is_first_item
        is_first_item = false
    else
        print ", "
    end if
    print item
end for 
like image 162
Keith Thompson Avatar answered Nov 15 '22 08:11

Keith Thompson


Using fseek on stdout is not possible. Instead, you can use the backspace character, '\b', to move the cursor back one space:

fprintf(stdout, "1,2,3,4,");

fprintf(stdout, "\b)");

Note: this will only work if stdout points to a terminal, and has not been redirected to a file or pipe. Also, if the cursor is currently at the beginning of a line, then this isn't guaranteed to work. In general, there are only a few cases where this will work.

like image 20
Drew McGowen Avatar answered Nov 15 '22 08:11

Drew McGowen