Are the buffer of input and output different in C? - c

Are the buffer of a C input and output different ? I am trying to implement buffering emulation in assembly and trying to do it as the C one does. I have so far implemented buffering system in my fgets function, however, I am not sure how I should implement it in case of fputs function. If the "buffer" are same, then it does make sense to implement a global variable which will contain the file descriptor last used so that in the case of a "fputs, fgets, fputs" operation, I can use the last file descriptor to flush out the buffer before reading in case of fgets. But this method also seems very costy, as I have to flush out the buffer every time regardless of the fact that I called a fputs function before. Or should I use two buffer for inputting and outputting ?

Or should I use two buffer for inputting and outputting ?
Suggest using one buffer per file handle; that should cover the common use cases — rather than buffering based on i/o direction.

Related

why an input function cannot follow an output function without an intervening call to fflush?

I'm new to C and I was reading a textbook which says that:
Standard I/O streams are full duplex in the sense that programs can perform input and output on the same stream. However, there are poorly documented restrictions on streams
Restriction 1: Input functions following output functions. An input function
cannot follow an output function without an intervening call to fflush, fseek, fsetpos, or rewind
Restriction 2: Output functions following input functions. An output function
cannot follow an input function without an intervening call to fseek,
fsetpos, or rewind, unless the input function encounters an end-of-file.
I'm confused, below is my questions:
Q1-My understanding about the stream buffer is, each stream has two buffers, a read buffer and a write buffer, and is my understanding correct?
Q2-why we have to resposition the current file position or flush the output buffer when input functions following output functions or vice versa?
the stream buffer is, each stream has two buffers, a read buffer and a write buffer, ...
Maybe. 2 or 1 buffers are not required, yet buffering is performance practical.
why we have to....
That is what is needed to meet the specification. Specs were written to provide implementers some latitude - but not too much.
With tight specs, come limited implementation possibilities (no so efficient code).

Is this the proper way to flush the C input stream?

Well I been doing a lot of searching on google and on here about how to flush the input stream properly. All I hear is mixed arguments about how fflush() is undefined for the input stream, and some say just do it that way, and others just say don't do it, I haven't had much luck on finding a clear efficient/proper way of doing so, that the majority of people agree on.. I am quite new at programming so I don't know all the syntax/tricks of the language yet, so my question which way is the most efficient/proper solution to clearing the C input stream??
Use the getchar() twice before I try to receive more input?
Just use the fflush() function on the input? or
This is how I thought I should do it.
void clearInputBuf(void);
void clearInputBuf(void)
{
int garbageCollector;
while ((garbageCollector = getchar()) != '\n' && garbageCollector != EOF)
{}
}
So, whenever I need to read a new scanf(), or use getchar() to pause the program I just call the clearInputBuf.. So what would be the best way out of the three solutions or is there a even better option?
All I hear is mixed arguments about how fflush() is undefined for the input stream
That's correct. Don't use fflush() to flush an input stream.
(A) will work for simple cases where you leave single character in the input stream (such as scanf() leaving a newline).
(B) Don't use. It's defined on some platforms. But don't rely on what standard calls undefined behaviour.
(C) Clearly the best out of the 3 options as it can "flush" any number of characters in the input stream.
But if you read lines (such as using fgets()), you'll probably have much less need to clear input streams.
It depends on what you think of as "flushing an input stream".
For output streams, the flush operation makes sure that all data that were written to the stream but were being kept buffered in memory have been flushed to the underlying filesystem file. That's a very well defined operation.
For input streams, there is no well defined operation of what flushing the stream should do. I would say that it does not make any sense.
Some implementations of the C standard library redefine the meaning of "flush" for input streams to mean "clear the rest of the current line which has not been read yet". But that's entirely arbitrary, and other implementations choose to do nothing instead.
As of C11 this disparity has been corrected, and the standard now explicitly states that the fflush() function does not work with input streams, precisely because it makes no sense, and we do not want each runtime library vendor to go implementing it in whatever way they feel like.
So, please by all means do go ahead and implement your clearInputBuf() function the way you did, but do not think of it as "flushing the input stream". There is no such thing.
It turns out to be platform dependent.
The fflush() cannot have an input stream as a parameter because according to the c standard, IT'S UNDEFINED BEHAVIOR since the behavior is not defined anywhere.
On Windows, there is a defined behavior for fflush() and it does what you need it to do.
On Linux, there is fpurge(3) which does what you want it to do too.
The best way is to simply read all characters in a loop until
A newline character is found.
EOF is returned from getchar().
like your clearInputBuf() function.
Note that flushing an output stream means writing all unwritten data to the stream, the data that is still in a buffer waiting to be flushed. But reading all the unread bytes from a stream, does not have the same meaning.
That's why it doesn't make sense to fflush() an input stream. On the other hand fpurge() is designed specifically for this, and it's name is a better choice because you want to clear the input stream and start fresh. The problem is, it's not a standard function.
Reading fpurge(3) should clarify why fflush(stdin) is undefined behavior, and why an implementation like the one on Windows doesn't make sense because it makes fflush() behave differently with different inputs. That's like making c compliant with PHP.
The problem is more subtile than it looks:
On systems with elaborate terminal devices, such as unix and OS/X, input from the terminal is buffered at 2 separate levels: the system terminal uses a buffer to handle line editing, from just correcting input with backspace to full line editing with cursor and control keys. This is called cooked mode. A full line of input is buffered in the system until the enter key is typed or the end-of-file key combination is entered.
The FILE functions perform their own buffering, which is line buffered by default for streams associated with a terminal. The buffer size in set to BUFSIZ by default and bytes are requested from the system when the buffered contents have been consumed. For most requests, a full line will be read from the system into the stream buffer, but in some cases such as when the buffer is full, only part of the line will have been read from the system when scanf() returns. This is why discarding the contents of the stream buffer might not always suffice.
Flushing the input buffer may mean different things:
discarding extra input, including the newline character, that have been entered by the user in response to input requests such as getchar(), fgets() or scanf(). The need for flushing this input is especially obvious in the case of scanf() because most format lines will not cause the newline to be consumed.
discarding any pending input and waiting for the user to hit a key.
You can implement a fluch function portably for the first case:
int flush_stream(FILE *fp) {
int c;
while ((c = getc(fp)) != EOF && c != '\n')
continue;
return c;
}
And this is exactly what your clearInputBuf() function does for stdin.
For the second case, there is no portable solution, and system specific methods are non trivial.

