You are not logged in.
Pages: 1
Hi, I'm learning C and have a question now:
Why does fgets not work in this case? What can I do to make it to work? Thanks for helping me.
#include <stdio.h>
int main(int argc, char **argv) {
printf("[0]: Integer or [1]: String? ");
short s;
scanf("%hd",&s);
switch(s) {
case 0: printf("Enter an integer: ");
int i;
scanf("%d",&i);
printf("You prompted %d.\n",i);
break;
case 1: printf("Enter a string: ");
char str[30];
scanf("%30s",&str[0]);
//fgets(str,30,stdin);
printf("You prompted \'%s\'.\n",str);
break;
}
return 0;
}
Offline
Hey,
#include <stdio.h>
int main(int argc, char **argv) {
printf("[0]: Integer or [1]: String? ");
short s;
scanf("%hd",&s);
switch(s) {
case 0: printf("Enter an integer: ");
int i;
scanf("%d",&i);
printf("You prompted %d.\n",i);
break;
case 1: printf("Enter a string: ");
char str[30];
// You don't have to write the number of characters you will read.
// &str[0] is equal to str
//scanf("%s", str);
// the reason why fgets doesn't work is because a '\n' is in the stdin-buffer.
// Under windows you could do a fflush(stdin) (cause it's defined in the c-runtime)
// but under linux your application would work undefined, cause it's not defined in the standard to flush the stdin stream
// a simple workaround would be:
getchar(); // get the '\n' and throw it away
fgets(str,30,stdin); // note: fgets reads also the '\n' so...
printf("You prompted \'%s\'.\n",str); // ... will give a strange output
break;
}
return 0;
}
Last edited by xephinx (2011-02-13 13:04:35)
A simple, lightweight distribution - Why the hell 'simple' ? It doesn't sound geekish -.-"
Offline
// You don't have to write the number of characters you will read. // &str[0] is equal to str //scanf("%s", str);
Omitting the size also results in a nice buffer overflow. If you didn't use the "%30s" on purpose, please make sure you understand why it was there, Radioactiveman.
And I know it has nothing to do with your question, but you might not be aware of the fact, that you're writing C99 and not pure ANSI. It's often considered best to start with learning the good old pure C, so you might want to check gccs output after using it with `-Wall -pedantic'.
Offline
Thanks for your help and I know why I used '%30s' and that my code is not C90 conform.
What I still don't understand is, why I need getchar here.
Is the '\n' already before the input by fgets in the stdin-buffer?
And why do I not need getchar if I use something like this?
#include <stdio.h>
int main(int argc, char **argv) {
char str[30];
fgets(str,30,stdin);
printf("%s\n",str);
return 0;
}
Offline
The first scanf call in your original program reads only the first characters matching the %hd spec. If you type "1asdf" on the first prompt and then hit enter (which puts a newline into stdin, behind the characters), the first scanf reads the "1", stores it in s and returns. The program logic continues til the second scanf called in the '1' case and this one reads all the other characters.
The '%s' directive tells scanf to only read characters, not including spaces and newlines, because scanf considers them to be separators. So scanf does not put the trailing newline in str, wheres fgets does.
Typing '1\n' results in '\n' being in the stream, when fgets would get called. And because fgets reads all characters (max 30) up to and including the first newline, it just stores this newline in str.
So, the best way to have two prompts, without characters inserted at the first one getting read by the second, you should insert something like "while (getchar() != '\n');" into the code before the second scanf/fgets call.
And remember: fgets reads up to 30 characters, including the trailing newline; so the buffer gets a newline at the end only if you type less than 30 characters at the prompt.
It's hard to explain, hope it's a bit more clear now. Also have a look at the fgets/scanf man pages.
Offline
Pages: 1