Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does ungetc have a parameter to specify which character to push back?

In my current understanding, you're supposed to call ungetc when you want to "un-get" the most recent character that you got from the stream, sort of like reversing the effect of an equivalent call to fgetc. If that's the case, then what's the point of having a parameter to specify which character to put back? Shouldn't the stream remember at least what its most recently obtained character was?

I was thinking that it could be just ungetc(stream), which probably makes more sense. I've seen a lot of implementations that involve the use of ungetc, and so far, none of them have really shown that the function is capable of pushing back a different character and explain how this behavior can be useful.

like image 850
AJ Tan Avatar asked Nov 29 '25 17:11

AJ Tan


2 Answers

In my current understanding, you're supposed to call ungetc when you want to "un-get" the most recent character that you got from the stream,

That is the use implied by the function's name, yes. And in my personal experience, it is the most common use, though this is a rarely-used function overall.

Shouldn't the stream remember at least what its most recently obtained character was?

It could, but I don't see how you get from there to should. The possibility of an alternative design for rarely-used ungetc() is pretty much the only reason for considering that.

I was thinking that it could be just ungetc(stream), which probably makes more sense.

It would make more sense if the function were limited to pushing back only the character most recently read from the specified stream. But in fact, there is no such limitation.

I've seen a lot of implementations that involve the use of ungetc, and so far, none of them have really shown that the function is capable of pushing back a different character

I don't find it surprising that the ungetc() uses you have seen all push back the character that was just read. That is certainly the primary intended use case, as reflected in the function's name. But that you haven't seen examples of other uses and can't think of any is irrelevant. The function's documentation specifies that it is the character passed as an argument that is pushed back, regardless of what the most recently read character was, or if there even was one.

Possibly this design reflects a convergence of multiple goals of C's designers:

  • memory conservation - why make every FILE in the system take an additional byte of RAM, of which there may be only a few thousand overall,* just to support a rarely-used function?

  • flexible interface - why create a system interface that can do only one specific thing when it could instead do a more general thing for little or no additional cost?


*Early C development was largely done on the PDP-11, whose minimal configuration featured a whopping 4 KB of RAM. Though I think Bell Labs' was somewhat more generously configured.

like image 103
John Bollinger Avatar answered Dec 02 '25 05:12

John Bollinger


You may use any character in the call of ungetc. It is not necessary that it must be the same as the last read character.

That is the function has a more general behavior.

More general functions have more applications.

For example if the last read character is tab character '\t' you can substitute it for space character ' ' in the input stream.

like image 42
Vlad from Moscow Avatar answered Dec 02 '25 07:12

Vlad from Moscow