Newlines and the input buffer #CProgramming

in #programming6 years ago

If you have done C programming before, then this should not be something too unfamiliar to you...


image.png
Source

For programming newbies, one of the most annoying things will be "correctly written down all the printfs and scanfs but get some strange hilarious output". That don't normally happen if they are learning Python or JavaScript, but here in my school we learn C language before anything else. Wow.

C is a pretty good language, don't get me wrong. It is readable enough to explicitly tell what it is doing most of the times, and is low level enough to do deep performance optimizing and stuff like that. But the low level part is the part that hurts. It's like a 4-bladed Jedi sword, you can stab yourself when using it. Probably accidentally. And sure, it kills brain cells in the process, so it is as deadly as a Jedi sword.

New coders frequently hit that same issue again and again - ask the program to receive two or more values. Works for the first input, probably for the second input, but when the inputs get more and more the program will start to behave strangely, like...looping itself over and over again. Until now I still don't catch how it happens, but it does.

Put that infinite loop aside, that's somehow related but it's not today's topic. Why? Because apparently I don't have a clue about it...yet. Let's look at something else.


I told you to let me input twice?

Let's look at this sample code.

#include <stdio.h>

int main() {
  int a = getchar();
  int b = getchar();
  printf("First character is %c, second is %c\n", a, b);
  return 0;
}

What does it do? Simple, you run it, type two characters each followed by an Enter, then it will show them out on your terminal. Run it here..

That's what newbies would expect it to do, but if you try it out you will realize that you only get the chance of input one character and the impatient program will just print out something you don't want to see before quitting like nothing happened.

In most books I have read and most solutions I have read on the net, they mentioned about the input buffer and stuff like that, mentioning a newline character which is left in it, bla bla bla, that's why it skips asking for the second input and that's why. The solution they give is actually pretty simple, just add another getchar() after the first one, and it will work.

#include <stdio.h>

int main() {
  int a = getchar();
  getchar();
  int b = getchar();
  getchar();
  printf("First character is %c, second is %c\n", a, b);
  return 0;
}

Run it here

I know, it does not really make sense to most newbie C programmers, but it works. I was one of the peeps that just copied solutions and fixed this bug in all of my assignment programs by randomly slapping getchar()s in anywhere it happens...but now probably I should dig a little deeper into this and explain why it happens. After all, it's been more than 1 year since I really got into C programming.

Don't look at me like that, my skills are still pretty potato

So, when your program runs, the computer will give it three streams - just think of three pipes connected to your program. One is for input, one is for output, and one is for error outputs. Most things that require user input in newbie programs involve reading from the input stream using functions like scanf() and getchar() and the likes. Sounds pretty straightforward, right?

But, most of the times we learn about these functions without realizing how they work. Let's say for the most common scanf(), it does its job by reading the input buffer. If it can find what you want it to find (say, a %c for a character), it copies it and puts it into the destination you told it. If it cannot find it, then it waits for you to input it. It will only read until a space, a tab, or an enter, or a end-of-file. And...probably a lot more characteristics that I forgot. In short, they contain a lot more black magic than you expect. Especially scanf(), this thing is basically one big grimoire and can perform a lot of evil stuff if you don't know how to handle it well. Its frequent appearance in textbooks and tutorials for newbies is just...overrated.

Look back at the code I have there, why it only allows me to input one time? Because, when you press the enter key on the keyboard, it also puts something into the input stream. That's what we call a newline character, and getchar() accepts anything unless it's the end of file.

The first getchar() took the first character, leaving the newline there. The second one jumps in and sees the newline, so it skipped the step of asking you, since its job is already done!

So, now we can explain why adding one more getchar() there can solve the issue - the second one consumes the remaining newline character so that there will be nothing else in the input stream. Hence, the third getchar() can do it's job of taking the input.

This trick will also work for scanf() and the likes - and if you are unsure how many characters you need to consume before taking the input, you can use while (getchar() != '\n'); to eat up all the characters up to and including the first newline. But it does not deal with end-of-files, so you will need another thing to handle that...Google yourself :P I highly discourage spoonfeeding.

So, now you know how to deal with all those randomly skipped input prompts :P


I kinda wrote this out because I was a little pissed at how frequently these things appear in my assignments and it is always a headache to solve. Now I did some of my own research, I guess it's worth putting it up here. Probably someone will find it useful, and probably I will one day refer to this too :)

Until next time,

--Lilacse

Sort:  

Hello lilacse!

Congratulations! This post has been randomly Resteemed! For a chance to get more of your content resteemed join the Steem Engine Team

You’ve been upvoted by TeamMalaysia Community :-

To support the growth of TeamMalaysia Follow our upvotes by using steemauto.com and follow trail of @myach

Vote TeamMalaysia witness bitrocker2020 using this link vote for witness

Coin Marketplace

STEEM 0.27
TRX 0.11
JST 0.030
BTC 68504.89
ETH 3816.55
USDT 1.00
SBD 3.51