I need help please!

J

Jim

This has got to be really simple but I can't figure it out... I got
swamped with work and am doing this project for a class that I'm
taking and I can't figure out why the output is like this.

I'm taking a Functional Programming in C and I have to write a
shuffling program. The problem is that when I ask the user if they
want to shuffle, they type y or n to answer. It then goes into a
switch statement and executes code. It exits if they type no and is
suppose to keep looping until they say no.

So... Here is the output I'm getting:

-------------
The array holds 20 elements which consists of:
{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
20 }

Would you like to shuffle the array? (y=yes, n=no): y
You have said you would like to shuffle.
Shuffling...

Would you like to shuffle the array? (y=yes, n=no): Would you like to
shuffle the array? (y=yes, n=no):
----------------

Notice that the question is getting asked twice instead of just once
(after it loops). I added a default: line to my switch statement and
it seems to be reading something else in the userval variable but I
can't figure out what I'm doing wrong. Please help... This is due in
4 hours. -- Before anyone flames me, I didn't purposely
procrastinate on this, I work full time, have a family and didn't get
a chance to do this earlier.

Here is my code:
-----------------
#include <math.h>
21 #include <stdio.h>
22 #include <stdbool.h>
23 #include <stdlib.h>
24 #include <math.h>
25 #define SIZE 20
26
27 // function prototypes
28
29
30 // main program
31 int main(void) {
32
33 // declare variables
34 int
35 array1[SIZE]= { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
13, 14, 15, 16, 17, 18, 19, 20 },
36 cnt = 0;
37
38 bool cont = true;
39 char userval;
40
41 // while(cont) {
42 // Display the contents of the array.
43 printf("The array holds %d elements which consists of:
\n { ", SIZE);
44
45 for(cnt = 0; cnt < SIZE; cnt++) {
46 (cnt != SIZE - 1) ? printf("%d, ", array1[cnt]) :
printf("%d ", array1[cnt]);
47 }
48
49 printf("}\n\n");
50
51 while(cont) {
52 // ask if the user woule like to shuffle the contents
of the array
53 printf("Would you like to shuffle the array? (y=yes,
n=no): ");
54 scanf("%c", &userval);
55
56 switch(userval) {
57 case 'y':
58 case 'Y':
59 printf("You have said you would like to
shuffle.\nShuffling...\n\n");
60 break;
61
62 case 'n':
63 case 'N':
64 printf("No shuffling will take place.
\nExiting...\n");
65 cont = false;
66 break;
67 }
68 }
69 }
-----------------
 
S

santosh

Jim said:
This has got to be really simple but I can't figure it out... I got
swamped with work and am doing this project for a class that I'm
taking and I can't figure out why the output is like this.

I'm taking a Functional Programming in C and I have to write a
shuffling program. The problem is that when I ask the user if they
want to shuffle, they type y or n to answer. It then goes into a
switch statement and executes code. It exits if they type no and is
suppose to keep looping until they say no.

So... Here is the output I'm getting:

-------------
The array holds 20 elements which consists of:
{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
20 }

Would you like to shuffle the array? (y=yes, n=no): y
You have said you would like to shuffle.
Shuffling...

Would you like to shuffle the array? (y=yes, n=no): Would you like to
shuffle the array? (y=yes, n=no):
----------------

Notice that the question is getting asked twice instead of just once
(after it loops). I added a default: line to my switch statement and
it seems to be reading something else in the userval variable but I
can't figure out what I'm doing wrong. Please help... This is due in
4 hours. -- Before anyone flames me, I didn't purposely
procrastinate on this, I work full time, have a family and didn't get
a chance to do this earlier.

Here is my code:
-----------------
#include <math.h>
21 #include <stdio.h>
22 #include <stdbool.h>
23 #include <stdlib.h>
24 #include <math.h>
25 #define SIZE 20
26
27 // function prototypes
28
29
30 // main program
31 int main(void) {
32
33 // declare variables
34 int
35 array1[SIZE]= { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
13, 14, 15, 16, 17, 18, 19, 20 },
36 cnt = 0;
37
38 bool cont = true;
39 char userval;
40
41 // while(cont) {
42 // Display the contents of the array.
43 printf("The array holds %d elements which consists of:
\n { ", SIZE);
44
45 for(cnt = 0; cnt < SIZE; cnt++) {
46 (cnt != SIZE - 1) ? printf("%d, ", array1[cnt]) :
printf("%d ", array1[cnt]);
47 }
48
49 printf("}\n\n");
50
51 while(cont) {
52 // ask if the user woule like to shuffle the contents
of the array
53 printf("Would you like to shuffle the array? (y=yes,
n=no): ");
54 scanf("%c", &userval);
55
56 switch(userval) {
57 case 'y':
58 case 'Y':
59 printf("You have said you would like to
shuffle.\nShuffling...\n\n");
60 break;
61
62 case 'n':
63 case 'N':
64 printf("No shuffling will take place.
\nExiting...\n");
65 cont = false;
66 break;
67 }
68 }
69 }
-----------------

This is a problem with your use of scanf. The second time around it
reads the '\n' character (generated by pressing ENTER) left in the
input buffer after reading in the 'y' or 'n' character preceding it.
You need to flush out the excessive characters before calling scanf.
You can do that with a simple loop with fgetc, reading until you
encounter a '\n' character, like say:

void flush_input(void) {
int ch;
while ((ch = fgetc(stdin)) != '\n')
;
return;
}

You should call this after each scanf call above.

But a more robust solution is to drop scanf and use fgets to read in a
whole line and examine that line yourself.
 
W

Willem

Jim wrote:
) This has got to be really simple but I can't figure it out... I got
) swamped with work and am doing this project for a class that I'm
) taking and I can't figure out why the output is like this.
)
) I'm taking a Functional Programming in C and I have to write a
) shuffling program. The problem is that when I ask the user if they
) want to shuffle, they type y or n to answer. It then goes into a
) switch statement and executes code. It exits if they type no and is
) suppose to keep looping until they say no.
)
) So... Here is the output I'm getting:
)
) -------------
) The array holds 20 elements which consists of:
) { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
) 20 }
)
) Would you like to shuffle the array? (y=yes, n=no): y
) You have said you would like to shuffle.
) Shuffling...
)
) Would you like to shuffle the array? (y=yes, n=no): Would you like to
) shuffle the array? (y=yes, n=no):
) ----------------
)
) Notice that the question is getting asked twice instead of just once
) (after it loops). I added a default: line to my switch statement and
) it seems to be reading something else in the userval variable but I
) can't figure out what I'm doing wrong.

