468,514 Members | 1,570 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 468,514 developers. It's quick & easy.

help needed please!

Hi guys!

Task 1: Write a program which presents a menu with 5 options. The 5th
option quits
the program. Each option should execute a system command using system().

Below is my humble offering.
================================================== =
#include <stdio.h>
#include <stdlib.h>

int menu( void );

int main( void )
{
int option;

while(1) {
option = menu();
switch(option) {
case 1:
system("dir");
break;
case 2:
system("help");
break;
case 3:
system("time");
break;
case 4:
system("type menu.c");
break;
case 5:
puts("Quitting program");
exit(0);
default:
puts("Not a valid option, try again");
}
}
return 0;
}

int menu( void )
{
int option;

puts("1. List directory");
puts("2. help");
puts("3. time");
puts("4. type menu.c");
puts("5. Quit");
scanf("%d", &option);

return option;
}
================================================== ========
Problem: My compiler is giving me an "unreachable code" warning for line
32(return 0;). The
program runs fine. Why does the compiler(Borland C++ Builder 6) give this
warning?

Task 2: Create a calculator program.

Below is my humble offering.
================================================== =================
#include <stdio.h>

void add(int a, int b);
void subtract(int a, int b);
void multiply(int a, int b);
void divide(int a, int b);

int main( void )
{
int a, b;
char c;

puts("Enter an integer");
scanf("%d", &a);
puts("Enter an operator");
scanf("%c", &c);
puts("Enter another integer");
scanf("%d", &b);
switch( c ) {
case '*':
multiply(a, b);
break;
case '+':
add(a, b);
break;
case '-':
subtract(a, b);
break;
case '/':
divide(a, b);
break;
default:
puts("Operator is not valid");
}
return 0;
}

void add(int a, int b)
{
printf("Sum is: %d", a+b);
}

void subtract(int a, int b)
{
printf("Answer is: %d", a-b);
}

void multiply(int a, int b)
{
printf("Product is: %d", a*b);
}

void divide(int a, int b)
{
printf("Answer is: %d", a/b);
}
================================================== ===
Output:

Enter an integer
2
Enter an operator
Enter another integer

Problem: Why does the program not allow the user to input the operator
before
jumping straight to "Enter another integer"? I think I am missing
something very
fundamental here.

Thanks in advance guys! Love your work!

Buck
--
Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
Nov 14 '05 #1
15 2531
# while(1) {
# option = menu();
# switch(option) {
# }
# }
# return 0;

# Problem: My compiler is giving me an "unreachable code" warning for line
# 32(return 0;). The
# program runs fine. Why does the compiler(Borland C++ Builder 6) give this
# warning?

Because it's true? The while condition is always true, and loop is devoid
of breaks or gotos out of loop. The only one to exit the loop is to exit
the program; whether it loops forever or exits the program, no code after
the loop can be reached and executed.

--
Derk Gwen http://derkgwen.250free.com/html/index.html
So basically, you just trace.
Nov 14 '05 #2
nrk
Buck Rogers wrote:
Hi guys!

Task 1: Write a program which presents a menu with 5 options. The 5th
option quits
the program. Each option should execute a system command using system().

Below is my humble offering.
================================================== =
#include <stdio.h>
#include <stdlib.h>

int menu( void );

int main( void )
{
int option;

while(1) {
option = menu();
switch(option) {
case 1:
system("dir");
break;
case 2:
system("help");
break;
case 3:
system("time");
break;
case 4:
system("type menu.c");
break;
case 5:
puts("Quitting program");
exit(0);
default:
puts("Not a valid option, try again");
}
}
return 0;
}

int menu( void )
{
int option;

puts("1. List directory");
puts("2. help");
puts("3. time");
puts("4. type menu.c");
puts("5. Quit");
scanf("%d", &option);

return option;
}
================================================== ========
Problem: My compiler is giving me an "unreachable code" warning for line
32(return 0;). The
program runs fine. Why does the compiler(Borland C++ Builder 6) give this
warning?

The only way out of your while ( 1 ) loop is through the exit(0) call, and
that doesn't bring you to the return 0; statement either. Hence the
complaint. Ideally, you should be able to replace the exit(0) call with
return 0; get rid of the existing return statements and the compiler should
be happy.
Task 2: Create a calculator program.

Below is my humble offering.
================================================== =================
#include <stdio.h>

void add(int a, int b);
void subtract(int a, int b);
void multiply(int a, int b);
void divide(int a, int b);

int main( void )
{
int a, b;
char c;

puts("Enter an integer");
scanf("%d", &a);
Read the fine FAQ. Specifically Q12.18:
http://www.eskimo.com/~scs/C-faq/q12.18.html

One fix is:
int ret;
/* read an int and discard rest of line */
ret = scanf("%d%*[^\n]", &a);
if ( ret < 1 ) {
/* ret == 0 => invalid input */
/* ret == EOF => end of input or error */
/* handle appropriately */
}
/* read and discard newline */
if ( !feof(stdin) ) getchar();
puts("Enter an operator");
scanf("%c", &c);
Similar problem as above. Similar fix can be applied.
puts("Enter another integer");
scanf("%d", &b);
switch( c ) {
case '*':
multiply(a, b);
break;
case '+':
add(a, b);
break;
case '-':
subtract(a, b);
break;
case '/':
divide(a, b);
break;
default:
puts("Operator is not valid");
}
return 0;
}