Reading a file in C with File Descriptor

I want to read from a file by using its file descriptor. I can't use its name because of assignment rules.
I obtain it by calling open and it works fine. At this moment I know that I have to use the read() function in order to read from it. My problem is that read() function requires as an argument the number of bytes to read, and I want to read a whole line from the file each time, so I don't know how many bytes to read.
If i use for example fscanf(), it works fine with a simple string and I take back the whole line as I want. So my question is:
Is there any function like fscanf() which can be called with file descriptor and not with a file pointer?
When you say "have to use read()" I can't tell if that's your understanding of the situation given a file descriptor from open() or a restriction on some kind of assignment.
If you have a file descriptor but you're more comfortable with fscanf() and friends, use fdopen() to get a FILE * from your fd and proceed to use stdio.
Internally it uses functions like read() into a buffer and then processes those buffers as you read them with fscanf() and friends.
What you could do is read one character at a time, until you've read the entire line, and detect a '/n'. As this is homework, I won't write it for you.
A few things to be warned of, however.
You need to check for EOF, otherwise, you might end up in an infinite loop.
You should declare some buffer which you read a character, then copy it into the buffer. Not knowing what your input is, I can't suggest a size, other than to say that for a homework assignment, [256] would probably be sufficient.
You need to make sure you don't overfill your buffer in the even that you do run over it's length.
Keep reading until you find a '/n' character. Then process the line that you have created, and start the next one.

character reading in C