My guess is that the 'something else' it is reading is a newline.
Before reading the response, code a loop that discards input characters
until you find a newline.


SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
 
J

Jim

Jim said:
This has got to be really simple but I can't figure it out... I got
swamped with work and am doing this project for a class that I'm
taking and I can't figure out why the output is like this.
I'm taking a Functional Programming in C and I have to write a
shuffling program. The problem is that when I ask the user if they
want to shuffle, they type y or n to answer. It then goes into a
switch statement and executes code. It exits if they type no and is
suppose to keep looping until they say no.
So... Here is the output I'm getting:
Would you like to shuffle the array? (y=yes, n=no): y
You have said you would like to shuffle.
Shuffling...
Would you like to shuffle the array? (y=yes, n=no): Would you like to
shuffle the array? (y=yes, n=no):
----------------
Notice that the question is getting asked twice instead of just once
(after it loops). I added a default: line to my switch statement and
it seems to be reading something else in the userval variable but I
can't figure out what I'm doing wrong. Please help... This is due in
4 hours. -- Before anyone flames me, I didn't purposely
procrastinate on this, I work full time, have a family and didn't get
a chance to do this earlier.
Here is my code:
-----------------
#include <math.h>
21 #include <stdio.h>
22 #include <stdbool.h>
23 #include <stdlib.h>
24 #include <math.h>
25 #define SIZE 20
26
27 // function prototypes
28
29
30 // main program
31 int main(void) {
32
33 // declare variables
34 int
35 array1[SIZE]= { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
13, 14, 15, 16, 17, 18, 19, 20 },
36 cnt = 0;
37
38 bool cont = true;
39 char userval;
40
41 // while(cont) {
42 // Display the contents of the array.
43 printf("The array holds %d elements which consists of:
\n { ", SIZE);
44
45 for(cnt = 0; cnt < SIZE; cnt++) {
46 (cnt != SIZE - 1) ? printf("%d, ", array1[cnt]) :
printf("%d ", array1[cnt]);
47 }
48
49 printf("}\n\n");
50
51 while(cont) {
52 // ask if the user woule like to shuffle the contents
of the array
53 printf("Would you like to shuffle the array? (y=yes,
n=no): ");
54 scanf("%c", &userval);
55
56 switch(userval) {
57 case 'y':
58 case 'Y':
59 printf("You have said you would like to
shuffle.\nShuffling...\n\n");
60 break;
61
62 case 'n':
63 case 'N':
64 printf("No shuffling will take place.
\nExiting...\n");
65 cont = false;
66 break;
67 }
68 }
69 }
-----------------

This is a problem with your use of scanf. The second time around it
reads the '\n' character (generated by pressing ENTER) left in the
input buffer after reading in the 'y' or 'n' character preceding it.
You need to flush out the excessive characters before calling scanf.
You can do that with a simple loop with fgetc, reading until you
encounter a '\n' character, like say:

void flush_input(void) {
int ch;
while ((ch = fgetc(stdin)) != '\n')
;
return;

}

You should call this after each scanf call above.

But a more robust solution is to drop scanf and use fgets to read in a
whole line and examine that line yourself.

thank you so much! I thought that it was the input buffer but I guess
I was handling it wrong. I thought that fflush(stdin) would clear the
buffer.

It works like a charm.
 
S

santosh

Jim wrote:

thank you so much! I thought that it was the input buffer but I guess
I was handling it wrong. I thought that fflush(stdin) would clear the
buffer.

Actually fflush is defined only for output streams and calling fflush on
stdin is totally non-portable, i.e., it might seem to work for your
current compiler, and it might lead to a system crash on the very next
one you try the code on.
It works like a charm.

But it will block if stdin is already at end-of-file and if there are
no '\n' in the input buffer.

For the long term using something like fgets followed by custom parsing
would be much more robust.
 
B

Bartc

[Simple stdin input]
But it will block if stdin is already at end-of-file and if there are
no '\n' in the input buffer.

For the long term using something like fgets followed by custom parsing
would be much more robust.

I was playing with the following code for reading a character at a time, to
do the same sort of thing as the OP.

But fgetc() doesn't return until end-of-line (Enter) is pressed. Is this
normal behaviour?

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
while (1)
{ switch (fgetc(stdin))
{ case 'Y': case 'y':
puts("es");
break;
case 'N': case 'n':
puts("o");
break;
case 'Q': case 'q':
puts("uit");
return EXIT_SUCCESS;
default:
puts("?");
};
};
}
 
B

Bill Reid

This has got to be really simple but I can't figure it out... I got
swamped with work and am doing this project for a class that I'm
taking and I can't figure out why the output is like this.

I'm taking a Functional Programming in C and I have to write a
shuffling program.

Ooooh, there's some "tricks" for that you should know about...but
since you didn't ask...
The problem is that when I ask the user if they
want to shuffle, they type y or n to answer. It then goes into a
switch statement and executes code. It exits if they type no and is
suppose to keep looping until they say no.

Yeah, this is the kind of stuff that will slow an "actual" programmer
(defined as somebody who really just wants to get a program written)
down to a crawl, because you have to incessantly re-invent this
little user input wheel, and about a dozen others...

I got so sick of repeating this stuff endlessly, I stuck them all in
a "library" (have you been taught that term?) so I now can simply
call a robust function with full user input error checking, rather
than watch my programs crash if I "fat-finger" something...but this
would get you tremendous extra credit if you show up with this...
So... Here is the output I'm getting:

-------------
The array holds 20 elements which consists of:
{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
20 }

Would you like to shuffle the array? (y=yes, n=no): y
You have said you would like to shuffle.
Shuffling...

Would you like to shuffle the array? (y=yes, n=no): Would you like to
shuffle the array? (y=yes, n=no):
----------------

Notice that the question is getting asked twice instead of just once
(after it loops). I added a default: line to my switch statement and
it seems to be reading something else in the userval variable but I
can't figure out what I'm doing wrong. Please help... This is due in
4 hours.

OK, I'm late, that's probably for the best, I shouldn't be doing your
homework for you...but here it is anyway!

-- Before anyone flames me, I didn't purposely
procrastinate on this, I work full time, have a family and didn't get
a chance to do this earlier.

Here is my code:

Ah, forget it, here is the library function:

unsigned get_yn_input(const char *question_string,unsigned default_input) {
size_t string_size;

#ifdef __CONSOLE__
printf("%s",question_string);

if(default_input==DEF_YES) printf(" [{y}|n] ");
else if(default_input==DEF_NO) printf(" [y|{n}] ");
else printf(" [y|n] ");

GetInput :

fgets(yn_input,sizeof(yn_input),stdin);

string_size=strlen(yn_input);

if(yn_input[string_size-1]!='\n') {
fflush(stdin);
goto ReTry;
}

if(string_size>2)
goto ReTry;

if(IS_STR_SAME(yn_input,"y\n")) return YES;
else if(IS_STR_SAME(yn_input,"n\n")) return NO;
else if((default_input>NO_DEF)&&(yn_input[0]=='\n')) {
if(default_input==DEF_YES) return YES;
else if(default_input==DEF_NO) return NO;
}

ReTry :

printf("TRY AGAIN, just type 'y' or 'n'");
if(default_input>NO_DEF) printf(" \(or RETURN for default\)");
printf(": ");
goto GetInput;
#endif

#ifdef __WINGUI__
if(MessageDlg(question_string,
mtConfirmation,TMsgDlgButtons()<<mbYes<<mbNo,0)==mrYes)
return YES;
else return NO;
#endif
}

Note that I can actually conditionally compile this into two separate
libraries: one for a "console" (terminal) type application, and another
for a "GUI" (guess which one!) application.

For the "console" application, the code performs all possible error
checking for fat-fingered idiotic input, and keeps prompting the user
until it gets either 'y' or 'n', which it then returns to the calling
function
(YES=1, NO=0, and don't ask about the other macro definitions,
they should be obvious).

For the "GUI" library, I just pop up a "dialog box" with the "question"
that prompts the user to press either the "Yes" or "No" button. The
GUI API does all the heavy lifting (at a heavy code bloat price!).

So if I want a "dual use" code module that I can also compile as
either a "console" or "GUI" application, I can just call the library
function
something like this:

get_yn_input("Would you like to shuffle the array?",DEF_NO)

And if it is a "console" application, the DEF_NO macro define tells
the function to interpret a RETURN without any input as a 'n' response.

So for your shuffling application, you could sort of use it like this:

void shuffle(void) {

PerformShuffle :

<shuffle code here>

if(get_yn_input("Would you like to shuffle the array again?",DEF_NO))
goto PerformShuffle;
}

Once again, the advantage of all this is that once you've got a robust
library function to do this routine crap, you can concentrate on the what
the program is really doing...but if you turned this in, your teacher would
know that you cheated...
 
S

santosh

Bartc said:
[Simple stdin input]
But it will block if stdin is already at end-of-file and if there are
no '\n' in the input buffer.

For the long term using something like fgets followed by custom
parsing would be much more robust.

I was playing with the following code for reading a character at a
time, to do the same sort of thing as the OP.

But fgetc() doesn't return until end-of-line (Enter) is pressed. Is
this normal behaviour?

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
while (1)
{ switch (fgetc(stdin))
{ case 'Y': case 'y':
puts("es");
break;
case 'N': case 'n':
puts("o");
break;
case 'Q': case 'q':
puts("uit");
return EXIT_SUCCESS;
default:
puts("?");
};
};
}

Yes. Because under most systems stdin is line buffered. Even if you turn
of it's buffering using setvbuf you'll still need to supply a
end-of-line since this is done at the OS level. You'll need to use a
more low-level API like <termios.h>. This is of course specific to a
system. Here is a UNIX example to read a single character without
echoing in non-canonical input mode (from glibc docs).

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <termios.h>

/* Use this variable to remember original terminal attributes. */

struct termios saved_attributes;

void
reset_input_mode (void)
{
tcsetattr (STDIN_FILENO, TCSANOW, &saved_attributes);
}
void
set_input_mode (void)
{
struct termios tattr;
char *name;

/* Make sure stdin is a terminal. */
if (!isatty (STDIN_FILENO))
{
fprintf (stderr, "Not a terminal.\n");
exit (EXIT_FAILURE);
}
/* Save the terminal attributes so we can restore them later. */
tcgetattr (STDIN_FILENO, &saved_attributes);
atexit (reset_input_mode);

/* Set the funny terminal modes. */
tcgetattr (STDIN_FILENO, &tattr);
tattr.c_lflag &= ~(ICANON|ECHO); /* Clear ICANON and ECHO. */
tattr.c_cc[VMIN] = 1;
tattr.c_cc[VTIME] = 0;
tcsetattr (STDIN_FILENO, TCSAFLUSH, &tattr);
}
int
main (void)
{
char c;

set_input_mode ();

while (1)
{
read (STDIN_FILENO, &c, 1);
if (c == '\004') /* `C-d' */
break;
else
putchar (c);
}

return EXIT_SUCCESS;
}
 
B

Ben Pfaff

Bartc said:
I was playing with the following code for reading a character at a time, to
do the same sort of thing as the OP.

But fgetc() doesn't return until end-of-line (Enter) is pressed. Is this
normal behaviour?

This topic is covered at some length in the C FAQ:

19.1: How can I read a single character from the keyboard without
waiting for the RETURN key? How can I stop characters from
being echoed on the screen as they're typed?

A: Alas, there is no standard or portable way to do these things in
C. Concepts such as screens and keyboards are not even
mentioned in the Standard, which deals only with simple I/O
"streams" of characters.

At some level, interactive keyboard input is usually collected
and presented to the requesting program a line at a time. This
gives the operating system a chance to support input line
editing (backspace/delete/rubout, etc.) in a consistent way,
without requiring that it be built into every program. Only
when the user is satisfied and presses the RETURN key (or
equivalent) is the line made available to the calling program.
Even if the calling program appears to be reading input a
character at a time (with getchar() or the like), the first call
blocks until the user has typed an entire line, at which point
potentially many characters become available and many character
requests (e.g. getchar() calls) are satisfied in quick
succession.

When a program wants to read each character immediately as it
arrives, its course of action will depend on where in the input
stream the line collection is happening and how it can be
disabled. Under some systems (e.g. MS-DOS, VMS in some modes),
a program can use a different or modified set of OS-level input
calls to bypass line-at-a-time input processing. Under other
systems (e.g. Unix, VMS in other modes), the part of the
operating system responsible for serial input (often called the
"terminal driver") must be placed in a mode which turns off line-
at-a-time processing, after which all calls to the usual input
routines (e.g. read(), getchar(), etc.) will return characters
immediately. Finally, a few systems (particularly older, batch-
oriented mainframes) perform input processing in peripheral
processors which cannot be told to do anything other than line-
at-a-time input.

Therefore, when you need to do character-at-a-time input (or
disable keyboard echo, which is an analogous problem), you will
have to use a technique specific to the system you're using,
assuming it provides one. Since comp.lang.c is oriented towards
those topics that the C language has defined support for, you
will usually get better answers to other questions by referring
to a system-specific newsgroup such as comp.unix.questions or
comp.os.msdos.programmer, and to the FAQ lists for these groups.
Note that the answers are often not unique even across different
variants of a system; bear in mind when answering system-
specific questions that the answer that applies to your system
may not apply to everyone else's.

However, since these questions are frequently asked here, here
are brief answers for some common situations.

Some versions of curses have functions called cbreak(),
noecho(), and getch() which do what you want. If you're
specifically trying to read a short password without echo, you
might try getpass(). Under Unix, you can use ioctl() to play
with the terminal driver modes (CBREAK or RAW under "classic"
versions; ICANON, c_cc[VMIN] and c_cc[VTIME] under System V or
POSIX systems; ECHO under all versions), or in a pinch, system()
and the stty command. (For more information, see <sgtty.h> and
tty(4) under classic versions, <termio.h> and termio(4) under
System V, or <termios.h> and termios(4) under POSIX.) Under
MS-DOS, use getch() or getche(), or the corresponding BIOS
interrupts. Under VMS, try the Screen Management (SMG$)
routines, or curses, or issue low-level $QIO's with the
IO$_READVBLK function code (and perhaps IO$M_NOECHO, and others)
to ask for one character at a time. (It's also possible to set
character-at-a-time or "pass through" modes in the VMS terminal
driver.) Under other operating systems, you're on your own.

(As an aside, note that simply using setbuf() or setvbuf() to
set stdin to unbuffered will *not* generally serve to allow
character-at-a-time input.)

If you're trying to write a portable program, a good approach is
to define your own suite of three functions to (1) set the
terminal driver or input system into character-at-a-time mode
(if necessary), (2) get characters, and (3) return the terminal
driver to its initial state when the program is finished.
(Ideally, such a set of functions might be part of the C
Standard, some day.) The extended versions of this FAQ list
(see question 20.40) contain examples of such functions for
several popular systems.

See also question 19.2.

References: PCS Sec. 10 pp. 128-9, Sec. 10.1 pp. 130-1; POSIX
Sec. 7.

19.2: How can I find out if there are characters available for reading
(and if so, how many)? Alternatively, how can I do a read that
will not block if there are no characters available?

A: These, too, are entirely operating-system-specific. Some
versions of curses have a nodelay() function. Depending on your
system, you may also be able to use "nonblocking I/O", or a
system call named "select" or "poll", or the FIONREAD ioctl, or
c_cc[VTIME], or kbhit(), or rdchk(), or the O_NDELAY option to
open() or fcntl(). See also question 19.1.
 
R

Richard Heathfield

Bill Reid said:
I shouldn't be doing your homework for you...

Right. Quite apart from the morality issue (and I haven't read the OP
closely enough to determine whether that /is/ an issue in this case)...
fgets(yn_input,sizeof(yn_input),stdin);

....this reply fails to check the result of a function that is very likely
under some circumstances to fail. What's more, it attempts to populate a
non-existent array...

fflush(stdin);

....and this demonstrates that the author either doesn't know what fflush
does or doesn't know the difference between a stream open for output or
update and a stream open for input.

I can't help wondering whether, when the author of this code was at
college, someone else did /his/ homework.
 
B

Bill Reid

BWHAHAHAHAHAHAHAHAHA!!!!

And to think, I came this close to complimenting you on your helpful,
knowledgeable, and correct answer to to the question about "Calling
external function in C"...the exception that proves the rule, I reckon, and
certainly a RARE event...

Richard Heathfield said:
Bill Reid said:


Right. Quite apart from the morality issue (and I haven't read the OP
closely enough to determine whether that /is/ an issue in this case)...
It was...
...this reply fails to check the result of a function that is very likely
under some circumstances to fail.

OK, I like the wording "very likely under some circumstances"...are
THESE the circumstances (reading from the standard input) where
fgets() is "very likely" to fail? Awaiting your response...but yeah, I
acknowledge it COULD fail, possibly, maybe, and possibly maybe
I could make the library function even more "robust" in some way...any
PRACTICAL HELPFUL suggestions?...awaiting your response...
What's more, it attempts to populate a
non-existent array...

Nahhh, it exists, just not locally...sorry about that, cheif, just did it
to irritate you...I also acknowleged there's a whole bunch of stuff that
you have to assume exists, but you must have missed that part of
my post since it was in plain simple English...
...and this demonstrates that the author either doesn't know what fflush
does or doesn't know the difference between a stream open for output or
update and a stream open for input.

My compiler "does the right thing" for fflush(stdin) so I use it...sorry
about that, cheif, just did it to irritate you...oh wait, I just did it
(originally)
because IT WORKS AND I DON'T HAVE TO RE-INVENT THE WHEEL
TO SOLVE A PROBLEM THAT ONLY EXISTS ON THIS NEWSGROUP
AND NOT IN "REAL LIFE"...

But OK, we can replace the above with a call to another function
called "clear_input()" or something that, depending on the compiler,
either calls fflush(stdin) (I guess the waste of the calling overhead
can be ignored due to the inherent "user wait" involved in what
we're doing) or a routine to chew up all the garbage characters
in the standard input...WOULD THAT MAKE YOU HAPPY, YOU
INSUFFERABLE TROLL??!!!?!!

Or is the existence of working, practical computer code on the
face of this planet (hate to tell you this, it's out there, not in great
quantities compared to the number of "programmers" like you, but
it exists) such a threat to you that you will spend the rest of your
miserable life in a blue funk?
I can't help wondering whether, when the author of this code was at
college, someone else did /his/ homework.

Well, I didn't take any computer science classes (the closest I got
was Boolean algebra and sentential logic), but actually I occasionally
did OTHER people's homework if the price was right...it was "morally"
wrong, I know, but even worse, I keep running into the same TYPE
of people now (idiotic cheaters) and they make a LOT more money
than I do and are highly-ranked "respected" business "leaders", which,
"morality" aside, I guess just proves something about people in general,
it's up to the reader to decide what...
 
S

santosh

Bill Reid wrote:

[ ... ]

[ ... ]
...this reply fails to check the result of a function that is very
likely under some circumstances to fail.

OK, I like the wording "very likely under some circumstances"...are
THESE the circumstances (reading from the standard input) where
fgets() is "very likely" to fail? [ ... ]

It can fail when the operator sends the end-of-file sequence (CONTROL-D
for UNIX, CONTROL-Z for Windows/DOS/CP-M). Surely you want to handle
this?
My compiler "does the right thing" for fflush(stdin) so I use
it...
Or is the existence of working, practical computer code on the
face of this planet (hate to tell you this, it's out there, not in
great quantities compared to the number of "programmers" like you, but
it exists) such a threat to you that you will spend the rest of your
miserable life in a blue funk?

But you should at least have mentioned to the OP that fflush(stdin) is
not portable. Subtly misleading advice is sometimes worse than an
outright wrong one.

<snip>
 
B

Bill Reid

santosh said:
Bill Reid wrote:

[ ... ]

[ ... ]
fgets(yn_input,sizeof(yn_input),stdin);

...this reply fails to check the result of a function that is very
likely under some circumstances to fail.

OK, I like the wording "very likely under some circumstances"...are
THESE the circumstances (reading from the standard input) where
fgets() is "very likely" to fail? [ ... ]

It can fail when the operator sends the end-of-file sequence (CONTROL-D
for UNIX, CONTROL-Z for Windows/DOS/CP-M). Surely you want to handle
this?

Thanks for proving my point, although "troll zero"'s non-response
also serves the same purpose.

No, handling THAT is not high on my list of priorities, because obviously
it is highly UNLIKELY that a user, after being prompted to press either
'y' or 'n' is going to simultaneously press CTRL and 'd' or 'z'. We COULD
test the probability of that happening empirally by placing cats on
keyboards,
and record how many hundreds of cats over how many thousands of
years it takes to get a statistically significant number of failures.

But I guess in the history of the universe it will happen a few times,
so if I acquire several hundred cats crammed into my home office that
I allow to walk over my keyboard after I have started one of my programs
apparently only for the purpose of allowing cats to crash it, I will be sure
to check the return value of fgets() and handle it "appropriately"...
But you should at least have mentioned to the OP that fflush(stdin) is
not portable. Subtly misleading advice is sometimes worse than an
outright wrong one.

I said that I assumed that the OP is long gone, since I posted well
AFTER his four-hour window of opportunity for getting somebody to
do his homework for him. The remaining audience for the post then
largely consists of people who a) know that call is "non-portable" and
b) know that MANY compilers on MANY systems provide it but
c) never tire of the "fun" of pointing out it is "non-portable" in insulting
and abusive language despite the fact just about everybody reading
the post knows the exact status of the call.
 
