LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Newbie (https://www.linuxquestions.org/questions/linux-newbie-8/)
-   -   scanf anomaly (https://www.linuxquestions.org/questions/linux-newbie-8/scanf-anomaly-472937/)

barunparichha 08-11-2006 07:58 AM

scanf anomaly
 
Hi friends,
plz go through the code.

#include<stdio.h>
int main() {
char str[30];
char opt='y';

while(opt=='y') {
printf("enter str :");
scanf("%s",str); //u can also use gets(str)
printf(\nstr = %s",str);

printf("\n enter option(y/n) :");
scanf("%s",&opt);
}
}

result :
first time it's takes i/p for str and prints and then leaves the program.

Initially i was thinking a buffer problem and i used "fflush(stdin)" but it bahaved as before. But when i tried two "scanf("%s",str);" consecutively it works fine. I don't know why it's taking some arbitary value of c for the first scanf. Can anyone of u sort out the problem ?

With thanks in advance,
barun

tharg 08-11-2006 08:58 AM

Hi, been a while since I did C.

I'm not sure if this is the right place to ask this type of question, you're probably better off posting here to comp.lang.c

timmeke 08-11-2006 11:01 AM

Quote:

printf(\nstr = %s",str);
Aren't you missing some double quotes here? Or did you copy it wrong in the post?
Also, you should include a '\n' at the end of the print or flush stdout.

exman 08-11-2006 12:08 PM

Hi,
I could not reproduce the problem but it seems that scanf leaves the newline on the input stream. This causes the program to end if u use scanf("%c",&opt) (as it should be used). Furthermore u should make sure u dont read a string longer than the buffer because it causes the programm to segfault.

exman

barunparichha 08-11-2006 11:54 PM

Yes i missed one quote while copying :

#include<stdio.h>

int main() {
char str[30];
char opt='y';

while(opt=='y') {
printf("\nstr ?");
scanf("%s",str);
printf("\nstr= %s\n",str);

printf("\n your opt(y/n) ? ");
scanf("%c",&opt);
}
}

This is my code ..
Yes i know my maximum string length is 30.
I am using Fedora 2.6 and gcc for compilation and have tested it more than two machines.
plz ur help needed.

PingFloyd 08-12-2006 03:07 AM

Here is what I did to get it working.

#include<stdio.h>

int main()
{
char str[30];
char opt='y';

while (opt=='y')
{
printf("enter str: ");
scanf("%s",str);
printf("str=%s\n",str);

printf("enter option(y/n): ");
scanf("%s",&opt);
}
return(0);
}

One thing I noticed, is that it doesn't matter if you hit "n" to quit since anything other than "y" seems to return false.

So I got to thinking of some ideas.

#include<stdio.h>

int main()
{
char str[30];
char opt='y';

while (opt=='y')
{
printf("enter str: ");
scanf("%s",str);
printf("str=%s\n",str);
do {
printf("enter option(y/n): ");
scanf("%s",&opt);

if (opt !='y' && opt !='n') {
printf("invalid option!\n");
}
} while (opt !='y' && opt!='n');

}
printf("goodbye...\n");
return(0);
}

I wonder if there is a better way to accomplish the same as thing but in a more kosher manner. Or was I going about things right way?

I'm not very experienced in C so I learned a little bit by trying to change the way it functions a little.

soggycornflake 08-12-2006 12:59 PM

The code is broken. opt is declared as a char, but you are reading a string into it:

Code:

char opt='y';
Code:

scanf("%s",&opt);
This is wrong, and will causes problems at some point.

Also note that scanf reads exactly what you tell it, and leaves everything else (including the newline, as exman pointed out) on the input stream. Frankly, it is a strange function that is often difficult to use properly. You might try fgets or getline instead, which has overflow protection. See man 3 getline (note that getline is a GNU extension).

Ideally, you'd want to read a single character into opt, but alas, this is not trivial on a unix terminal (you have to use raw mode input, and it's probably too much trouble in this case).

If you use getline, it will read an entire line, but this is no problem, just look at the first character to see if it's y, the rest of the line can be ignored. So, you'd change opt to a char pointer, and pass that to getline,
e.g.

Code:

char *opt = NULL; /* getline will allocate memory and store the pointer in opt */
...
getline(&opt, 1, stdin);

then check if opt[0] == y/n, don't forget to free opt later (not that it's a big deal in this small program but it's good to get into the habit of freeing everything that is allocated).

If you must use scanf, then change it to read in a single char, i.e. scanf("%c", &opt).

PingFloyd 08-12-2006 08:42 PM

Good to know. Thanks for the pointers (pun intended):D .

barunparichha 08-13-2006 11:03 AM

i checked this code if i m using

scnaf("%s",&opt);

it works fine but not for "scanf("%c",&opt);".


U can also use two consecutive scanfs like

scnaf("%s",&opt);
scnaf("%s",&opt);


But still it's not clear what character it's taking in first scanf. and ofcourse how it works for "%s".

With thanks,
barun


All times are GMT -5. The time now is 04:27 AM.