Changing the file position indicator of stdout - c

I am trying to mess with the file position indicator and write over stuff that is already on screen.
#include <stdio.h>
int main ()
{
fpos_t position;
fgetpos (stdout, &position);
fputs ("That is a sample",stdout);
fsetpos (stdout, &position);
fputs ("This",stdout);
return 0;
}
I want this "This is a sample". I got similar code right off of cplusplus.com the only difference is that they use an actual file and not stdout. Is there some special exception for stdout of which I am unaware.
I thought I could treat stdout like a file. For some reason I am getting this as output: That is a sampleThisPress any key to continue . . . I would really like to know why. This guy even asked the same question on with no response on cplusplus.com
I know about fseek and lseek and I might use those instead if they work but regardless I want to know why the above does not work. If you have a better way of doing this I am open to suggestions but I still want to know what I am doing wrong here. Thank you in advance.

If what you are trying to achieve is to modify the output to a screen, you may want to look at ncurses (or something similar).
Or perhaps, if you just want something like this (a progress bar that shows how much "part2 is of the "total" work that is done so far):
....
cout << part * 100 / total << "% done\r"; cout.flush();
....
The \r is "carriage return", and will move the cursor back to the start of the line, without moving down.

Stdout doesn't have a concept of file positions when pointing at tty style devices, think of the old days of tty modems etc and once a character is sent it's sent. You may be able to send a sequence of characters to reposition the cursor after the event and overwrite text on the screen, but how you do that is dependent on the output device.

Your program will work if stdout is redirected to a file. Terminals are not seekable, but disk files, and some other types of streams, are seekable.
There is a system call library call, isatty(1), which is widely supported. If it returns true, stdout is connected to a terminal-like device, and is not seekable. If false, you can usually depend on it working. I thought there was a isapipe() call, but I have never used it (only thought I remembered seeing it in the man pages), but I don't find it anywhere now. Pipes tend not to be seekable as well (in most cases).

Related

Is it possible to implement printf() in a non blocking manner in linux terminal

I have a printf statement after sleep for 1 second. Since the printf statement takes longer than 1 second , the refresh rate is more than 2 seconds. Here is an example i am talking about :
while(1){
printf("%s",buf);//Takes more than one second to print a table. Only few
//values are updated
sleep(1);
}
How can i have a printf to be non blocking. Is there a way in a standard linux machine ?
-Sanatan
If you only care about what shows on the screen, that is one of the problems that curses addresses. Using curses, you could update the display using reasonably optimal output (only the changed areas would be updated rather than printing the whole table each time), and with the typeahead feature, you can alleviate the problem of falling behind if the updates are too rapid.
It's more complicated than just printf. But with printf, the buffer will get full, and there is nowhere to put it except to the standard output. In some implementations, you could use setvbuf to assign a new output buffer, but POSIX frowns on that after output has started, saying:
The setvbuf() function may be used after the stream pointed to by stream is associated with an open file but before any other operation (other than an unsuccessful call to setvbuf()) is performed on the stream.
Because of this, ncurses has treated setvbuf (and similar functions such as setbuf) with caution. In the current release, to solve other problems, ncurses no longer uses this function. But it is still documented:
ncurses enabled buffered output during terminal initialization. This was done (as in SVr4 curses) for performance reasons. For testing purposes, both of ncurses and
certain applications, this feature was made optional.
Setting the NCURSES_NO_SETBUF variable disabled output
buffering, leaving the output in the original (usually
line buffered) mode.
The function printf is a buffered function. It only flush to stdout when the buffer is full or when you force it. If you print a \n this will full the buffer. What you can do is to use the fflush function on stdout to force it.

How are files written? Why do I not see my data written immediately?

I understand the general process of writing and reading from a file, but I was curious as to what is happening under the hood during file writing. For instance, I have written a program that writes a series of numbers, line by line, to a .txt file. One thing that bothers me however is that I don't see the information written until after my c program is finished running. Is there a way to see the information written while the program is running rather than after? Is this even possible to do? This is a hard question to phrase in one line, so please forgive me if it's already been answered elsewhere.
The reason I ask this is because I'm writing to a file and was hoping that I could scan the file for the highest and lowest values (the program would optimally be able to run for hours).
Research buffering and caching.
There are a number of layers of optimisation performed by:
your application,
your OS, and
your disk driver,
in order to extend the life of your disk and increase performance.
With the careful use of flushing commands, you can generally make things happen "quite quickly" when you really need them to, though you should generally do so sparingly.
Flushing can be particularly useful when debugging.
The GNU C Library documentation has a good page on the subject of file flushing, listing functions such as fflush which may do what you want.
You observe an effect solely caused by the C standard I/O (stdio) buffers. I claim that any OS or disk driver buffering has nothing to do with it.
In stdio, I/O happens in one of three modes:
Fully buffered, data is written once BUFSIZ (from <stdio.h>) characters were accumulated. This is the default when I/0 is redirected to a file or pipe. This is what you observe. Typically BUFSIZ is anywhere from 1k to several kBytes.
Line buffered, data is written once a newline is seen (or BUFSIZ is reached). This is the default when i/o is to a terminal.
Unbuffered, data is written immediately.
You can use the setvbuf() (<stdio.h>) function to change the default, using the _IOFBF, _IOLBF or _IONBF macros, respectively. See your friendly setvbuf man page.
In your case, you can set your output stream (stdout or the FILE * returned by fopen) to line buffered.
Alternatively, you can call fflush() on the output stream whenever you want I/O to happen, regardless of buffering.
Indeed, there are several layers between the writing commands resp. functions and the actual file.
First, you open the file for writing. This causes the file to be either created or emptied. If you write then, the write doesn't actually occur immediately, but the data are cached until the buffer is full or the file is flushed or closed.
You can call fflush() for writing each portion of data, or you can actually wait until the file is closed.
Yes, it is possible to see whats written in the file(s). If you programm under Linux you can open a new Terminal and watch the progress with for example "less Filename".

Can a program output be redirected to a pipe through program itself?

Well this is regarding a program for a competition.
I was submitting a program & finding my metrics to be relatively way slower than the top scorers in terms of total execution speed. All others (page faults, memory...) were similar. I found that when I ran through my program without the printf (or write) my total execution speed (as measured in my own pc) seemed to be similar.
The competition evaluates the output by redirecting the output (with a pipe, i suppose) into a file & matching its MD5 with theirs....
My question is, Is there by any means something in C, that doesn't write to the output stream but still the pipe gets its input. Or perhaps I am even framing the question wrong. But either way, I am in a fix.
I have been beating my head off with optimizing the algorithm. BTW they accept makefile where many have tried to optimize. For me neither of the optimization flags have worked. I don't know what else can be done about that too...
If you need to make a program that writes its output to a file, you just need to:
open the file with int fd = fopen("/file/path", O_WRONLY); (you may need to check the parameters, it's been a long time since I've done C programming) and then write(fd, ...); or fprintf(fd, ...);
open the file with fopen, close the standard output and use dup2() to duplicate the file descriptor to the file descriptor number 1 (i.e. standard output).
You may try fprintf on the pipe fd.

Retrieving stdin after using the redirection operator <

For a programming assignment, we have the following requirements:
It needs to be a command-line program written in C.
It needs to read text from a text document. However, we are to do this by using the Unix redirection operator < when running the program rather than having the program load the file itself. (So the program reads the text by pretending it's reading from stdin.)
After reading the data from the file, the program is to poll the user for some extra information before doing its job.
After much research, I can't find a way to retrieve the "old" stdin in order to accomplish part (3). Does anybody know how or if this is even possible?
Technically part (3) is part of a bonus section, which the instructor probably didn't implement himself (it's very lengthy), so it's possible that this is not possible and it's an oversight on his part. However, I certainly don't want to jump to this conclusion.
On linux, i would open the controlling terminal /dev/tty.
Which OS? On Linux the usual trick to accomplish this is to check if stderr is still connected to a tty:
if (isatty(2))
and if so, open a new reading file descriptor to that terminal:
new_stdin = open("/proc/self/fd/2", O_RDONLY);
then duplicate the new file descriptor to stdin (which closes the old stdin):
dup2(new_stdin, 0);
(If stderr has also been redirected, then isatty(2) will return false and you'll have to give up.)
If you run the program like this:
myprog 3<&0 < filename
then you get file descriptor 3 set up for you as a duplicate of stdin. I don't know if this meets the requirements of your assignment, but it might be worth an experiment.

how to write into a text file by C program

my problem is fprintf is only printing part of the expected output into the file.When i use printf the output is correctly printed on the output window, showing that the loop is correct but when i use it with fprintf the complete output is not printed.Only the initial part is printed.
PLease advise as to what might possibly be the problem???
thanks in advance...
I bet that you've not flushed/closed your file.
The problem is likely that you are not telling C to actually write the data to disk. This usually happens automatically when you close a file, and may happen automatically at other times (such as when internal buffers fill up).
It sounds like you are writing just a few bytes and then checking the file to see what happened. If so, your program may be holding those bytes in an internal buffer before actually writing to disk. It does this to improve performance in the general case -- you don't normally want a disk access for each and every single print statement.
One solution, as other answers suggest, is to call fflush. This will "flush" all of the buffered data to disk. There are other solutions such as to turn off buffering, but calling fflush is the best first step since you are new to programming.
For more information, here's a link to a wiki book about file I/O with C. You can jump straight to the section on fflush, though you might want to read the introductory paragraphs to gain a little more insight.
Sound like you forgot to do fflush or fclose
you try to use fflush()

Resources