S

santosh

Bill said:
santosh said:
Bill Reid wrote:

[ ... ]
Bill Reid said:

[ ... ]
fgets(yn_input,sizeof(yn_input),stdin);

...this reply fails to check the result of a function that is very
likely under some circumstances to fail.

OK, I like the wording "very likely under some circumstances"...are
THESE the circumstances (reading from the standard input) where
fgets() is "very likely" to fail? [ ... ]

It can fail when the operator sends the end-of-file sequence
(CONTROL-D for UNIX, CONTROL-Z for Windows/DOS/CP-M). Surely you want
to handle this?

Thanks for proving my point, although "troll zero"'s non-response
also serves the same purpose.

No, handling THAT is not high on my list of priorities, because
obviously it is highly UNLIKELY that a user, after being prompted to
press either 'y' or 'n' is going to simultaneously press CTRL and 'd'
or 'z'. We COULD test the probability of that happening empirally by
placing cats on keyboards, and record how many hundreds of cats over
how many thousands of years it takes to get a statistically
significant number of failures.

A library routine must try to deal sensibly with all reasonable
possibilities. CTRL-D is often used to signal end of input, or as a
wish to exit from the program. That is another option that you should
try to present, wherever it makes sense: allowing a user to exit the
application without having to kill it with CTRL-C or 'kill'.