void add(int a, int b)
{
printf("Sum is: %d", a+b);
}

void subtract(int a, int b)
{
printf("Answer is: %d", a-b);
}

void multiply(int a, int b)
{
printf("Product is: %d", a*b);
}

void divide(int a, int b)
{
printf("Answer is: %d", a/b);
}
================================================== ===
Output:

Enter an integer
2
Enter an operator
Enter another integer

Problem: Why does the program not allow the user to input the operator
before
jumping straight to "Enter another integer"? I think I am missing
something very
fundamental here.

What you're missing is knowledge of how scanf works. A trip to the scanf
pages in your C book could come in handy.

-nrk.
Thanks in advance guys! Love your work!

Buck


--
Remove devnull for email
Nov 14 '05 #3


Buck Rogers wrote:
Hi guys!

Task 1: Write a program which presents a menu with 5 options. The 5th
option quits
the program. Each option should execute a system command using system().

Below is my humble offering.
================================================== =
#include <stdio.h>
#include <stdlib.h>

int menu( void );

int main( void )
{
int option;

while(1) {
option = menu();
switch(option) {
case 1:
system("dir");
break;
case 2:
system("help");
break;
case 3:
system("time");
break;
case 4:
system("type menu.c");
break;
case 5:
puts("Quitting program");
exit(0);
default:
puts("Not a valid option, try again");
}
}
return 0;
}

int menu( void )
{
int option;

puts("1. List directory");
puts("2. help");
puts("3. time");
puts("4. type menu.c");
puts("5. Quit");
scanf("%d", &option);

return option;
}
================================================== ========
Problem: My compiler is giving me an "unreachable code" warning for line
32(return 0;). The
program runs fine. Why does the compiler(Borland C++ Builder 6) give
this warning?

It gives the warning because the expression is unreachable. You can
simply ignore the warning or you change the logic. One way would be
change the while loop into a do-while loop.

#include <stdio.h>

int menu( void );

int main( void )
{
int option;

do {
option = menu();
switch(option) {
case 1:
system("dir");
break;
case 2:
system("help");
break;
case 3:
system("time");
break;
case 4:
system("type menu.c");
break;
case 5:
puts("Quitting program");
break;

default:
puts("Not a valid option, try again");
}
}while(option != 5);
return 0;
}

int menu( void )
{
int option;

puts("1. List directory");
puts("2. help");
puts("3. time");
puts("4. type menu.c");
puts("5. Quit");
scanf("%d", &option);

return option;
}


Task 2: Create a calculator program.

Below is my humble offering.
================================================== =================
#include <stdio.h>

void add(int a, int b);
void subtract(int a, int b);
void multiply(int a, int b);
void divide(int a, int b);

int main( void )
{
int a, b;
char c;

puts("Enter an integer");
scanf("%d", &a);
Add here:
getchar();
puts("Enter an operator");
scanf("%c", &c);
puts("Enter another integer");
scanf("%d", &b);
switch( c ) {
case '*':
multiply(a, b);
break;
case '+':
add(a, b);
break;
case '-':
subtract(a, b);
break;
case '/':
divide(a, b);
break;
default:
puts("Operator is not valid");
}
return 0;
}

void add(int a, int b)
{
printf("Sum is: %d", a+b);
printf("Sum is: %d\n", a+b);
}

void subtract(int a, int b)
{
printf("Answer is: %d", a-b);
printf("Answer is: %d\n", a-b); }

void multiply(int a, int b)
{
printf("Product is: %d", a*b);
printf("Product is: %d\n", a*b); }

void divide(int a, int b)
{
printf("Answer is: %d", a/b);
printf("Answer is: %d\n", a/b); }
================================================== ===
Output:

Enter an integer
2
Enter an operator
Enter another integer

Problem: Why does the program not allow the user to input the operator
before
jumping straight to "Enter another integer"? I think I am missing
something very
fundamental here.


When you enter the first number, your input includes the digits for
the number and the newline char, '\n', because you preesed the
enter key. In the first scanf statement, the %d specifier will
stop reading the input buffer when it incounters the '\n' character.
This character remains in the input buffer. In the next scanf
statement you are using the %c specifier. This specifier will not
remove leading whitespace, so the value of the newline char is
read into variable c. The operator,*,/,+ or -, and a newline character
remain in the input buffer. Your next scanf statement, using
the %d, reads the operator. Seeing the operator is not a digit,
it aborts scanning.

The easy solution is to put getchar() after the first scanf
statement which will remove the newline char from the input
buffer and enables you to read the operator into variable c.

--
Al Bowers
Tampa, Fl USA
mailto: xa******@myrapidsys.com (remove the x to send email)
http://www.geocities.com/abowers822/

Nov 14 '05 #4