I am struggling to know the difference between these functions. Which one of them can be used if i want to read one character at a time.
fread()
read()
getc()
Depending on how you want to do it you can use any of those functions.
The easier to use would probably be fgetc().
fread() : read a block of data from a stream (documentation)
read() : posix implementation of fread() (documentation)
getc() : get a character from a stream (documentation). Please consider using fgetc() (doc)instead since it's kind of saffer.
fread() is a standard C function for reading blocks of binary data from a file.
read() is a POSIX function for doing the same.
getc() is a standard C function (a macro, actually) for reading a single character from a file - i.e., it's what you are looking for.
In addition to the other answers, also note that read is unbuffered method to read from a file. fread provides an internal buffer and reading is buffered. The buffer size is determined by you. Also each time you call read a system call occurs which reads the amount of bytes you told it to. Where as with fread it will read a chunk in the internal buffer and return you only the bytes you need. For each call on fread it will first check if it can provide you with more data from the buffer, if not it makes a system call (read) and gets a chunk more data and returns you only the portion you wanted.
Also read directly handles the file descriptor number, where fread needs the file to be opened as a FILE pointer.
The answer depends on what you mean by "one character at a time".
If you want to ensure that only one character is consumed from the underlying file descriptor (which may refer to a non-seekable object like a pipe, socket, or terminal device) then the only solution is to use read with a length of 1. If you use strace (or similar) to monitor a shell script using the shell command read, you'll see that it repeatedly calls read with a length of 1. Otherwise it would risk reading too many bytes (past the newline it's looking for) and having subsequent processes fail to see the data on the "next line".
On the other hand, if the only program that should be performing further reads is your program itself, fread or getc will work just fine. Note that getc should be a lot faster than fread if you're just reading a single byte.

unistd.h read() function: How to read a file line by line?

What I need to do is use the read function from unistd.h to read a file
line by line. I have this at the moment:
n = read(fd, str, size);
However, this reads to the end of the file, or up to size number of bytes.
Is there a way that I can make it read one line at a time, stopping at a newline?
The lines are all of variable length.
I am allowed only these two header files:
#include <unistd.h>
#include <fcntl.h>
The point of the exercise is to read in a file line by line, and
output each line as it's read in. Basically, to mimic the fgets()
and fputs() functions.
You can read character by character into a buffer and check for the linebreak symbols (\r\n for Windows and \n for Unix systems).
You'll want to create a buffer twice the length of your longest line you'll support, and you'll need to keep track of your buffer state.
Basically, each time you're called for a new line you'll scan from your current buffer position looking for an end-of-line marker. If you find one, good, that's your line. Update your buffer pointers and return.
If you hit your maxlength then you return a truncated line and change your state to discard. Next time you're called you need to discard up to the next end of line, and then enter your normal read state.
If you hit the end of what you've read in, then you need to read in another maxline chars, wrapping to the start of the buffer if you hit the bottom (ie, you may need to make two read calls) and then continue scanning.
All of the above assumes you can set a max line length. If you can't then you have to work with dynamic memory and worry about what happens if a buffer malloc fails. Also, you'll need to always check the results of the read in case you've hit the end of the file while reading into your buffer.
Unfortunately the read function isn't really suitable for this sort of input. Assuming this is some sort of artificial requirement from interview/homework/exercise, you can attempt to simulate line-based input by reading the file in chunks and splitting it on the newline character yourself, maintaining state in some way between calls. You can get away with a static position indicator if you carefully document the function's use.
This is a good question, but allowing only the read function doesn't help! :P
Loop read calls to get a fixed number of bytes, and search the '\n' character, then return a part of the string (untill '\n'), and stores the rest (except '\n') to prepend to the next character file chunk.
Use dynamic memory.
Greater the size of the buffer, less read calls used (which is a system call, so no cheap but nowadays there are preemptive kernels).
...
Or simply fix a maximum line length, and use fgets, if you need to be quick...
If you need to read exactly 1 line (and not overstep) using read(), the only generally-applicable way to do that is by reading 1 byte at a time and looping until you get a newline byte. However, if your file descriptor refers to a terminal and it's in the default (canonical) mode, read will wait for a newline and return less than the requested size as soon as a line is available. It may however return more than one line, if data arrives very quickly, or less than 1 line if your program's buffer or the internal terminal buffer is shorter than the line length.
Unless you really need to avoid overstep (which is sometimes important, if you want another process/program to inherit the file descriptor and be able to pick up reading where you left off), I would suggest using stdio functions or your own buffering system. Using read for line-based or byte-by-byte IO is very painful and hard to get right.
Well, it will read line-by-line from a terminal.
Some choices you have are:
Write a function that uses read when it runs out of data but only returns one line at a time to the caller
Use the function in the library that does exactly that: fgets().
Read only one byte at a time, so you don't go too far.
If you open the file in text mode then Windows "\r\n" will be silently translated to "\n" as the file is read.
If you are on Unix you can use the non-standard1 gcc 'getline()' function.
1 The getline() function is standard in POSIX 2008.
Convert file descriptor to FILE pointer.
FILE* fp = fdopen(fd, "r");
Then you can use getline().

Resources