<snip>

Regarding the fflush(stdin) call in your code, you might have considered
mentioning it's non-portability for the benefit of other newbies that
might be lurking, not just for the OP. It's used too often everywhere,
without people knowing that it invokes undefined behaviour on anything
other than output streams and update streams where the most recent
operation was output. You also fail to check for the possibility of
fflush failing.
 
F

Flash Gordon

Bill Reid wrote, On 08/03/08 19:15:

OK, I like the wording "very likely under some circumstances"...are
THESE the circumstances (reading from the standard input) where
fgets() is "very likely" to fail? Awaiting your response...but yeah, I
acknowledge it COULD fail, possibly, maybe, and possibly maybe
I could make the library function even more "robust" in some way...any
PRACTICAL HELPFUL suggestions?...awaiting your response...

I sometimes forget which OS I'm using and press ctrl-z to try and
gracefully exit from a program, on some systems that would generate a
failure. I am a user as well as a programming by the way.

My compiler "does the right thing" for fflush(stdin) so I use it...sorry
about that, cheif, just did it to irritate you...oh wait, I just did it
(originally)
because IT WORKS AND I DON'T HAVE TO RE-INVENT THE WHEEL
TO SOLVE A PROBLEM THAT ONLY EXISTS ON THIS NEWSGROUP
AND NOT IN "REAL LIFE"...

