Alternate method for clearing input buffer in c - c

Is there any other method to clear the input buffer in c withut using
fflush();
or
while(getchar()!='\n');
Because i have read it everywhere and cant find any other way to do it.

The best solution is to not depend on the input buffer's state so much.
Read input as whole lines, using fgets(), then parse those. Don't use e.g. scanf() to read individual values, since it interacts with the buffer in annoying ways.

Using fgets() as suggester #unwind best approach.
To flush to the end of the line.
void FlushStdin(void) {
int ch;
while(((ch = getchar()) !='\n') && (ch != EOF));
}
If stdin is all ready flushed to the end-of-line, calling FlushStdin() or other posted scanf(), fgetc() solutions, will flush to the end of the next line.
Note scanf("%*[^\n]%*1[\n]"); does not work if the next char is '\n'.

Another method to clear the input buffer(stdin) would be to use
scanf("%*[^\n]%*1[\n]");
Here,%*[^\n] instructs scanf to scan everything until a new-line character(\n) is found and then discard it.The %1*[\n] tells scanf to scan 1 character including a \n character and discard it also.

Related

How fget works?

I am using gcc (Ubuntu 4.8.2-19ubuntu1) 4.8.2
I am writing a very simple script to take string as input and print the same with the some custom message. First user enters the T(no. of times to take string) and then takes input by fgets.. I used this&this as reference. I am getting a very strange output ie fgets is adding some extra new lines and even loop is not working properly for T=2 it is asking input only once. Can anybody explain me what is wrong with snippet. Thanks in advance!
#include<stdio.h>
#include<string.h>
int main()
{
int T;
scanf("%d",&T);
while(T--){
char str[100]={""};
int i;
printf("Hello\n");
fgets(str,80,stdin);
i = strlen(str)-1;
if(str[i]=='\n')
str[i]='\0';
printf("World\n");
printf("%s\n",str);
}
return 0;
}
Please see the image reference for T=2, even T=2 it is taking string only once and order of printing statement is also not as expected.
This is because your scanf() call
scanf("%d",&T);
does not consume the new line character \n accompanied by your input.
When you input T, your input is 2Enter.
scanf() consumes the 2, sees \n and stops consuming, leaving \n in the input buffer.
When the fgets() gets called, it sees the \n in the buffer and treats this as the input.
To solve this, you have a few choices (in decreasing order of my subjective preference):
Use fgets() to get the first input, then parse it using strtol() to get T.
Add an extra fgets() after the scanf().
Add getchar() to consume one extra character. This works if you are certain that exactly one \n will be present after the input. So for example it won't work if you type 2SpaceEnter. Alternatively, you may use while(getchar() != '\n'); after the scanf() to consume everything up to a new line, but this may cause problems if an empty line is a valid input to your later fgets() calls.
If your implementation supports it, you may use fpurge(stdin) or __fpurge(stdin).
And, very importantly, do not use fflush(stdin) unless your implementation clearly defines its behavior. Otherwise it is undefined behavior. You may refer to this question for more details. Also, note that the fpurge() and fflush() methods may not work correctly if your input can be piped into the program.
This line
scanf("%d",&T);
reads the input until the first non-numeral is found, which is newline. Then fgets() reads that newline for its first input.
I suggest using fgets() to read the number too.
fgets(str,80,stdin);
sscanf(str, "%d", &T);
With your first call to scanf you allow the user to input an integer for the number of loops. They do so, and use a carriage return to signal the end of input. At this point scanf reads the integer, but leaves the end-of-line (\n) in the stream..
So when you call fgets, fgets gets from the stream until it reaches the first newline -- in you code, on the first loop, this is the very first character it encounters.
If you discard the newline before calling fgets, you should get your desired results. You can do this, for example by changing your first three lines to:
int T;
char newline;
scanf("%d%c",&T, &newline);
Although there are probably stylistically superior ways of doing this.
You have a newline character in the input stream when you press "enter" after typing 2 for the first scanf. This is consumed by fgets() initially, hence it prints nothing (You replace the newline by \0).
In the next line, your input is read and echoed after World because you are printing it after it.

Alternative to C library-function fflush(stdin)

