[aclug-L] Re: C programing problem
[Top] [All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
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
|
|