It does not work on the machine I'm currently using. I know because I
just tested it. So it DOES NOT ALWAYS WORK IN REAL LIFE.

in the standard input...WOULD THAT MAKE YOU HAPPY, YOU
INSUFFERABLE TROLL??!!!?!!

So people who point out your mistakes are trolls. Hmm.
 
C

CBFalconer

Bill said:
.... snip ...

I said that I assumed that the OP is long gone, since I posted well
AFTER his four-hour window of opportunity for getting somebody to
do his homework for him. The remaining audience for the post then
largely consists of people who a) know that call is "non-portable"
and b) know that MANY compilers on MANY systems provide it but
c) never tire of the "fun" of pointing out it is "non-portable" in
insulting and abusive language despite the fact just about everybody
reading the post knows the exact status of the call.

No, the majority of educated users in this group KNOW that some
things are not guaranteed by the C standard, and thus should be
avoided. They find that the simple action of using the library and
language correctly ensures the portability of their code. They are
extremely lazy, and do not eagerly anticipate rewriting all their
code at every port.

You are lucky enough to get their analysis without charge. If you
choose to ignore it, that's your loss. But insulting those helpful
and knowledgeable people tends to get you ignored.
 
C

CBFalconer

Flash said:
Bill Reid wrote, On 08/03/08 19:15:
.... snip ...


