Complete.Org: Mailing Lists: Archives: discussion: August 2000:
[aclug-L] Re: C programing problem
Home

[aclug-L] Re: C programing problem

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: discussion@xxxxxxxxx
Subject: [aclug-L] Re: C programing problem
From: james <solosuze@xxxxxxxxxxxxxxxx>
Date: Mon, 14 Aug 2000 22:00:04 -0500
Reply-to: discussion@xxxxxxxxx

Thanks for the advice!
It will take a while for my 'blessed' mind to digest all of it :)


Tom Hull wrote:

> james wrote:
> >
> > yeah, I sent it as an attachment, and it wasn't recognized:
> >
> > >
> > > > -- Binary/unsupported file stripped by Listar --
> > > > -- Type:
> > > > application/x-unknown-content-type-TextPad.c
> > > > -- File: mathQuiz.c
> > > >
>
> Main problem: do not (ever!) use scanf() to read input from an
> unreliable input source, the definition of which includes any
> and all human beings. scanf() gets very confused if you don't
> feed it data in exactly the order that you request it, and once
> it's out of sync, you're hosed. You said that addition() works
> OK, but subtraction() doesn't. Not blessed with your intricate
> knowledge of the program, I never made it past addition().
>
> Some possible solutions:
>
>  1) Read a line of input into a buffer, then use sscanf() to
>     get the data from the buffer. For example:
>
>       char buf[128];
>
>       while (gets(buf)) {
>         if (sscanf(buf, "%c", &choice) == 1) {
>           switch (choice) {
>             case 'a': ...; break;
>           }
>         }
>       }
>
>     Since scanf("%c", ...) only reads the next character, w/o
>     checking to discard whitespace, you can replace the sscanf()
>     above with:
>
>       choice = buf[0];
>
>     In the case of "press any key", you really mean "press return
>     to continue", which is just:
>
>       gets(buf);
>
>     In all cases, make sure buf is larger than anyone would be
>     tempted to type in, because gets() isn't smart enough to
>     keep a user from overflowing your buffer. If you're more
>     paranoid (and paranoia is a good habit in programming),
>     use fgets(), check for '\n' to detect overflows, etc.
>
>  2) The reason why the easy way to do this is #1 above is that
>     your tty is normally in "cooked" mode. In "cooked" mode, the
>     user can use some editing keys (like backspace or delete) to
>     correct the input, which is only released from the operating
>     system to your program when the return key is hit. If you
>     want to be able to detect keys as they are hit (for example,
>     if you want "press any key" to work as advertised, you have
>     to put the terminal into "raw" mode. There are basically two
>     ways to do this: use the termios(3) interface, or use the
>     curses library. For anything more complicated than your
>     present program, curses is the way to go.
>
> A couple of other little nits are noted below.
>
> > Any ways here it is, sorry about the problems.
> >
> > #include <stdio.h>
> >
> > int numList1[10], numList2[10];
> >
> > main(){
> >
> >  char choice = ' ';
> >  int cntra, cntrb, cntrc, cntrd;
> >  cntra = 1;
> >  cntrb = 3;
> >  cntrc = 5;
> >  cntrd = 2;
> >
> >  initialize();
> >
> >  while(1==1){
>
> For forever loops, use while (1) or for (;;). What you wrote is
> harmless (it will be optimized out of existence), but requirse
> unnecessary brainpower to decipher.
>
> >   clr();
> >   printf("please choose a quiz:\n\n");
> >   printf("A) addition quiz\n");
> >   printf("B) subtraction quiz\n");
> >   printf("C) multiplacation quiz\n");
> >   printf("D) division quiz\n");
> >   printf("Q) quit\n\n\n");
> >   scanf("\n%c", &choice);
> >
> >   if(choice == 'a'){
> >    clr();
> >    addition(cntra, cntrb);
> >   }else if(choice == 'b'){
> >    clr();
> >    subtraction(cntrc, cntrd);
> >   }else if(choice == 'c'){
> >    clr();
> >    multiplication();
> >   }else if(choice == 'd'){
> >    clr();
> >    division();
> >   }else if(choice == 'q'){
> >    break;
> >   }else{
> >    printf("%c", 7);
> >    continue;
> >   }
> >  }
> >  clr();
> > }
> >
> > clr(){
> >  int cntr = 0;
> >  while(cntr < 26){
> >   printf("\n");
> >   cntr += 1;
> >  }
> > }
>
> Curses has a function for this, which will work reliably even
> if your tty is more than 26 lines high.
>
> > initialize(){
>
> Any function which doesn't return a value should be declared
> as void, e.g.: void initialize()
>
> >  numList1[0] = 1;
> >  numList1[1] = 2;
> >  numList1[2] = 3;
> >  numList1[3] = 4;
> >  numList1[4] = 5;
> >  numList1[5] = 6;
> >  numList1[6] = 7;
> >  numList1[7] = 8;
> >  numList1[8] = 9;
> >  numList1[9] = 10;
> >
> >  numList2[0] = 10;
> >  numList2[1] = 9;
> >  numList2[2] = 8;
> >  numList2[3] = 7;
> >  numList2[4] = 6;
> >  numList2[5] = 5;
> >  numList2[6] = 4;
> >  numList2[7] = 3;
> >  numList2[8] = 2;
> >  numList2[9] = 1;
> > }
>
> You can do the above initialization statically, e.g.:
>
> int numList1[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
> int numList2[10] = { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 };
>
> > addition(int cntr1, int cntr2){
> >
> >  int numOne, numTwo, answer;
> >  int again = 0;
> >  char dummy = ' ';
> >
> >  while(again < 5){
> >   numOne = numList1[cntr1];
> >   numTwo = numList2[cntr2];
> >
> >   printf("\nWhat is %d plus %d? ", numOne, numTwo);
> >   scanf("\n%d", &answer);
> >   if(answer == (numOne + numTwo)){
> >    printf("\nYou are Correct, Sir!\n\n");
> >   }else{
> >    printf("\nhiii hooooo, you are WRONG!\n\n");
> >    printf("the answer is %d\n", (numOne + numTwo));
> >   }
> >   cntr1 = cntr1 + 2;
> >   cntr2 = cntr2 + 1;
> >   if(cntr1 >= 9){
> >    cntr2 = 1;
> >   }
> >   if(cntr2 >= 2){
> >    cntr2 = 3;
> >   }
> >   again += 1;
> >  }
> >  printf("press any key");
> >  scanf("\n%c", &dummy);
> > }
> >
> > subtraction(int cntr1, int cntr2){
> >
> >  int numOne, numTwo, answer;
> >  int again = 0;
> >  char dummy = ' ';
> >
> >  while(again < 5){
> >   numOne = numList1[cntr1];
> >   numTwo = numList2[cntr2];
> >
> >   if((numOne - numTwo) > 0){
> >    printf("\nWhat is %d minus %d? ", numOne, numTwo);
> >    scanf("\n%d", &answer);
> >    if(answer == (numOne - numTwo)){
> >     printf("\nYou are Correct, Sir!\n\n");
> >    }else{
> >     printf("\nhiii hooooo, you are WRONG!\n\n");
> >     printf("the answer is %d\n", (numOne - numTwo));
> >    }
> >   }
> >   cntr1 = cntr1 + 2;
> >   cntr2 = cntr2 + 2;
> >   if(cntr1 >= 9){
> >    cntr1 = 2;
> >   }
> >   if(cntr2 >= 9){
> >    cntr2 = 3;
> >   }
> >   again += 1;
> >  }
> >  printf("press any key");
> >  scanf("\n%c", &dummy);
> >
> > }
> >
> > multiplication(){
> >
> >  int numOne, numTwo, cntra, cntrb, answer;
> >  char again = 'y';
> >  cntra = 14;
> >  cntrb = 1;
> >
> >  while(again == 'y' || again == 'Y'){
> >   numOne = numList1[cntra];
> >   numTwo = numList2[cntrb];
> >
> >   printf("\nWhat is %d times %d? ", numOne, numTwo);
> >   scanf("\n%d", &answer);
> >   if(answer == (numOne * numTwo)){
> >    printf("\nYou are Correct, Sir!\n\n");
> >    printf("Want another? ");
> >    scanf("\n%c", &again);
> >   }else{
> >    printf("\nhiii hooooo, you are WRONG!\n\n");
> >    printf("the answer is %d\n", (numOne * numTwo));
> >    printf("Want another? ");
> >    scanf("\n%c", &again);
> >   }
>
> Once you write something a couple of times, it's very tempting
> to make it a function, e.g.:
>
> int eval_answer(int given_answer, int correct_answer)
> {
>   char buf[128];
>   int again = 'y';
>
>   if (given_answer == correct_answer) {
>     printf("\nYou are Correct, Sir!\n\n");
>   }
>   else {
>     printf("\nhii hooooo, you are WRONG!\n\n");
>     printf("the answer is %d\n", correct_answer);
>   }
>   printf("Want another? ");
>   if (gets(buf) && buf[0])
>     again = buf[0];
>   return again;
> }
>
> You would then call this like:
>
>   again = eval_answer(answer, numOne * numTwo);
>
> >    cntra = cntra + 9;
> >    cntrb = cntrb + 4;
> >   if(cntra >= 19){
> >    cntra = 2;
> >   }
> >   if(cntrb >= 19){
> >    cntrb = 3;
> >   }
> >  }
> >
> > }
> >
> > division(){
> >
> >  int numOne, numTwo, cntra, cntrb, answer, remainder;
> >  char again = 'y';
> >  cntra = 10;
> >  cntrb = 9;
> >
> >  while(again == 'y' || again == 'Y'){
> >   numOne = numList1[cntra];
> >   numTwo = numList2[cntrb];
> >
> >   printf("\nWhat is %d divided by %d? ", numOne, numTwo);
> >   scanf("\n%d", &answer);
> >   printf("and the remainder? ");
> >   scanf("\n%d", &remainder);
> >   if((answer == (numOne / numTwo)) && (remainder ==
> > (numOne % numTwo))){
> >    printf("\nYou are Correct, Sir!\n\n");
> >    printf("Want another? ");
> >    scanf("\n%c", &again);
> >   }else{
> >    printf("\nhiii hooooo, you are WRONG!\n\n");
> >    printf("the answer is %d, remainder: %d", (numOne
> > / numTwo), (numOne % numTwo));
> >    printf("Want another? ");
> >    scanf("\n%c", &again);
> >   }
> >    cntra = cntra + 1;
> >    cntrb = cntrb + 7;
> >   if(cntra >= 19){
> >    cntra = 2;
> >   }
> >   if(cntrb >= 19){
> >    cntrb = 3;
> >   }
> >  }
> >
> > }
>
> --
> /*
>  *  Tom Hull * thull@xxxxxxxxxxx * http://www.ocston.org/~thull/
>  */
>
> -- This is the discussion@xxxxxxxxx list.  To unsubscribe,
> visit http://tmp2.complete.org/cgi-bin/listargate-aclug.cgi


-- This is the discussion@xxxxxxxxx list.  To unsubscribe,
visit http://tmp2.complete.org/cgi-bin/listargate-aclug.cgi


[Prev in Thread] Current Thread [Next in Thread]