Getting keyboard input after fgets
I, for the life of me, cannot be at peace with c strings and input/output.
For my program I simply enter a string and it gets processed in the following code: (tmpstring and ch are already defined)
For my incomning input, I write in terminal: echo "test" | ./program
int main(int argc, char *argv[]) {
char tmpstring[2048];
int ch;
int r;
int c;
fgets(tmpstring, sizeof tmpstring, stdin);
while((ch = fgetc(stdin))!= EOF && ch != '\n');
tmpstring[strlen(tmpstring)-1]='\0';
strncpy(opponent, tmpstring+1, strlen(tmpstring+1));
move();
Inside of move();
char buffer[2048]={0};
int r, c;
r=0; c=0;
printf("Your move (row column):");
if((fgets(buffer, sizeof buffer, stdin)==NULL) || ((sscanf(buffer,"%d %d", &r, &c))!=2)){
printf("Invalid input. Please insert two numbers separated by whitespace.\n");
exit(1);
}
//continues
Executing this goes straight into the invalid input without asking for more input. I've read all around about how you shouldn't clear stdin 开发者_运维问答(and that it's impossible) but I really don't know what to do. I clearly tried to "dump" stdin with the second part of the while loop. I've changed the && after the first condition to an || in the while loop. No change. Overall, how can I ask for more input after already used fgets?
*edit: more code and separated the original while loop
This kind of problem has been discussed elsewhere.
I will copy a part of my own post, from here:
Max string length using scanf -> ANSI C
- It is defined a function
my_scanf()
with variable number of parameters, by invoking thestdarg.h
library, joint to a combination offgets()
andvsscanf()
. - That function is designed to handle in a right manner combinations of
fgets()
andsscanf()
(actually, we have to usevsscanf()
in order to properly process the list of arguments). - The input is read up to an upper limit of characters. if the input has more than this limit, it is truncated. The '\n' are handled correctly. The function returns the same value as
scanf()
would return. So, you can usemy_scanf()
instead.
Here you have the code:
#include <stdio.h>
#include <stdarg.h>
int my_scanf(const char* fmt, const unsigned int maxbuff, ...) {
va_list ptr;
int ret;
if (maxbuff <= 0)
return EOF; /* Bad size for buffer[] */
char buffer[maxbuff+1];
buffer[maxbuff-1] = '\0'; /* Quick buffer cleaning... */
if (fgets(buffer, maxbuff+1, stdin) == NULL)
return EOF; /* Error detected */
else {
if ((buffer[maxbuff-1] != '\n') && (buffer[maxbuff-1] != '\0'))
/* Condition logically equivalent to:
fgets() has not reached an '\n'
*/
while (getchar() != '\n')
; /* "Flushing" stdin... */
va_start(ptr, maxbuff);
ret = vsscanf(buffer, fmt, ptr);
va_end(ptr);
return ret;
}
}
#define MAXBUFF 20
int main(void) {
int x;
float z;
int scanf_ret = my_scanf("%d %g", MAXBUFF, &x, &z);
printf("\nTest:\n x == %d\n z == %g\n scanfret == %d", x, z, scanf_ret);
getchar();
return 0;
}
The function my_scanf() has the prototype
int my_scanf(const char* fmt, const int maxbuff, ...);
- It accepts a format string
fmt
that behaves in the same way as any otherscanf()
-like does. - The 2nd parameter is the maximum number of chars that will be effectively accepted from the standard input (keyboard).
The return value is an int, which is
EOF
ifmaxbuff
has no sense, or well some input error happened. If a non-negative value is returned, it is the same that would be returned by the standard functionssscanf()
orvsscanf()
.- Inside the function,
maxbuff
is incremented in 1, becausefgets()
makes some room for an additional '\0' character. - Non-positive values of
maxbuff
are immediatelly discarded. fgets()
will read a string fromstdin
(keyboard) with room for at mostmaxbuff
characters, including '\n'.- If the user has entered a very long string, then it will be truncated, and some kind of "flush" mechanism is necessary in order to discard all the characters to the next '\n' (ENTER). If not, the next keyboard reading could have older characters, not desired at all.
- The condition for "flushing" is that
fgets()
has not reached '\n' after readingstdin
. - This is true if, and only if,
buffer[maxbuff - 1]
is not equal to '\0' nor '\n'. (Check it!)
- The condition for "flushing" is that
- Finally, an appropiate (and standard) combination of
stdarg.h
macros and the functionvsscanf()
is employed to process the variable list of parameters.
- Inside the function,
精彩评论