Escaping "white space" escaping in C - c

I'm it really sure how to explain this question but i'll give it a try.
I have this line of code in my program:
scanf (" %c", &character);
Notice the space before %c. This is supposed to keep the scanf from interpreting the last ENTER key as a character. This works, however after this line and its resulting printf output the program will not continue to execute until I provide another character and then press the ENTER key. After that it ignore all scanf and prints all printf output with the absence of any user input. Does that make sense. Im new to C so im sure im missing something simple but I couldn't find any solutions.
Thanks!

The standard input is buffered.
Your code will not see the buffer until it (the standard input) is flushed.
This happens when the buffer becomes full or the '\n' (Enter Key) is inserted.
Because scanf() is a blocking I/O call. The application will wait for input (indefinitely). Thus making the code look like it has stalled.
IMHO
You should not try and interpret what has happend behind you in previous parts of the code. This will couple your code to other input that you may have no control over. Your input should read everything it need to and no more.
For example: If you ask the user to enter a character then hit enter. You should remove the character then enter from the input stream. You should not expect the next user of the stream to tidy up for you (or compensate for your code).
printf("Enter (Y/N)\n");
scanf("%c", &character);
scanf("%*[^\n]"); // Ignore everything to the end of line.
// Assuming you have told the user you will ignore
// extraneous characters. The next input should now
// expect only what they need.

Try this:
scanf ("\n%c", &character);
It should "consume" the \n character in buffer and then wait for a new char.

In your previous scanf call, use something like scanf("%c\n", &character); to eat the newline as it is entered. This is typically less error-prone than waiting to handle it the next time you need input.

Related

why does this part of the program skip the second input?