Can anyone explain how the following code could be explained, I dont understand it really.
while((c = getchar()) != '\n' && c != EOF);
I know that its used to flush the inputstream and that it could be replaced with the standard C library-function:
fflush(stdin)
while((c = getchar()) != '\n' && c != EOF);
This reads input characters until it reaches either the end of the line (i.e., getchar() returned '\n) or end-of-file or an error condition (i.e., getchar() returned EOF).
If stdin is reading from the keyboard, it discards input until you press Enter.
Leaving off the EOF check could give you an infinite loop if there's an input error, or if you trigger an end-of-file condition (on Unix, by typing Ctrl-D twice).
This could be useful, for example, after using scanf() to read an integer. If you execute scanf("%d", &num); and type 123, it will read those 3 digits (and store the value 123 in n), but leave everything after that waiting to be read. The above line can be used to skip the rest of the input line.
(An alternative, likely a better one, is to read whole lines using fgets() and parse them using sscanf().)
This is not equivalent to fflush(stdin). A far as the C standard is concerned, calling fflush on an input stream has undefined behavior.
Some implementations do define the behavior of fflush(stdin). On systems that use GNU libc, for example (most Linux system):
For input streams, fflush() discards any buffered data that has
been fetched from the underlying file, but has not been consumed by
the application.
That's not the same as discarding input up to the end of the line. And using it makes your code non-portable.
This code, assuming the file (or some other input) has been opened, will continue to get character by character until it finds a newline (\n) or an end of file (eof).
fflush will just clear the stream for an open file.

Best way to read stdin that may include newline?

I have to write a program in C that handles the newline as part of a string. I need a way of handling the newline char such that if it is encountered, it doesn't necessarily terminate the input. So far I've been using fgets() but that stops as soon as it reaches a '\n' char. Is there a good function for processing the input from the console that doesn't necessarily end at the newline character?
To clarify:
I need a method that doesn't terminate at the newline char because in this particular exercise when the newline char is encountered it's replaced with a space char.
fgets gets a line from a stream. A line is defined as ending with a newline, end-of-file or error, so you don't want that.
You probably want to use fgetc. Here's a code example of a c program file fgetc.c
#include <stdio.h>
int main (void) {
int c;
while ((c = fgetc(stdin)) != EOF) fputc(c, stdout);
}
compile like this:
cc fgetc.c -o fgetc
use like this (notice the newline character '\n'):
echo 'Hello, thar!\nOh, hai!' | ./fgetc
or like this:
cat fgetc.c | ./fgetc
Read the fgetc function manual to find out more: man fgetc
If I understand your question correctly you want to read from the standard input until user has finished typing ( which ain't be a newline of course ). This can be done by setting a flag like EOF while getting input. One way which I came out with is this:
#include <stdio.h>
int main(void)
{
char ch;
char str[100];
int i = 0;
setbuf (stdout,NULL);
while ( (ch = getchar()) != EOF)// user can input until the EOF which he or she enters to mark the end of his/her typing or more appropriately input.
{
str[i] = ch;// you can store all the input character by character in a char array
i++;
}
printf ("%s",str);// then you can print it at last as a whole
return 0;
}
BEGINNER's NOTE- EOF can vary from system to system so check it and enter the proper EOF for your system.
If you are simply reading blocks of information without the need for scanf(), then fread() may be what you are after. But on consoles you can read to the \n, notice the \n, then continue reading more if you decide that \n is not for you.
scanf works when used as directed. Specifically, it treats \n as white space.
Depending on how your application is coded (i.e. how buffers are defined), a \n prompts the system to flush the buffer and feed data into scanf. This should occur as a default without you having to do anything.
So the real question is, what kind of data or characters do you need from the console? In some cases scanf will remove white space and NOT pass blanks, tabs, new lines, into your program. However, scanf can be coded to NOT do this!
Define how data should be entered and I can guide you on how to code scanf.

fgets instructions gets skipped.Why?

Whenever I do a scanf before a fgets the fgets instruction gets skipped. I have come accross this issue in C++ and I remember I had to had some instrcution that would clear the stdin buffer or something like that. I suppose there's an equivalent for C. What is it?
Thanks.
I'll bet it's because of the \n stuck in the input stream.
See one of these questions:
I am not able to flush stdin.
How do I go about Flushing STDIN here?
scanf() causing infinite loop
or this answer.
Also: Why not to use scanf().
P.S. fgets() is a function, not an instruction.
The fgets() function following the call to scanf() is probably1 not getting skipped. It is probably1 returning immediately having found a newline in the input stream.
Calling scanf() before fgets() almost always results in scanf() leaving an unused newline ('\n') in the input stream, which is exactly what fgets() is looking out for.
In order to mix scanf() and fgets(), you need to remove the newline left behind by the call to scanf() from the input stream.
One solution for flushing stdin (including the newline) would be something along the lines of the following:
int c;
/* discard all characters up to and including newline */
while ((c = getchar()) != '\n' && c != EOF);
1 - It is difficult to be certain without seeing the actual code.
Or, as Jerry Coffin suggested in his comment below, you could use scanf("%*[^\n]");. The "%*[^\n]" directive instructs scanf() to match things that are not newlines and suppress assignment of the result of the conversion.
/* match up to newline */
scanf("%*[^\n]");
/* discard the newline */
scanf("%*c");
From http://c-faq.com/stdio/gets_flush1.html:
An initial scanf() with “%*[^\n]” will either eat everything up to but not including a newline, or fail. A subsequent “%*c” (or plain old getchar()) will consume the newline, if there was one.
That last “if” matters too: perhaps the user signalled EOF. In this case, the getchar() or scanf("%*c") might -- this decision is left to the people who write your compiler -- either immediately return EOF, or go back to the user for more input. If the implementors choose the latter, the user might have to click on “end this thing” (^D, ^Z, mouse button, front panel switch, or whatever) one extra time. This is annoying, if nothing else.
Or, as Chris Dodd suggested in his comment below, you could use scanf("%*[^\n]%*1[\n]");. The "%*[^\n]%*1[\n]" directive instructs scanf() to match things that are not newlines and then match one newline and suppress assignment of the results of the conversion.
/* match and discard all characters up to and including newline */
scanf("%*[^\n]%*1[\n]");
You can just put this line before your fgets() call and that'll get the trailing '\n' generated when you pressed enter
scanf("%c", (char *) stdin);

how to read scanf with spaces

I'm having a weird problem
i'm trying to read a string from a console with scanf()
like this
scanf("%[^\n]",string1);
but it doesnt read anything. it just skips the entire scanf.
I'm trying it in gcc compiler
Trying to use scanf to read strings with spaces can bring unnecessary problems of buffer overflow and stray newlines staying in the input buffer to be read later. gets() is often suggested as a solution to this, however,
From the manpage:
Never use gets(). Because it is
impossible to tell without knowing the
data in advance how many characters
gets() will read, and because gets()
will continue to store characters past
the end of the buffer, it is extremely
dangerous to use. It has been used to
break computer security. Use fgets()
instead.
So instead of using gets, use fgets with the STDIN stream to read strings from the keyboard
That should work fine, so something else is going wrong. As hobbs suggests, you might have a newline on the input, in which case this won't match anything. It also won't consume a newline, so if you do this in a loop, the first call will get up to the newline and then the next call will get nothing. If you want to read the newline, you need another call, or use a space in the format string to skip whitespace. Its also a good idea to check the return value of scanf to see if it actually matched any format specifiers.
Also, you probably want to specify a maximum length in order to avoid overflowing the buffer. So you want something like:
char buffer[100];
if (scanf(" %99[^\n]", buffer) == 1) {
/* read something into buffer */
This will skip (ignore) any blank lines and whitespace on the beginning of a line and read up to 99 characters of input up to and not including a newline. Trailing or embedded whitespace will not be skipped, only leading whitespace.
I'll bet your scanf call is inside a loop. I'll bet it works the first time you call it. I'll bet it only fails on the second and later times.
The first time, it will read until it reaches a newline character. The newline character will remain unread. (Odds are that the library internally does read it and calls ungetc to unread it, but that doesn't matter, because from your program's point of view the newline is unread.)
The second time, it will read until it reaches a newline character. That newline character is still waiting at the front of the line and scanf will read all 0 of the characters that are waiting ahead of it.
The third time ... the same.
You probably want this:
if (scanf("%99[^\n]%*c", buffer) == 1) {
Edit: I accidentally copied and pasted from another answer instead of from the question, before inserting the %*c as intended. This resulting line of code will behave strangely if you have a line of input longer than 100 bytes, because the %*c will eat an ordinary byte instead of the newline.
However, notice how dangerous it would be to do this:
scanf("%[^n]%*c", string1);
because there, if you have a line of input longer than your buffer, the input will walk all over your other variables and stack and everything. This is called buffer overflow (even if the overflow goes onto the stack).
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *text(int n);
int main()
{
char str[10];
printf("enter username : ");
scanf(text(9),str);
printf("username = %s",str);
return 0;
}
char *text(int n)
{
fflush(stdin);fflush(stdout);
char str[50]="%",buf[50],st2[10]="[^\n]s";
char *s;itoa(n,buf,10);
// n == -1 no buffer protection
if(n != -1) strcat(str,buf);
strcat(str,st2);s=strdup(str);
fflush(stdin);fflush(stdout);
return s;
}

Resources