It does not work on the machine I'm currently using. I know
because I just tested it. So it DOES NOT ALWAYS WORK IN REAL LIFE.



So people who point out your mistakes are trolls. Hmm.

I think 'Bill Reid' just earned a PLONK.
 
B

Bill Reid

Flash Gordon said:
Bill Reid wrote, On 08/03/08 19:15:



I sometimes forget which OS I'm using and press ctrl-z to try and
gracefully exit from a program, on some systems that would generate a
failure. I am a user as well as a programming by the way.

OK, THINK REAL HARD...I know this might be tough, but try...

YOU WANT TO "TRY" TO "GRACEFULLY" QUIT THE
PROGRAM BY PRESSING AN UNDOCUMENTED KEY
COMBINATION ABSENT-MINDEDLY, BUT YOU'RE WORRIED
ABOUT FAILURE TO GET A 'y' OR 'n' INPUT?

DOES THAT MAKE ANY SENSE? How about your untimely
death at the keyboard with your cheek hitting CTRL and your nose
hitting 'z'?

You know what else I haven't stupidly allowed for...you suddenly
decide you are giving up on modern technology when confronted
with a 'y' or 'n' input prompt, so you take a sledgehammer to your
computer and smash it to bits!!! WHAT HAPPENS IF I DON'T
CHECK THE RETURN VALUE OF fgets() IN THAT "VERY LIKELY
UNDER CERTAIN CIRCUMSTANCES" SITUATION!!??!!