Buck Rogers wrote:
Hi guys!

Task 1: Write a program which presents a menu with 5 options. The 5th
option quits
the program. Each option should execute a system command using system().

Below is my humble offering.
================================================== =
#include <stdio.h>
#include <stdlib.h>

int menu( void );

int main( void )
{
int option;

while(1) {
option = menu();
switch(option) {
case 1:
system("dir");
break;
case 2:
system("help");
break;
case 3:
system("time");
break;
case 4:
system("type menu.c");
break;
case 5:
puts("Quitting program");
exit(0);
default:
puts("Not a valid option, try again");
}
}
return 0;
}
<snip> ================================================== ========
Problem: My compiler is giving me an "unreachable code" warning for line
32(return 0;). The
program runs fine. Why does the compiler(Borland C++ Builder 6) give
this warning?


As others have already pointed out, you can't reach that line. Sticking
an "exit" in the middle of your code is pretty nasty in terms of code
structure (it's like having a "goto return;"), and having a loop that
you claim is infinite when it's not, isn't great either. If you have a
loop that termintes under some condition (or the negation of some
condition), then that condition is important enough to be explicitly
named by you so that anyone in future who has to enhance this code
doesn't have to waste time trying to work out the abstraction for that
condition.

To make your code clearer for the next guy who has to work on it (i.e.
more easily maintainable), write it this way:

int main( void )
{
int option;
int prompting = 1;

while(prompting) {
option = menu();
switch(option) {
case 1:
system("dir");
break;
case 2:
system("help");
break;
case 3:
system("time");
break;
case 4:
system("type menu.c");
break;
case 5:
puts("Quitting program");
prompting = 0;
break;
default:
puts("Not a valid option, try again");
}
}
return 0;
}

That will co-incidentally get rid of the compiler warning.

Ed.

Nov 14 '05 #5
Ed Morton wrote:
.... snip ...
To make your code clearer for the next guy who has to work on it
(i.e. more easily maintainable), write it this way:

int main( void )
{
int option;
int prompting = 1;

while(prompting) {
option = menu();
switch(option) {
case 1:
system("dir");
break;
case 2:
system("help");
break;
case 3:
system("time");
break;
case 4:
system("type menu.c");
break;
case 5:
puts("Quitting program");
prompting = 0;
break;
default:
puts("Not a valid option, try again");
}
}
return 0;
}

That will co-incidentally get rid of the compiler warning.


My solution for the same problem:

int main(void)
{
int option;

while(5 != (option = menu())) {
switch(option) {
case 1: system("dir"); break;
case 2: system("help"); break;
case 3: system("time"); break;
case 4: system("type menu.c"); break;
default: puts("Not a valid option, try again"); break;
}
}
puts("Quitting program");
return 0;
}

--
Chuck F (cb********@yahoo.com) (cb********@worldnet.att.net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net> USE worldnet address!

Nov 14 '05 #6
nrk wrote:
Buck Rogers wrote:

Hi guys!

Task 1: Write a program which presents a menu with 5 options. The 5th
option quits
the program. Each option should execute a system command using system().

Below is my humble offering.
================================================ === (snip code)
Problem: My compiler is giving me an "unreachable code" warning for line
32(return 0;). The
program runs fine. Why does the compiler(Borland C++ Builder 6) give this
warning?


The only way out of your while ( 1 ) loop is through the exit(0) call, and
that doesn't bring you to the return 0; statement either. Hence the
complaint. Ideally, you should be able to replace the exit(0) call with
return 0;


Or (better IMHO) replace the exit(0) with a break, so 1/code after the
loop may be executed and 2/ the function has a single point of exit
located at the end of the function (which usually makes a more readable
code).

Bruno

Nov 14 '05 #7
Buck Rogers wrote:

do {
option = menu();
switch(option) {
case 1:
system("dir");
break;
case 2:
system("help");
break;
case 3:
system("time");
break;
case 4:
system("type menu.c");
break;
case 5:
puts("Quitting program");
break;
default:
puts("Not a valid option, try again");
}
}


while (option != 5);

--
pete
Nov 14 '05 #8
On Sat, 17 Jan 2004 12:19:41 GMT, nrk
<ra*********@devnull.verizon.net> wrote:
Buck Rogers wrote:
Hi guys!

Task 1: Write a program which presents a menu with 5 options. The 5th
option quits
the program. Each option should execute a system command using system().

Below is my humble offering.
================================================== =
#include <stdio.h>
#include <stdlib.h>

int menu( void );

int main( void )
{
int option;

while(1) {
option = menu();
switch(option) {
case 1:
system("dir");
break;
case 2:
system("help");
break;
case 3:
system("time");
break;
case 4:
system("type menu.c");
break;
case 5:
puts("Quitting program");
exit(0);
default:
puts("Not a valid option, try again");
}
}
return 0;
}
snip Problem: My compiler is giving me an "unreachable code" warning for line
32(return 0;). The
program runs fine. Why does the compiler(Borland C++ Builder 6) give this
warning?

The only way out of your while ( 1 ) loop is through the exit(0) call, and
that doesn't bring you to the return 0; statement either. Hence the
complaint. Ideally, you should be able to replace the exit(0) call with


Why? The exit(0) works fine.
return 0; get rid of the existing return statements and the compiler should
be happy.


<<Remove the del for email>>
Nov 14 '05 #9
nrk
Barry Schwarz wrote:
On Sat, 17 Jan 2004 12:19:41 GMT, nrk
<ra*********@devnull.verizon.net> wrote:
Buck Rogers wrote:
Hi guys!

Task 1: Write a program which presents a menu with 5 options. The 5th
option quits
the program. Each option should execute a system command using system().

Below is my humble offering.
================================================== =
#include <stdio.h>
#include <stdlib.h>

int menu( void );

int main( void )
{
int option;

while(1) {
option = menu();
switch(option) {
case 1:
system("dir");
break;
case 2:
system("help");
break;
case 3:
system("time");
break;
case 4:
system("type menu.c");
break;
case 5:
puts("Quitting program");
exit(0);
default:
puts("Not a valid option, try again");
}
}
return 0;
}
snip Problem: My compiler is giving me an "unreachable code" warning for line
32(return 0;). The
program runs fine. Why does the compiler(Borland C++ Builder 6) give
this warning?


The only way out of your while ( 1 ) loop is through the exit(0) call, and
that doesn't bring you to the return 0; statement either. Hence the
complaint. Ideally, you should be able to replace the exit(0) call with


Why? The exit(0) works fine.


Except for the complaint from OP's compiler. Simply getting rid of the
return statment may not be an option as the compiler may complain about no
value being returned from main. Of course, you could just happily co-exist
with the compiler diagnostic as well.

-nrk.
return 0; get rid of the existing return statements and the compiler
should be happy.


<<Remove the del for email>>


--
Remove devnull for email
Nov 14 '05 #10
On Sat, 17 Jan 2004 11:17:52 UTC, Buck Rogers <wh*@cares.com.au>
wrote:
Hi guys!

Task 1: Write a program which presents a menu with 5 options. The 5th
option quits
the program. Each option should execute a system command using system().

Below is my humble offering.
================================================== =
#include <stdio.h>
#include <stdlib.h>

int menu( void );

int main( void )
{
int option;

while(1) {
This while is NOT wrong! But some compilers like to give you a warning
here that the test is against a constant. Avioding this warning is
simple: replace the while with

for (;;) {

The result is the same - but the compiler is quite still.Somebody like
to have a macro for this:

#define FOREVER for (;;)

and then instead writing the empty loop like
FOREVER [
but it is easy to trick out onesef because one tends to append the
semicolon to the macro - and as that is not a syntax error it produces
some unwanted code.
option = menu();
switch(option) {
case 1:
system("dir");
break;
use continue istead of break; break breaks the switsh block. continue
iterates the while and shows the reader that your current run is
clearly done.
case 2:
system("help");
break; same case 3:
system("time");
break; same case 4:
system("type menu.c");
break; same case 5:
puts("Quitting program");
exit(0);
Even as this is well you can use break here now instead to exit
immediately.
default:
puts("Not a valid option, try again");
another continue here makes cleear that you will run the next while.
}
Now, whenever you falls through the switch block you knows your while
should break, so

break;

lets you reach the return and the compiler will be happy.
}
return 0;
}

int menu( void )
{
int option;

puts("1. List directory");
puts("2. help");
puts("3. time");
puts("4. type menu.c");
puts("5. Quit");
scanf("%d", &option);

return option;
}
================================================== ========
Problem: My compiler is giving me an "unreachable code" warning for line
32(return 0;). The
program runs fine. Why does the compiler(Borland C++ Builder 6) give this
warning?

Task 2: Create a calculator program.

Below is my humble offering.
================================================== =================
#include <stdio.h>

void add(int a, int b);
void subtract(int a, int b);
void multiply(int a, int b);
void divide(int a, int b);

int main( void )
{
int a, b;
char c;

puts("Enter an integer");
Depending on your terminal nothing is shown yet. This is because
stdout is line bufferd and until one or both of the following cases is
not fullifyied nothing is send to the stream: either line is full or
newline is given.

fflush(stdout);

resolves that. This forces the stream to send the buffer to the device
immediately.

scanf("%d", &a);
scanf is errornous! You should avoid it. O.k., here is buffer overflow
no problem, but when you use scanf with other format string it is easy
to fall into that trap.

scanf is not designed to interact with keyboard or other other
untrusted devices. It ends up with giving you nothing when the input
does not match the format, living the unmatched data in stream.

puts("Enter an operator");
scanf("%c", &c);
puts("Enter another integer");
scanf("%d", &b);
Same as in the program above. Type something unwanded - and scanf
gives you nothing and anything hungs because scanf gives you nothing.
You can trap wrong input here: scanf returns the number of fields it
has filled, so
int rc = scanf("%d");
if (rc == 1) {
/* one value readed */
} else {
/* no value gotten, input wrong */
/* do something to receive the crap and continue */
/* attention: fflush() is undefined for input streams! */
}
switch( c ) {
case '*':
multiply(a, b);
break;
case '+':
add(a, b);
break;
case '-':
subtract(a, b);
break;
case '/':
divide(a, b);
break;
default:
puts("Operator is not valid");
}
return 0;
}

void add(int a, int b)
{
printf("Sum is: %d", a+b);
}

void subtract(int a, int b)
{
printf("Answer is: %d", a-b);
}

void multiply(int a, int b)
{
printf("Product is: %d", a*b);
}

void divide(int a, int b)
{
printf("Answer is: %d", a/b);
}
================================================== ===
Output:

Enter an integer
2
Enter an operator
Enter another integer

Problem: Why does the program not allow the user to input the operator
before
jumping straight to "Enter another integer"? I think I am missing
something very
fundamental here.


scanf is a problem, any other higher functions like fscanf too. The
problem is that all the functions are designed in a time as punchcards
were the standard input and console (TTY) were operator input (an
operator is/was commonly more trained to interact with his computer.
That was in the old days where PCs was not invented. We have to live
with now.

So any experienced programmer has his own library of helkper functions
to avoid this flaws. As getc() gives more and direct control over the
stream one of them is:

/* clean input stream */
int MyFlush(FILE *in) {
int c;

while ((c = getc(in)) != EOF && c != '\n')
; /* do nothing */
return c;
}

/* helper function to read numerical values */
/* read from stream an unsigned number */
/* return number in *u and number of digits readed as result */
static int GetNumber(FILE *in, unsigned long *u) {
int c;
int rc = 0;
int i = 0;

while ((c = getc(in) != EOF) {
if (c == '\n') break; /* newline found */
if (isdigit(c)) {
rc *= 10;
rc += c - '0';
i++;
/* read more! */
continue;
}
break;
}
/* not a digit */
ungetc(in); /* unwanted char back to stream */
*u = rc;
return i;
}
/* get an unsigned int from stream
*/
/* the value must be greater or equal to min and less or equal to max
*/
/* FILE *in stream to read from */
/* unsigned min, max minumum maximum value */
/* char *msg message shown to user, when NULL, nothing */
/* char *errmsg[] error messages: */
/* [0] number given < min */
/* 1 > max
*/
/* 2 not a number
*/
/* return value readed
*/
/*

unsigned int GetUInt(FILE *in,
unsigned min, unsigned max,
char *msg, char *errmsg[]) {
unsigned long u = 0; /* final result */
int l;

for (;;) {
if (msg) {
fputs(msg, stdout);
fflush(stdout);
}
if (GetNumber(in, &u)) {
if (u < min) {
fputs(errmsg[0]);
continue;
}
if (u > max) {
fputs(errmsg[1]);
continue;
}
break;
}
fputs(errmsg[2]);
}
return (unsigned int) u;
}

how to read signed int, float.... left as homework to the reader.
When your compiler supports unsigned long long use that instead of
unsigned long as intermediate values.
--
Tschau/Bye
Herbert

Visit http://www.ecomstation.de the home of german eComStation

Nov 14 '05 #11
"The Real OS/2 Guy" <os****@pc-rosenau.de> wrote in message
news:wmzsGguTDN6N-pn2-6xUmS86KvrDj@moon...
On Sat, 17 Jan 2004 11:17:52 UTC, Buck Rogers <wh*@cares.com.au>
wrote: ....
#include <stdio.h>
#include <stdlib.h>

int menu( void );

int main( void )
{
int option;

while(1) {


This while is NOT wrong! But some compilers like to give you a warning
here that the test is against a constant. Avioding this warning is
simple:


And unnecessary. [Just turn off the warning or get a better compiler... ;-]
replace the while with

for (;;) {

The result is the same - but the compiler is quite still.
Not if someone writes a compiler with warnings like...

warning: no expression used in for loop

Warnings (and the ability to turn them off) is a QoI issue.
Somebody like to have a macro for this:

#define FOREVER for (;;)

and then instead writing the empty loop like
FOREVER [
but it is easy to trick out onesef because one tends to append the
semicolon to the macro - and as that is not a syntax error it produces
some unwanted code.
It seems to lose something in translation, but it sounds like a good reason
for not defining such a macro. ;)
option = menu();
switch(option) {
case 1:
system("dir");
break;


use continue istead of break; break breaks the switsh block. continue
iterates the while and shows the reader that your current run is
clearly done.


I don't think that's a good thing to do in general. If the programmer later
wants to add some housekeeping after the the switch statement, then they've
got to replace all the continue statements [back to breaks which would have
worked just fine in the initial instance.]

....
default:
puts("Not a valid option, try again");


another continue here makes cleear that you will run the next while.
}


Now, whenever you falls through the switch block you knows your while
should break, so

break;

lets you reach the return and the compiler will be happy.
}
That looks like goto style spagetti code to me!
return 0;
}
.... int main( void )
{
int a, b;
char c;

puts("Enter an integer");


Depending on your terminal nothing is shown yet.


Yes, you will need a working switched on monitor to see the prompt! <g>
This is because
stdout is line bufferd and until one or both of the following cases is
not fullifyied nothing is send to the stream: either line is full or
newline is given.

fflush(stdout);

resolves that. This forces the stream to send the buffer to the device
immediately.

The puts() call appends a \n to the output [though fputs() doesn't.] If
stdout is fully buffered, then the user isn't likely to see the prompt with
or without the fflush. So the fflush() is redundant in this case.
scanf("%d", &a);


scanf is errornous! You should avoid it. O.k., here is buffer overflow
no problem, but when you use scanf with other format string it is easy
to fall into that trap.

scanf is not designed to interact with keyboard or other other
untrusted devices.


Huh?
It ends up with giving you nothing when the input
does not match the format, living the unmatched data in stream.
puts("Enter an operator");
scanf("%c", &c);
puts("Enter another integer");
scanf("%d", &b);
Same as in the program above. Type something unwanded - and scanf
gives you nothing and anything hungs because scanf gives you nothing.
You can trap wrong input here: scanf returns the number of fields it
has filled, so
int rc = scanf("%d");


You're missing a destination for the converted input.
if (rc == 1) {
/* one value readed */
} else {
/* no value gotten, input wrong */
/* do something to receive the crap and continue */
/* attention: fflush() is undefined for input streams! */
}
<snip>
Problem: Why does the program not allow the user to input the operator
before
jumping straight to "Enter another integer"? I think I am missing
something very
fundamental here.


scanf is a problem, any other higher functions like fscanf too. The
problem is that all the functions are designed in a time as punchcards
were the standard input and console (TTY) were operator input (an
operator is/was commonly more trained to interact with his computer.


What are you smoking, and where can I get some? <g>
That was in the old days where PCs was not invented. We have to live
with now.

So any experienced programmer has his own library of helkper functions
to avoid this flaws. As getc() gives more and direct control over the
stream one of them is:
<snip>
/* helper function to read numerical values */
/* read from stream an unsigned number */
/* return number in *u and number of digits readed as result */
static int GetNumber(FILE *in, unsigned long *u) {
int c;
int rc = 0;
Why not just use *u ?
int i = 0;

while ((c = getc(in) != EOF) {
if (c == '\n') break; /* newline found */
Redundant test as '\n' is not a digit.
if (isdigit(c)) {
if (isdigit((unsigned char) c))
rc *= 10;
rc += c - '0';

And what happens if and when the int overflows?
i++;
/* read more! */
continue;
}
break;
}

More spagetti code! Try...

while ( (c = getc(in)) != EOF
&& isdigit((unsigned char) c) )
{
/* process next digit */
}
/* not a digit */
ungetc(in); /* unwanted char back to stream */
*u = rc;
return i;
}


Your method does nothing to detect the case where an unsigned integer
overflow has occured. That said, 100% bullet proof methods for integer input
are surprisingly non trivial.

--
Peter
Nov 14 '05 #12
On Sun, 18 Jan 2004 00:33:37 GMT, nrk
<ra*********@devnull.verizon.net> wrote:
Barry Schwarz wrote:
On Sat, 17 Jan 2004 12:19:41 GMT, nrk
<ra*********@devnull.verizon.net> wrote:
Buck Rogers wrote:

Hi guys!

Task 1: Write a program which presents a menu with 5 options. The 5th
option quits
the program. Each option should execute a system command using system().

Below is my humble offering.
================================================== =
#include <stdio.h>
#include <stdlib.h>

int menu( void );

int main( void )
{
int option;

while(1) {
option = menu();
switch(option) {
case 1:
system("dir");
break;
case 2:
system("help");
break;
case 3:
system("time");
break;
case 4:
system("type menu.c");
break;
case 5:
puts("Quitting program");
exit(0);
default:
puts("Not a valid option, try again");
}
}
return 0;
}
snip
Problem: My compiler is giving me an "unreachable code" warning for line
32(return 0;). The
program runs fine. Why does the compiler(Borland C++ Builder 6) give
this warning?
The only way out of your while ( 1 ) loop is through the exit(0) call, and
that doesn't bring you to the return 0; statement either. Hence the
complaint. Ideally, you should be able to replace the exit(0) call with


Why? The exit(0) works fine.


Except for the complaint from OP's compiler. Simply getting rid of the
return statment may not be an option as the compiler may complain about no
value being returned from main. Of course, you could just happily co-exist
with the compiler diagnostic as well.


Replacing the exit(0) with return 0 will do nothing to silence the
complaint.

-nrk.
return 0; get rid of the existing return statements and the compiler
should be happy.


<<Remove the del for email>>


<<Remove the del for email>>
Nov 14 '05 #13
nrk
Barry Schwarz wrote:
On Sun, 18 Jan 2004 00:33:37 GMT, nrk
<ra*********@devnull.verizon.net> wrote:
Barry Schwarz wrote:
On Sat, 17 Jan 2004 12:19:41 GMT, nrk
<ra*********@devnull.verizon.net> wrote:

Buck Rogers wrote:

> Hi guys!
>
> Task 1: Write a program which presents a menu with 5 options. The 5th
> option quits
> the program. Each option should execute a system command using
> system().
>
> Below is my humble offering.
> ================================================== =
> #include <stdio.h>
> #include <stdlib.h>
>
> int menu( void );
>
> int main( void )
> {
> int option;
>
> while(1) {
> option = menu();
> switch(option) {
> case 1:
> system("dir");
> break;
> case 2:
> system("help");
> break;
> case 3:
> system("time");
> break;
> case 4:
> system("type menu.c");
> break;
> case 5:
> puts("Quitting program");
> exit(0);
> default:
> puts("Not a valid option, try again");
> }
> }
> return 0;
> }
>
snip
> Problem: My compiler is giving me an "unreachable code" warning for
> line 32(return 0;). The
> program runs fine. Why does the compiler(Borland C++ Builder 6) give
> this warning?
>

The only way out of your while ( 1 ) loop is through the exit(0) call,
and
that doesn't bring you to the return 0; statement either. Hence the
complaint. Ideally, you should be able to replace the exit(0) call with

Why? The exit(0) works fine.


Except for the complaint from OP's compiler. Simply getting rid of the
return statment may not be an option as the compiler may complain about no
value being returned from main. Of course, you could just happily
co-exist with the compiler diagnostic as well.


Replacing the exit(0) with return 0 will do nothing to silence the
complaint.


It will. Read the rest of the quote that follows below.

-nrk.

-nrk.
return 0; get rid of the existing return statements and the compiler
should be happy.

--
Remove devnull for email
Nov 14 '05 #14
On Sun, 18 Jan 2004 14:16:41 UTC, "Peter Nilsson" <ai***@acay.com.au>
wrote:
"The Real OS/2 Guy" <os****@pc-rosenau.de> wrote in message
news:wmzsGguTDN6N-pn2-6xUmS86KvrDj@moon...
On Sat, 17 Jan 2004 11:17:52 UTC, Buck Rogers <wh*@cares.com.au>
wrote: ...
#include <stdio.h>
#include <stdlib.h>

int menu( void );

int main( void )
{
int option;

while(1) {


This while is NOT wrong! But some compilers like to give you a warning
here that the test is against a constant. Avioding this warning is
simple:


And unnecessary. [Just turn off the warning or get a better compiler... ;-]


Never! Each warning a compiler can give you is important when you not
aware of. A condition that evaluates always true is often senseless
and points to a programming error.
A loop without condition is in contrast to that normal.

replace the while with

for (;;) {

The result is the same - but the compiler is quite still.


Not if someone writes a compiler with warnings like...

warning: no expression used in for loop


This is senseless - always.
Warnings (and the ability to turn them off) is a QoI issue.
Somebody like to have a macro for this:

#define FOREVER for (;;)

and then instead writing the empty loop like
FOREVER [
but it is easy to trick out onesef because one tends to append the
semicolon to the macro - and as that is not a syntax error it produces
some unwanted code.
It seems to lose something in translation, but it sounds like a good reason
for not defining such a macro. ;)
option = menu();
switch(option) {
case 1:
system("dir");
break;


use continue istead of break; break breaks the switsh block. continue
iterates the while and shows the reader that your current run is
clearly done.


I don't think that's a good thing to do in general. If the programmer later
wants to add some housekeeping after the the switch statement, then they've
got to replace all the continue statements [back to breaks which would have
worked just fine in the initial instance.]


No, but you may use flages to handle flags to handle flags when you
are unable to work out a clean design. Don't hack around and you'll
have always functions with a clean design, avoiding gotos, flags and
flags you don't need. Learn how to use continue and you'll save flags
have clean and short code.

Whenever an action is done 'contimue' is good to flag that. 'break'
shows that you're halfway done, but something left over for common
actions.

'exit()' is good for emergency breakout - but never for break on data
fault. A well designed program does never use exit except for an point
whereas nothing else makes sense.
...
default:
puts("Not a valid option, try again");
another continue here makes cleear that you will run the next while.
}


Now, whenever you falls through the switch block you knows your while
should break, so

break;

lets you reach the return and the compiler will be happy.
}
That looks like goto style spagetti code to me!


No, it's clear: continue shows up that anything to do is done, next
loop has to run. Break from switch shows that there is something left
to do. And in this case the only that can left over is to break the
whole loop. spaghetti code looks absolutely different. It were easy to
use goto but goto will break ever the flow - and there is no need to
break the flow. Again, learn what continue does for you. It helps you
to document the data flow!
return 0;
}
... int main( void )
{
int a, b;
char c;

puts("Enter an integer");


Depending on your terminal nothing is shown yet.


Yes, you will need a working switched on monitor to see the prompt! <g>


[ ] You knows the difference between unbuffered, line buffered and
block buffered devices.
This is because
stdout is line bufferd and until one or both of the following cases is
not fullifyied nothing is send to the stream: either line is full or
newline is given.

fflush(stdout);

resolves that. This forces the stream to send the buffer to the device
immediately.

The puts() call appends a \n to the output [though fputs() doesn't.] If
stdout is fully buffered, then the user isn't likely to see the prompt with
or without the fflush. So the fflush() is redundant in this case.
scanf("%d", &a);


scanf is errornous! You should avoid it. O.k., here is buffer overflow
no problem, but when you use scanf with other format string it is easy
to fall into that trap.

scanf is not designed to interact with keyboard or other other
untrusted devices.


Huh?


Give
d o n ' t t y p e t ex t wh en y h a ve t
o
t
y p
e
a n
um
er
instead a number and try to catch that. Users are crazy alays. You
have more work to catch typing errors than to work with regular input.

Writing an own function to receive exactly that you awaits from the
stream makes it much easier to handle the crap a user gives you as you
ever can have with the old design (f)scanf() brings. Reading something
in only to copy it again to copy it again to scan it is waste of
resources.

Why not just use *u ?
A leftover from the old days where compilers were not so good in
optimising and code generation as today and the time difference
between indirect addressing as in modifying a variable a pointer
points to was really slow because the mashine was unable to do it
other than to read to a register modify that register and write back.
Direct register manipulation was in factor 10 to 100 more quick!

int i = 0;

while ((c = getc(in) != EOF) {
if (c == '\n') break; /* newline found */


Redundant test as '\n' is not a digit.


O.k., yes - but a bit documentation that distinguishes betwen unwanted
and wanted chars.
if (isdigit(c)) {


if (isdigit((unsigned char) c))
rc *= 10;
rc += c - '0';

And what happens if and when the int overflows?


Have you ever done this test in a real program? You can do it anyway
as you can test if the number of digits should reflect it.
Your method does nothing to detect the case where an unsigned integer
overflow has occured. That said, 100% bullet proof methods for integer input
are surprisingly non trivial.


It is trivial - but costs more code when you have the real need to
dedect it immediately.

Save the old vale. Add and compare with the old value. Whenever the
old value is lower as the new one you have had an overflow in unsigned
arithmetic. Simple.

Does you really check each and any arithmetic operation for overflow?
I don't think so.

Here it is easy to let the user of the function do it when he feels
the need. That is one of the points why the function returns the
number of digits readed and not only the converted number.

--
Tschau/Bye
Herbert

Visit http://www.ecomstation.de the home of german eComStation

Nov 14 '05 #15
On Mon, 19 Jan 2004 05:29:19 GMT, nrk
<ra*********@devnull.verizon.net> wrote:
Barry Schwarz wrote:
On Sun, 18 Jan 2004 00:33:37 GMT, nrk
<ra*********@devnull.verizon.net> wrote:
Barry Schwarz wrote:

On Sat, 17 Jan 2004 12:19:41 GMT, nrk
<ra*********@devnull.verizon.net> wrote:

>Buck Rogers wrote:
>
>> Hi guys!
>>
>> Task 1: Write a program which presents a menu with 5 options. The 5th
>> option quits
>> the program. Each option should execute a system command using
>> system().
>>
>> Below is my humble offering.
>> ================================================== =
>> #include <stdio.h>
>> #include <stdlib.h>
>>
>> int menu( void );
>>
>> int main( void )
>> {
>> int option;
>>
>> while(1) {
>> option = menu();
>> switch(option) {
>> case 1:
>> system("dir");
>> break;
>> case 2:
>> system("help");
>> break;
>> case 3:
>> system("time");
>> break;
>> case 4:
>> system("type menu.c");
>> break;
>> case 5:
>> puts("Quitting program");
>> exit(0);
>> default:
>> puts("Not a valid option, try again");
>> }
>> }
>> return 0;
>> }
>>
snip
>> Problem: My compiler is giving me an "unreachable code" warning for
>> line 32(return 0;). The
>> program runs fine. Why does the compiler(Borland C++ Builder 6) give
>> this warning?
>>
>
>The only way out of your while ( 1 ) loop is through the exit(0) call,
>and
>that doesn't bring you to the return 0; statement either. Hence the
>complaint. Ideally, you should be able to replace the exit(0) call with

Why? The exit(0) works fine.
Except for the complaint from OP's compiler. Simply getting rid of the
return statment may not be an option as the compiler may complain about no
value being returned from main. Of course, you could just happily
co-exist with the compiler diagnostic as well.
Replacing the exit(0) with return 0 will do nothing to silence the
complaint.


It will. Read the rest of the quote that follows below.


The rest of the quote will get rid of the complaint without replacing
the exit(0) with a return 0. I have no argument with your clause that
follows the semicolon. My question is what benefit is derived from
the clause before the semicolon?

-nrk.

-nrk.

>return 0; get rid of the existing return statements and the compiler
>should be happy.
>


<<Remove the del for email>>
Nov 14 '05 #16

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

reply views Thread by Durham Writer | last post: by
2 posts views Thread by Stephen | last post: by
9 posts views Thread by silverchrono | last post: by
4 posts views Thread by inspiretechnologies | last post: by
4 posts views Thread by Dave G | last post: by
1 post views Thread by fmendoza | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.