InsaneCoder
InsaneCoder

Reputation: 8268

Inputting characters and integers in a line in c reading characters from past input stream

I was always bad at inputting characters in C and this is another example. Though I understood (maybe) what's happening but I can't figure out the solution.

I have the following code

scanf("%ld %ld",&n,&m);

for(i=0;i<n;i++)
    scanf("%ld",&array[i]);

for(i=0;i<m;i++)
{
    fflush(stdin);
    //inputting a character 'R' but it is picking '\n' from past buffer
    scanf("%c",&query);

    //As a result of above problem, it is also acting wierd for same reason
    scanf("%ld",&d);

    printf("%c %ld",query,d);
    printf("\nI=%ld\n",i);
}

Please help me figure out the reason why its happening and what is the solution.

Upvotes: 1

Views: 1786

Answers (2)

pablo1977
pablo1977

Reputation: 4433

Since you are tired of input issues, I can give you a method that can help to simplify your live.
I can observe that:

  • You have problems in handling end-of-lines.
  • Sometimes you need to input numbers and sometimes you need characters or another kind of input. So, you (think that you) are forced to use formatted input.

My advice is that you separate the issue of reading input from the issue of interpreting data entered from input.

The standard C brings only a few functions to handle input/output operations, in the standard header <stdio.h>.
If you are not interested in very sofisticated I/O results, the standard library is enough.
However, the functions of <stdio.h> usually have the effect that input is read one line at the time, which includes the end-of-line character: '\n'.

What you can do, then, it's what follows:

  1. Read a line with fgets(..., stdin) and put the result in a buffer (not so long), used only for this purpose.
    Once you have read an entire line, no more issues with end-of-line will bother you.
  2. Then, re-read this line, that it's held in a buffer, and apply to it all the formatted input that you need.

A short example:

 #include <stdio.h>
 int main(void) {
   char buffer[200] = ""; // Initialize array to 0's
   long int n, m;
   char c;

   fgets(buffer, sizeof(buffer), stdin);
   sscanf(buffer,"%ld %ld",&n,&m);

   // Now you have processed the "integer number" input,
   // read input characters again, withou any "flushes" and extrange things:

   fgets(buffer, sizeof(buffer), stdin);
   sscanf(buffer,"%c", &c);

   fgets(buffer, sizeof(buffer), stdin);
   // and so on...

 }

Thus, every time you need to separate a section of input from a previous one, just do a new line reading with fgets(..., stdin), which stores the input in buffer, and then process the buffer with sscanf(), which applies the format string to the buffer instead of the input itself (in its flesh).

Note: This method can have a little problem: If the string input has more than sizeof(buffer) characters (in the example: 200), the line is not completely read. This situation can be handled by checking if the character before last in buffer is not equal to '\n' nor '\0'. In such a case, you would make automatically some kind of "flushing input" operation (reading and discarding characters till the next end-of-line is found).

Upvotes: 1

M.M
M.M

Reputation: 141598

Using scanf with %d (or %ld) only extracts the number from the input stream; it leaves the newline in the stream.

So when you write scanf("%c", it reads that newline.

To fix this (if your intent is that scanf("%c" reads the first character of the next line), you need to flush the input of the previous line. One way to do that is:

int ch; while ( (ch == getchar()) != EOF && ch != '\n' ) { }

Your line fflush(stdin); causes undefined behaviour - don't do that. The fflush function is only for output streams.

Also , it is a really good idea to check the return value of scanf. If it was not what you expected then you may wish to take some action, instead of pretending that a number was entered.

Upvotes: 1

Related Questions