I have seen this piece of code several times but am unable to understand what it does
inline char nc()
{
static char buf[100000], *L = buf, *R = buf;
return L == R && (R = (L = buf) + fread(buf, 1, 100000, stdin), L == R) ? EOF : *L++;
}
The condition L==R
should always be true , right? since both the pointers point to the same variable. I cant understand what the second part of the condition checks. Could someone please help me out?
All the variables are declared as static
which means that they keep their value from the previous function call. The initializations =buf
are only run the first time the function is called. It's basically the same thing as if you declared those variables as globals and initialized them before the first function call. Of course with the difference that globals can be accessed from anywhere in the code.
Let's disassemble the second line a bit. It can be rewritten like this:
char ret;
if(L == R &&
R = (L = buf) + fread(buf, 1, 100000, stdin), L == R) {
ret = EOF;
} else {
ret=*L; // Return the character read
L++; // Advance to next character in the buffer
}
return ret;
A bit clearer, but still a bit clunky. The second condition R = (L = buf) + fread(buf, 1, 100000, stdin), L == R)
is not very clear. It can be rewritten like this:
L = buf;
int noCharactersRead = fread(buf, 1, 100000, stdin);
R = L + noCharactersRead;
if(L == R) // If no characters have been read
ret = EOF;
So the complete refactored code (with some extra refactoring) will be
char nc()
{
#define BUFSIZE 100000
static char buf[BUFSIZE], *L = buf, *R = buf;
if(L == R) { // If buffer is empty
L = buf; // Reset L to beginning of buffer
// Read next character from stdin, put it in the buffer
// and check if read was successful
int noCharactersRead = fread(buf, 1, BUFSIZE, stdin);
// Return EOF on read failure
if(noCharactersRead == 0)
return EOF;
// Advance R one step if a character was read
R = L + noCharactersRead;
}
// If the buffer was not empty, or if the buffer was empty and we
// successfully read a new character into the buffer, return the next
// character in the buffer and advance L
return *L++;
}
I removed the inline
because the function contains static variables. An alternative would be to declare the function as static inline
.
It is essentially a buffered version of getchar()
function, but written in a very unreadable way. Do also note that it has very little protection for buffer overflow. It basically relies on the buffer being big enough to not cause any issues. A way to solve this would be changing the call to fread
to fread(buf, 1, BUFSIZE - (R-L), stdin)
This is basically equivalent of:
char buf[100000];
char* L = buf;
char* R = buf;
char non_fancy_getchar()
{
if (L == R) {
/* reset pointers and try to read stdin again */
L = buf;
R = L + fread(buf, 1, sizeof(buf), stdin);
}
/* return next char or EOF */
return (L == R) ? EOF : *L++;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With