You're right, there's so much I haven't taken into account...giant
asteroids, the return of disco music, electromagnetic pulses sending
the keyboard into a parallel universe...HEP ME LEST I CODE AGAIN!!!
It does not work on the machine I'm currently using. I know because I
just tested it. So it DOES NOT ALWAYS WORK IN REAL LIFE.

Next time you MIGHT try just reading the documentation (I know, that
doesn't ALWAYS work, but it's still the REASONABLE man's method
of discovering information about a system)...beats hitting the "any" key
to "test" stuff, anyway...
So people who point out your mistakes are trolls. Hmm.

No, "snippy", people who use uncalled-for abusive and insulting
language to harass people who post well-meaning information are
trolls, but you "snipped" out the troll's nastiness for reasons known
only to you...CONSTRUCTIVE criticism is ALWAYS welcome, but
please try to keep your disappointment down to a dull roar if I merely
point out that I've previously considered the point you've made and
rejected it on purely practical grounds for my purposes...

Simple enough?
 
B

Bill Reid

santosh said:
Bill said:
santosh said:
Bill Reid wrote:

[ ... ]

Bill Reid said:

[ ... ]

fgets(yn_input,sizeof(yn_input),stdin);

...this reply fails to check the result of a function that is very
likely under some circumstances to fail.

