I'm a C beginner, I want to call ungetc() twice in a row although I know in regular C it is not permitted. Someone told me I can modify Fflush() to do this job, however I don't know how to do it.
Here is my code, my Fflush only allow one ungetc(), I want it to allow twice.
#define altUngetc(c, fp) ((fp)->next > (fp)->buffer && (c) != EOF ? \
*--(fp)->next = (c) : EOF)
int altGetc(ALT_FILE *fp) {
if (fp->next == fp->buffer + fp->bufSize)
altFflush(fp);
return fp->flags & FILE_ATEOF ? EOF : *fp->next++;
}
int altFflush(ALT_FILE *fp) {
int res;
if (fp->fd < 0 || fp->flags & FILE_ATEOF)
return EOF;
if (fp->flags & FILE_READ) {
res = read(fp->fd, fp->buffer, BUF_SIZE);
if (res == 0)
fp->flags |= FILE_ATEOF;
fp->bufSize = res;
fp->next = fp->buffer;
}
else {
res = write(fp->fd, fp->buffer, fp->next - fp->buffer);
fp->next = fp->buffer;
}
return res < 0 ? EOF : 0;
}
As wisely mentioned in the comments,
you should probably first learn to work with the rules instead of trying to break them. However, we're here to answer the question, and that means to break the rules! Take into account that neitherfflush(),setbuf(), orsetvbuf()would work here for different reasons.First of all, at least four custom functions are required. One to create a "proxy buffer" relating to a file (called just after
fopen()), one to destroy it (called just beforefclose(), one to do the actual ungetting (replacement forungetc(), and one to to retrieve acharfrom the file (replacement forfgetc(). Unfortunately, this means that performingfscanf(),fflush(), etc... on the stream will yield you bad and ugly results. You would have to rewrite all ofstdio!First of all, let's call all of our new stuff
xtdio("extendedstdio"), so, first of all comesxtdio.h...Then, in the interesting side of the fence, comes
xtdio.c...The smallish
xtdiolibrary will allow you to perform as many ungets as you pass toxwrap()'s parameter. EachXFILEhas a buffer with the ungotten characters. When youxgetc(), it first checks if there's something on the buffer and retrieves it. Otherwise, it fallbacks tofgetc(). Example usage case...xtdiocan be further improved, by adding things such asxrewrap()to extend/shrink the buffer's size.There's an even better solution, and it is to refactor your code, and follow the conventions, so that you don't have to
ungetc()twice.xtdiois just a proof of concept, but is not good code, and shall never be used in practice. This way, you won't have to deal with rewritingstdio.