inability to input sentences with white space - c

I'm trying to make the 20 questions game using c. The following is the code excerpt of one of the functions.
int question_input(void)
{
char q[100];
int i=0;
printf("Enter the question or say if you want to guess\n");
scanf("%[^\n]",q);
i=check_if_guess(q);
if(i==0)
{
printf("Say yes or no\n");
scanf("%s",q);
}
return i;
}
I get a general protection fault when I execute and on debugging, I found that the problem is with the
scanf("%[^\n]",q)
statement.
If the same statement is changed to "%s", then, I get no segmentation fault. Functions like gets (general protection fault) and fgets(doesn't ask for input at all) also fail to take inputs.
The thing which is more curious is that when I execute these statements in a seperate file, without the rest of the code, they execute properly.
Even if I try "%99[^\r\n]", it shows the same.
Please help

Well, I found an answer to my question by myself. One of my previous functions in my code had
scanf("%d",&n)
It is a known fact that after we enter our input we press the enter key. This is taken as a '\n' by the compiler and is stored in the buffer. My next scanf statement( the one which I got error in)(scanf("%[^\n]",q) straight away took the '\n' from the buffer. Hence it could not take any input, since \n terminates input. The compiler I use is turbo C++. In some cases of empty strings, it reports an error. Hence I got the error message. To solve this problem, I had to use
getchar()
statement before the scanf("%[^\n]",q) statement, so that the '\n' is removed from the buffer and taken as an input for the getchar statement.

Related

How to completely clear stdin and the \n before scanf()

Environment:
Windows 7 Enterprise SP1
gcc version 6.3.0 (MinGW.org GCC-6.3.0-1)
I'm new to C language (not new to programming).
I'm migrating a big program to C language. All works fine except for this.
I create this small program to reproduce the problem:
int AAA ()
{
const char *p = "Enter to proceed.. X to Exit.. : ";
const char *ok = "OK" ;
char proceed1 ;
char proceed2 ;
printf(p) ;
fflush(stdin) ;
scanf("%c",&proceed1);
if (proceed1 == 'X'){
return 0 ; }
sleep(3) ;
fflush(stdin) ;
printf("\n%s",p) ;
scanf("%c",&proceed2);
if (proceed2 == 'X'){
return 0 ; }
printf("\n%s",ok) ;
return 0 ;
}
All worls fine, BUT if the user (wrongly) hits twice the enter key at the proceed1 then scanf of proceed2 automatically reads the newline character '\n' that remain in the buffer...
I tried all: rewind(stdin), fseek stdin, a getchar before the second prompt to bypass the problem, but let the scanf hang if the user correctly hit enter key once.
I repeat I'm new to C language. I understand the problem can be bypassed writing a scanf that does not accpet the \n alone.
But before proceeding I ask here this question:
How to completely clear the stdin buffer?
Just because this is a common enough question, notwithstanding the links to other like questions and/or duplicates, I think this bears repeating:
If you are trying to fflush(stdin), you are almost certainly doing something wrong
An input buffer flush says, “I don’t care what you typed so far. I’m throwing it away and we’re starting over.”
Such behavior is exceedingly frustrating to users of a program. Users expect their inputs to be recognized and acted on — even if those inputs are wrong! By throwing it away, your program tells the user that their wishes are not respected, leaving them feeling like they have less control of their computer than they should.
It’s an XY problem
The usual suspect behind desires to clear the input is a scanf failure. The user typed something wrong, input is stuck with invalid characters, and the program needs to get past that.
But the program does not need to get any further than the next newline, which is to say, it only needs to discard stuff that was input before the user pressed Enter. This comes from one very simple principle:
The user will always press Enter after every prompted input
The solution comes in three forms:
Crash and burn. This is a strong signal that the user needs to fix his input to work, and actually provides him (or her) with a greater sense of control: the program does only what it is supposed to, accepting only input it should, and does nothing unless the input is correct!This also affords the user greater control in how he or she uses your program, because he can now supply prepared input to the program without having to babysit the keyboard.
Skip to the EOL and ask for the user to try again. This presupposes a human is frobbing the keyboard. But if you are going to go through this grief, then:
Read all input as a string, one line at a time, and endeavor to process that string (using sscanf, for example). This keeps your input and processing pointers all lined up and you will never have need to try to resynchronize with the input buffer.
Obviously, my opinion is that crash and burn is the most correct method for your usual console programs.
This is, in fact, part of the core design of Unix. This behavior enables individual utility programs to combine to perform useful scripted tasks.
The exception is a TUI program.
A text-based user interface is for a program that requires a human to operate it*, and takes over the terminal to behave in a different way, not requiring the user to press Enter to receive and act on input.
Games and text editors are examples of this kind of program.
* It is still possible to automate a TUI, of course, but the point is that the expected interaction with the program is no longer via newline-delimited streams, but rather via direct, individual key presses as input.
The C Standard says that fflush(stdin) has undefined behavior. You should not use it to flush pending input even on platforms where it seems to have the expected effect. There is no portable way to flush pending input, ie: all input that was typed before the prompt was issued.
If you just want to consume the characters typed by the user for a previous entry parsed with scanf(), up to and including the newline, you can use this simple function:
#include <stdio.h>
// Read and discard the rest of the current line of input.
// Returns EOF at end of file, otherwise returns a newline character
int flush_input(FILE *fp) {
int c;
while ((c = getc(fp)) != EOF && c != '\n')
continue;
return c;
}
If you are required to use scanf(), you can use these 2 calls:
scanf("%*[^\n]"); // read the remaining characters on the line if any.
scanf("%1[\n]"); // read the newline character if present.
Note however that you should not combine these 2 as a single call to scanf() because the first conversion will fail if the pending byte is a newline, and this newline will not be consumed by the second conversion.

Incomprehensible issue in a loop (C on Clion)

I'm learning C in my school for 2 months and I have to make a Halma's Game in the console, so I'm a newbie for now.
I use Clion and CodeBlock but I prefer Clion for his internal console.
The game work pretty good, but I've got 2 weird issues that I can't fix by myself:
- My loop is presumed to stop with the scanf,but it doesnt.
("saut" variable).
It work only in the 2nd(or more) passage in the loop.
-The variable "h" increment during the loop (in order to ignore the next condition when you are out the loop), but the program always get in.
I don't know why..
Check my code:
MY CODE (IN FRENCH DON'T WORRY ABOUT
Thanks for your help.
Robin.
On some platforms (especially Windows and Linux) you can use fflush(stdin);:
Do modify your code like :-
while(saut==1)
...
....
scanf("%d",&saut);
fflush(stdin);
}
fflush(stdin);
these is another trick to solve this issue :-
It goes into an infinite loop because scanf() will not consumed the input token if match fails. scanf() will try to match the same input again and again. you need to flush the stdin.
if (!scanf("%d", &sale.m_price)) fflush(stdin)

C program stops accepting input at 1023 characters

I'm teaching myself C using K&R. Exercise 1-16 asks me to refactor some provided code to give the length of "arbitrarily long input lines".
Whilst working on the problem I found that my terminal ceases to accept input after 1023 characters; a very suspicious number I'm sure you'll agree!! I have tested on Mac OS X and OpenBSD and see the same behaviour. The program hasn't stopped responding because typing backspace and submitting the input works correctly.
I couldn't figure out how to debug this with gdb because the problem occurs during data entry, not after submission when stepping through with gdb.
I could see no reference to a limit in the getchar or bash manpages, and indeed it seems very little input anyway.
I reduced the problem to the following and see the same behaviour.
#include <stdio.h>
main()
{
int c,i=0;
while ((c=getchar()) != EOF && c!='\n')
++i;
printf("%d\n",i);
return 0;
}
Could people please explain:
Why this is happening
How I might debug this kind of issue myself
Many thanks.
As per the comments on my question, it would appear to be a terminal limitation. Piping a file into the program works as expected.

fseek(stdin,0,SEEK_SET) and rewind(stdin) REALLY do flush the input buffer "stdin".Is it OK to use them? [duplicate]

This question already has an answer here:
Can fseek(stdin,1,SEEK_SET) or rewind(stdin) be used to flush the input buffer instead of non-portable fflush(stdin)?
(1 answer)
Closed 8 years ago.
I was thinking since the start that why can't fseek(stdin,0,SEEK_SET) and rewind(stdin) flush the input buffer since it is clearly written in cplusplusreference that calling these two functions flush the buffer(Input or Output irrespective).But since the whole idea seemed new,I had put it in a clumsy question yesterday.
Can fseek(stdin,1,SEEK_SET) or rewind(stdin) be used to flush the input buffer instead of non-portable fflush(stdin)?
And I was skeptical about the answers I got which seemed to suggest I couldn't do it.Frankly,I saw no reason why not.Today I tried it myself and it works!! I mean, to deal with the problem up the newline lurking in stdin while using multiple scanf() statments, it seems like I can use fseek(stdin,0,SEEK_SET) or rewind(stdin) inplace of the non-portable and UB fflush(stdin).
Please tell me if this is a correct approach without any risk.Till now, I had been using the following code to deal with newline in stdin: while((c = getchar()) != '\n' && c != EOF);. Here's my code below:
#include <stdio.h>
int main ()
{
int a,b;
char c;
printf("Enter 2 integers\n");
scanf("%d%d",&a,&b);
printf("Enter a character\n");
//rewind(stdin); //Works if activated
fseek(stdin,0,SEEK_SET); //Works fine
scanf("%c",&c); //This scanf() is skipped without fseek() or rewind()
printf("%d,%d,%c",a,b,c);
}
In my program, if I don't use either of fseek(stdin,0,SEEK_SET) or rewind(stdin),the second scanf() is skipped and newline is always taken up as the character.The problem is solved if I use fseek(stdin,0,SEEK_SET) or rewind(stdin).
I'm not sure where you read on cplusplusreference (whatever that is) that flushing to end of line is the mandated behaviour.
The closest matches I could find, http://www.cplusplus.com/reference/cstdio/fseek/ and http://www.cplusplus.com/reference/cstdio/rewind, don't mention flushing at all, other than in reference to fflush().
In any case, there's nothing in the C standard which mandates this behaviour either. C11 7.20.9.2 fseek and 7.20.9.5 rewind (which is, after all, identical to fseek with zero offset and SEEK_SET) also make no mention of flushing.
All they state is that the file pointer is moved to the relevant position in the stream.
So, to the extent this works in your environment, all we can say is that this works in your environment. It may not work elsewhere, it may even stop working in your envirnment at an indeterminate point in the future.
If you really want robust input, you should be using a two-stage approach, fgets to retrieve a line followed by sscanf to get what you want from that line. Mixing the two paradigms of input (scanf and getchar) is frequently problematic.
A good (robust, error-checking, and clearing to end of line if needed) input function can be found here.
I tested it right ago, and I checked that fseek doesn't work on stdin. fseek() usually works on the file on the disk so that it seems to be prohibited to access to stdin by the kernel for some secure reasons. Anyway, it was so happy to see who thought like me. Tnx for good question.

How to use sscanf correctly and safely

First of all, other questions about usage of sscanf do not answer my question because the common answer is to not use sscanf at all and use fgets or getch instead, which is impossible in my case.
The problem is my C professor wants me to use scanf in a program. It's a requirement.
However the program also must handle all the incorrect input.
The program must read an array of integers. It doesn't matter in what format the integers
for the array are supplied. To make the task easier, the program might first read the size of the array and then the integers each in a new line.
The program must handle the inputs like these (and report errors appropriately):
999999999999999...9 (numbers larger than integer)
12a3 (don't read this as an integer 12)
a...z (strings)
11 aa 22 33\n all in one line (this might be handled by discarding everything after 11)
inputs larger than the input array
There might be more incorrect cases, these are the only few I could think of.
If the erroneous input is supplied, the program must ask the user to input again until
the correct input is given, but the previous correct input must be kept (only incorrect
input must be cleared from the input stream).
Everything must conform to C99 standard.
The scanf family of function cannot be used safely, especially when dealing with integers. The first case you mentioned is particularly troublesome. The standard says this:
If this object does not have an appropriate type, or if the result of
the conversion cannot be represented in the object, the behavior is
undefined.
Plain and simple. You might think of %5d tricks and such but you'll find they're not reliable. Or maybe someone will think of errno. The scanf functions aren't required to set errno.
Follow this fun little page: they end up ditching scanf altogether.
So go back to your C professor and ask them: how exactly does C99 mandate that sscanf will report errors ?
Well, let sscanf accept all inputs as %s (i.e. strings) and then program analyze them
If you must use scanf to accept the input, I think you start with something a bit like the following.
int array[MAX];
int i, n;
scanf("%d", &n);
for (i = 0; i < n && !feof(stdin); i++) {
scanf("%d", &array[i]);
}
This will handle (more or less) the free-format input problem since scanf will automatically skip leading whitespace when matching a %d format.
The key observation for many of the rest of your concerns is that scanf tells you how many format codes it parsed successfully. So,
int matches = scanf("%d", &array[i]);
if (matches == 0) {
/* no integer in the input stream */
}
I think this handles directly concerns (3) and (4)
By itself, this doesn't quite handle the case of the input12a3. The first time through the loop, scanf would parse '12as an integer 12, leaving the remaininga3` for the next loop. You would get an error the next time round, though. Is that good enough for your professor's purposes?
For integers larger than maxint, eg, "999999.......999", I'm not sure what you can do with straight scanf.
For inputs larger than the input array, this isn't a scanf problem per se. You just need to count how many integers you've parsed so far.
If you're allowed to use sscanf to decode strings after they've been extracted from the input stream by something like scanf("%s") you could also do something like this:
while (...) {
scanf("%s", buf);
/* use strtol or sscanf if you really have to */
}
This works for any sequence of white-space separated words, and lets you separate scanning the input for words, and then seeing if those words look like numbers or not. And, if you have to, you can use scanf variants for each part.
The problem is my C professor wants me to use scanf in a program.
It's a requirement.
However the program also must handle all the incorrect input.
This is an old question, so the OP is not in that professor's class any more (and hopefully the professor is retired), but for the record, this is a fundamentally misguided and basically impossible requirement.
Experience has shown that when it comes to interactive user input, scanf is suitable only for quick-and-dirty situations when the input can be assumed to correct.
If you want to read an integer (or a floating-point number, or a simple string) quickly and easily, then scanf is a nice tool for the job. However, its ability to gracefully handle incorrect input is basically nonexistent.
If you want to read input robustly, reliably detecting incorrect input, and perhaps warning the user and asking them to try again, scanf is simply not the right tool for the job. It's like trying to drive screws with a hammer.
See this answer for some guidelines for using scanf safely in those quick-and-dirty situations. See this question for suggestions on how to do robust input using something other than scanf.
scanf("%s", string) into long int_string = strtol(string, &end_pointer, base:10)

Resources