OK, I like the wording "very likely under some circumstances"...are
THESE the circumstances (reading from the standard input) where
fgets() is "very likely" to fail? [ ... ]

It can fail when the operator sends the end-of-file sequence
(CONTROL-D for UNIX, CONTROL-Z for Windows/DOS/CP-M). Surely you want
to handle this?

Thanks for proving my point, although "troll zero"'s non-response
also serves the same purpose.

No, handling THAT is not high on my list of priorities, because
obviously it is highly UNLIKELY that a user, after being prompted to
press either 'y' or 'n' is going to simultaneously press CTRL and 'd'
or 'z'. We COULD test the probability of that happening empirally by
placing cats on keyboards, and record how many hundreds of cats over
how many thousands of years it takes to get a statistically
significant number of failures.

A library routine must try to deal sensibly with all reasonable
possibilities. CTRL-D is often used to signal end of input, or as a
wish to exit from the program. That is another option that you should
try to present, wherever it makes sense: allowing a user to exit the
application without having to kill it with CTRL-C or 'kill'.

Well, my "user" is me, and me alone, as I've said many times, and
I know exactly how and when to exit the application (as a matter of
fact, generally you are offered the option to "abort" in all menus,
which is usually a RETURN default that bumps you back to a previous
level menu, so press RETURN about three or four times tops and you're
done)...so MY library deals with all MY reasonable possibilities, so
it's "golden" by your "standard"...

In short, the routine works for ME...for others, a few tweaks may be in
order...
<snip>

Regarding the fflush(stdin) call in your code, you might have considered
mentioning it's non-portability for the benefit of other newbies that
might be lurking, not just for the OP. It's used too often everywhere,
without people knowing that it invokes undefined behaviour

I suspect that in many cases, people use it simply because it's
DOCUMENTED in their compiler documentation, but OK, in the past
when I've shown code with fflush(stdin) I've mentioned it was
"non-portable", but in this case I SPECIFICALLY said I wasn't going
to exhaustively "mention" all the OTHER "non-portabilities" in the
code, I just wanted to freakin' cut'n'paste it and let it go, BUT NOOOOO,
that can't happen HERE...
on anything
other than output streams and update streams where the most recent
operation was output. You also fail to check for the possibility of
fflush failing.

OK, I give up, now I forgot to check the return value of fflush(whatever),
but you know what? The code is there, it has a goal, it could be made
even "better", have at it and re-post it when it's perfect...but then we
ALL know some prig will get all freaked-out by the "goto"s or something
else AND IT NEVER ENDS DOES IT?!!??!!

Of course, for me it also never ends as well, but I'm willing to let
stuff go when it's "good enough" in the interest of just GETTING
SOME STUFF DONE, which I stated as the goal of the whole thing
in the first place...here I am, making all these mistakes, and yet
I'm churning out great gobs of useful program functionality with
automatically-generated dual interfaces without worrying about
writing menus and prompts and dialog boxes and stupid crap like
that, so I'm happy, why can't you be happy for me?
 
I

Ian Collins

Bill said:
My compiler "does the right thing" for fflush(stdin) so I use it...sorry
about that, cheif, just did it to irritate you...oh wait, I just did it
(originally)
because IT WORKS AND I DON'T HAVE TO RE-INVENT THE WHEEL
TO SOLVE A PROBLEM THAT ONLY EXISTS ON THIS NEWSGROUP
AND NOT IN "REAL LIFE"...
The compiler has little to do with it, it works with any compiler on a
platform where the operation is defined and fails with any platform
where its isn't.

Such platform specific code is pretty common (I know I've used
fflush(stdin) on Solaris), but is should be noted, or even conditionally
compiled as a hint for maintainers. The maintainer might be you
porting your own code to a new platform.
 

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

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top