getc/fgets

R

Richard Weeks

Below is a fragment from a program that calculates statistics on
x,y data. I want the user to be able to predict one or more
predicted values of y from x, given the line of best fit. I have
a procedural problem.


predict:
printf("\npredict y? (y/n): ");
if((getc(stdin)=='n')) exit(EXIT_SUCCESS);
//if((fgets(response, 1, stdin)=="n")) exit(EXIT_SUCCESS);
else
{
printf("\nenter x: ");
scanf("%lf", &xdatum);
printf("\ny = %f\n", y_int + (slope * xdatum));
fflush(stdin);
goto predict;
}

It works fine using getc, but when I use fgets execution jumps
directly into the else{} block and prompts for x without waiting
for user response to the y/n prompt. What am I doing wrong?

Richard
 
S

santosh

Richard said:
Below is a fragment from a program that calculates statistics on
x,y data. I want the user to be able to predict one or more
predicted values of y from x, given the line of best fit. I have
a procedural problem.


predict:
printf("\npredict y? (y/n): ");

Unless output is terminated with a newline, it might appear immediately on
the screen.
if((getc(stdin)=='n')) exit(EXIT_SUCCESS);

getc can return EOF on end-of-file or error. EOF is not a valid character
value. You must test for EOF and *then* test against 'n' and 'N'.
//if((fgets(response, 1, stdin)=="n")) exit(EXIT_SUCCESS);

This is not correct usage of the fgets function. fgets returns a char *
value that is NULL if end-of-file or error has occurred. Otherwise it's
equal to fgets's first argument, which has to be an char array. The second
argument specifies the length of this array. The third argument is the
stream to read from.

See man 3 fgets on a UNIX system, or library documentation.
else
{
printf("\nenter x: ");
scanf("%lf", &xdatum);
printf("\ny = %f\n", y_int + (slope * xdatum));
fflush(stdin);

fflush is not defined for input streams like stdin.
goto predict;
}

It works fine using getc, but when I use fgets execution jumps
directly into the else{} block and prompts for x without waiting
for user response to the y/n prompt. What am I doing wrong?

You're not using the Standard library functions correctly.
Besides the library documentation see;
http://www.c-faq.com/
 
S

santosh

santosh said:
Unless output is terminated with a newline, it might appear immediately on
the screen.

That should read;

.... might *not* appear immediately on the screen.

An alternative is to use fflush(stdout) just after the printf.
 
O

Old Wolf

//if((fgets(response, 1, stdin)=="n")) exit(EXIT_SUCCESS);

It works fine using getc, but when I use fgets execution jumps
directly into the else{} block and prompts for x without waiting
for user response to the y/n prompt. What am I doing wrong?
From the C standard (ISO/IEC 9899:1999 7.19.7.2):
[#2] The fgets function reads at most one less than the
number of characters specified by n from the stream pointed
to by stream into the array pointed to by s.

My guess is that since you specified n=1, fgets
determines that it needs to read at most 0
characters. Since doing nothing is the same
as reading 0 characters, it does nothing.

Also, as santosh pointed out, your method of
checking the result is not correct.
 
K

Keith Thompson

Richard Weeks said:
Below is a fragment from a program that calculates statistics on x,y
data. I want the user to be able to predict one or more predicted
values of y from x, given the line of best fit. I have a procedural
problem.


predict:
printf("\npredict y? (y/n): ");

Why do you print a newline at the beginning of the prompt? If you
just want a blank line above the prompt, that's fine; if you think
it's required, it isn't.

You should add 'fflush(stdout);' here to ensure that your prompt
appears. It may not be necessary on most systems, but stdout could be
line-buffered.
if((getc(stdin)=='n')) exit(EXIT_SUCCESS);
//if((fgets(response, 1, stdin)=="n")) exit(EXIT_SUCCESS);

You can't use the "==" operator to compare strings, at least not
meaningfully.

Take a look at the definition of fgets from the standard:

The fgets function reads at most one less than the number of
characters specified by n from the stream pointed to by stream
into the array pointed to by s.

Your fgets call reads at most zero characters.
else
{
printf("\nenter x: ");

Again, 'fflush(stdout);'.
scanf("%lf", &xdatum);
printf("\ny = %f\n", y_int + (slope * xdatum));
fflush(stdin);

Just what do you think 'fflush(stdin);' is going to do?

It invokes undefined behavior.
goto predict;

Style point: this would be better written as a loop.
[snip]

The comp.lang.c FAQ is at <http://www.c-faq.com/>. Please read it.
 
J

Justin Spahr-Summers

It works fine using getc, but when I use fgets execution jumps
directly into the else{} block and prompts for x without waiting
for user response to the y/n prompt. What am I doing wrong?

All previously mentioned points aside, I have to wonder: why do you
want to use fgets() when all you're doing at that point is reading one
character anyways?
 
R

Richard Weeks

Justin said:
All previously mentioned points aside, I have to wonder: why do you
want to use fgets() when all you're doing at that point is reading one
character anyways?

Because anybody learning C gets this drummed into his head again
and again: NEVER EVER UNDER ANY CIRCUMSTANCES USE GETC. :)

Richard
 
S

santosh

Richard said:
Because anybody learning C gets this drummed into his head again
and again: NEVER EVER UNDER ANY CIRCUMSTANCES USE GETC. :)

No. The objection is with gets, not getc. fgets is a recommended alternative
for gets.
 
R

Richard Weeks

santosh said:
Richard Weeks wrote:




No. The objection is with gets, not getc. fgets is a recommended alternative
for gets.

Thanks to you and the others for pointing out several silly
mistakes which, hopefully, I will now be able to avoid.

Richard

PS- I got my program to work using a different approach.
 
C

CBFalconer

Richard said:
Justin Spahr-Summers wrote:
.... snip ...


Because anybody learning C gets this drummed into his head again
and again: NEVER EVER UNDER ANY CIRCUMSTANCES USE GETC. :)

Where did you ever acquire such a ridiculous idea? You may be
thinking of gets(). getc() has many advantages.
 
A

Army1987

Richard Weeks wrote: [snip]
if((getc(stdin)=='n')) exit(EXIT_SUCCESS);

getc can return EOF on end-of-file or error. EOF is not a valid character
value. You must test for EOF and *then* test against 'n' and 'N'.
What the hell? If getc(stdin) return EOF, the program will do
exactly the same thing as if it returned '\n', ' ', or anything
else other than 'n'.
A better thing to do would be islower(getchar()) != 'y', so the
default would be "no".
But (k = getc(stdin)) != EOF && k == 'n' will always do the exact
same thing as getc(stdin) == 'n', except that it needs an
otherwise useless temporary variable.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top