On entering the first inputs this part of my program terminates.
float p_x,p_y,q_x,q_y,r_x,r_y;
printf("Note :- coordinates are entered as follows (x,y) \n");
printf("Enter the coordinates of 'p' :");
scanf("(%f,%f)",&p_x,&p_y);
printf("Enter the coordinates of 'q' :");
scanf("(%f,%f)",&q_x,&q_y);
Short answer: Change the second scanf call to
scanf(" (%f,%f)", &q_x, &q_y);
Note the extra space in the format statement.
Longer explanation: One of scanf's quirks is that it only reads what it needs, and leaves everything else sitting on the input stream for next time. So when you read p_x and p_y, scanf reads the (, the value for p_x, the ,, the value for p_y, and the ), but it doesn't do anything with the invisible final \n on the line, the "newline" character that's there as a result of the Enter key you typed.
So, later, when you try to read q_x and q_y, the first thing scanf wants to see is the ( you said should be there, but the first thing scanf actually sees is that \n character left over from last time. So the second scanf call fails, reading nothing.
In a scanf format statement, a space character means "read and ignore whitespace". So if you change the second format string to " (%f,%f)", scanf will read and ignore the stray newline, and then it will be able to read the input you asked for.
The reason you don't have this problem all the time is that most (though not all) of the scanf format characters automatically skip leading whitespace as a part of doing their work. If you had, say, a simpler call to
scanf("%f", &q_x);
followed by a later call to
scanf("%f", &q_y);
it would work just fine, without any extra explicit space characters in the format strings.
General advice: You may be thinking that this is a pretty lame situation. You may have gotten the impression that scanf was supposed to be a nice, simple way to do input in your C programs, and you may be thinking, "But this is not simple! How was I supposed to know to write " (%f,%f)"?" And I would absolutely agree with you: This is a pretty lame situation!
The fact is that scanf only seems to be a nice, simple way to do input. It's actually a terribly complicated, unforgiving, nearly useless mess. It's only simple if you're reading very simple input, such as single numbers or simple strings (not containing spaces), or maybe single characters. For anything more complicated than that, there are so many quirks and foibles and exceptions and special cases that it almost never works the first time, and it's often more trouble than it's worth to even try to get it working.
So the general advice is to only try to use scanf for very simple input, during the first few weeks of your C programming career. You can read what I mean by "very simple input" in this answer to a previous question. Then, once you've gotten a few skills under your belt, or when you need to do something a little more complicated, its time to learn how to do input using better techniques than scanf.
Check return value to identify problems.
// scanf("(%f,%f)",&q_x,&q_y);
if (scanf("(%f,%f)",&q_x,&q_y) != 2) {
puts("Bad input");
}
Tolerate and consume spaces, new lines, tabs, etc. between portion of input. OP did not do this. The '\n' of the first entry was not consumed and caused the 2nd scanf() to fail. "%f" already allows optional leading white-spaces. Add a " " before the fixed formats characters: (,) so optional white-spaces will get consumed there too.
// v---v---v add spaces to format to allow any white-space in input.
if (scanf(" (%f ,%f )",&q_x,&q_y) != 2) {
puts("Bad input");
}

fgets reads newline character from prompt

I should mention that this does work in a different environment: in our programming class we normally use the IDE codeblocks (which is find awful), so I just use the gcc compiler and vim in my terminal (I'm on arch). I didn't encounter problems until recently, when I had to read in a string which contained spaces. For that I thought using the fgets() function would be a good idea, but it created some problems. This is what the code looks like:
void addStudent() {
struct Student student;
printf("Name of student: ");
fgets(student.name, 25, stdin);
}
This however does not prompt me for input in my shell, it simply continues and reads in a newline character \n immediately. Do you guys have any idea how to fix this?
As pointed out by the comments, it's not good to combine a function like scanf() with fgets(). When scanf() is called it leaves a newline character in the input buffer which is then immediately read by fgets(), causing it to fail prompting the user.

How does \n affect string scan in scanf? [duplicate]

This question already has answers here:
Why does scanf ask twice for input when there's a newline at the end of the format string?
(7 answers)
Closed 4 years ago.
Here's a simple example: I have an array of 3 characters, I write an input on terminal and I want to check immediately what i scanned, like this:
scanf("%3s\n",array);
printf("%s",array);
What i want to know is: why, after running the program, if I write on terminal "abc", to make it print out the array I have to put another input, like writing another letter or a number?
If I write "abcd" and then press ENTER then it immediately prints, but if I just write "abc" and press ENTER many times it still doesn't go to the next instruction (which is printf).
I know that it has to do with how \n makes scanf read the string, but I cant quite get it.
It is not the printf (as the first version of your now edited title implied) which needs the additional input, it is the scanf.
Your format string contains a "\n".
That happens to be a white space.
Any whitespace in that position will tell scanf to consume any number of whitespace following the three characters (e.g. "abc").
As long as you continue adding whitespace (including returns), the scanf is not done consuming "all following whitespace".
As soon as you enter any non-whitespace (e.g. "d") it knows "aha, all whitespace done". Then, and not before, it can complete. Leaves the non-whitespace in the input stream and returns.
Note (credits to chux) that with a (commonly, to the point of almost always if you did not intentionally change that) line buffered input, you need to enter such a non-whitespace with a return/newline following it somewhere.
Note, as mentioned in comments, you need 4 characters of space in your target array, to also accomodate the always written "\0" at the end of the string. If you only have three characters space, then the last 0 will be written beyond causing undefined behaviour.
I am not sure how to solve your problem, because I cannot tell what the purpose of your "\n" is. But I think you should try the behaviour if you move the "\n" out of scanf() and maybe into the printf(). A following scanf() call starting with a conversion specifier (except "[", "c", and "n") consumes any leading whitespace anyway, including any remaining newlines/returns from this one.

Using scanf for question, allow user to skip question

I'm working on a final project for a C programming course. The project is to create a database to store drug information. I've completed all of the elements and now it's down to fine tuning everything.
There's a requirement in the project in the function where the user can change the drugs information. In the requirement, the user should be able to skip a field by hitting enter. For example, the user can change the producer of the drug and the quantity. If the user didn't want to change the producer, they'd hit enter and move onto the quantity.
I've looked around the internet and was able to let the user skip entering a string for the producer. However, I cannot get it work with an integer.
This is what I used so that the user can skip entering a string:
scanf("%30[^\n]", fentry[found].producer);
For clarity sake, fentry.producer is a string with 30 characters and found is an integer variable.
I've tried doing something similar with the integer input (EDIT: By integer input, I meant the one to enter the quantity, not the 'found' varible). It will let you skip entering something, but if you do enter something, it stores a random value.
Anyone know how to go about this?
Rather than using scanf(), a better way to get interactive input from a user is to use fgets(). This function gets a complete line of input up to where the user presses Enter, and returns it so you can parse it.
You can then use sscanf() to read the information out of the line, if you like. sscanf() works almost exactly like scanf() except it reads data from a string rather than from standard input.
Have you initialized the integer to 0 before the scanf?
What about this?
char s[50];
fgets(s, 50, stdin);
if(s[0] != '\n') {
fentry[found].producer = atoi(s);
}
You have to remove all spaces from s though.
scanf("%29s", fentry[found].producer); while('\n'!=getchar());
This works at all, is strictly ANSI C conform, max. portable.
Input buffer is cleared, chararray-length is supported, chararray contains ever a (terminating) '\0' (no initialization needed) and your array contains never the '\n' from user input.
I suspect the keyboard buffer is causing the problems in your code. The first time you call the code, it will read a maximum of 30 characters - so long as they are not the NEWLINE character. They will terminate when they read the NEWLINE. The NEWLINE will remain in the buffer.
However... if you call scanf in the same way again, the NEWLINE from the previous call will still be in the keyboard buffer. This will be read before requesting more input from the keyboard. The NEWLINE will immediately fail the scanf pattern, the char array will not be updated, and you will be left to a char pointer that points to an uninitialized area of memory.

Force scanf to consume newline

I have a program that reads data from stdin. This data is a sequence of bytes. If there is a byte describing a new line in it (in hex: 0x0A), scanf stops reading.
Can I mask this byte, so that scanf continues to read the whole sequence?
It is important that the memory, that is written by scanf contains the newline-byte.
Without seeing your code, I can't make a precise recommendation. But if your goal is take the input "as-is", I'll recommend read() as an alternative to scanf(). See this question for someone who had the exact opposite issue.
scanf("%[^`]s", str);
You can use some thing like this. `\n will now be the terminating sequence of characters. You can replace ` using any other character or even a group of them and input will end with that character followed by a \n.

Resources