Thread: Redundant output

  1. #1
    Registered User
    Join Date
    Nov 2020
    Posts
    12

    Redundant output

    C program. IDE used is Xcode v12.2

    After typing the letter 'S' to show results, the program displays two outputs. But when entering the letters 'P' or 'R', the program displays normal output.

    Redundant output-screenshot-2020-12-16-11-25-20-am-png

    Code:
    bool done = false;
            bool unsure = true;
            bool showS = true;
     
            while (unsure)
            {
                unsure = false;
                puts("\n");
                if (showS)
                {
                    puts(" Enter 'S' to show results");
                }
                puts(" Enter 'P' to play another round");
                puts(" Enter 'R' to return to main menu");
                char choice;
                printf(" ");
                scanf("%c", &choice);
                if (choice == 'r' || choice == 'R')
                {
                    done = true;
                }
                else
                {
     
                    ///////////////////////// Changes    /////////////
     
                    g = 0;
                    // calculate total score for current round
                    for (i = 0; i < MAX_TESTS; i++)
                    {
                        g += test[i].grade;    //add score of each question
                    }
                    allScore += g;    //add current round's score to total
                    avg = allScore / rounds;    //average of all rounds
     
                    if (g > highest)
                    {
                        highest = g;
                    }
     
                    if (g < lowest)
                    {
                        lowest = g;
                    }
     
                    if (choice == 'S' || choice == 's')
                    {
                        showS = false;
                        if (rounds == 1)
                        {
                            printf(" Final score: %d/100\n", g);    //display round score
                            printf(" ******Player: %s ******\n", name);
                        }
                        else
                        {
                            printf(" Round %d score: %d/100\n", rounds, g);    //display round score
                            printf(" Highest score: %d/100\n", highest);
                            printf(" Lowest score: %d/100\n", lowest);
                            printf(" Average score: %d/100\n", avg);
                            printf(" ******Player: %s ******\n", name);
                        }
                        unsure = true;
                    }
                    else if (choice == 'P' || choice == 'p')
                    {
                             /// nothing to be done here
                        //we will display next test
                    }
                    else
                    {
                        puts(" Invalid input!");
                        unsure = true;
                    }
     
                    ////////////////////////////////////
     
                }
            }
            if (done)
                break;
        }
    }
    Any advice would be greatly appreciated.

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    This is basically the same issue as your previous thread on Weird 'Enter' key glitches.

    You have to understand that when the user enters "S", this ends up being two characters in the input buffer: 'S' and '\n'. Your scanf call reads the 'S' as expected, and then you compute the results and print it. Then, you go to the next iteration of the loop. Since '\n' is in the input buffer, it is read by scanf, and hence you get "Invalid input!" as the output. Then you go to the next iteration of the loop, so you see the "Enter 'P' to play another round" etc prompt again.

    I believe you already have solutions for this suggested to you, and they would come in two general categories:
    • Discard the trailing whitespace in the input buffer after reading the character.
    • Read a line and parse it.

    For the latter, I responded to a post with an example not too long ago: How to wait until a condition is met before proceeding, and that is what I would recommend because for a beginner with reasonable assumptions about input it tends to be pretty easy to implement.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  3. #3
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    You have a perfectly good function in myread, but then you louse things up with your mix-and-match hackery of calling getchar / scanf and that piece of garbage fflush(stdin). fflush is for OUTPUT streams, not input streams.

    Your code, calling ONLY myread()
    Code:
    #include <limits.h>
    #include <stdbool.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    #include <string.h>
    #define MAX_TESTS 10
    #define MAXQUESTION 10000
    
    bool myread(const char *format, void *address)
    {
        char buffer[1024];
        fgets(buffer, sizeof buffer, stdin);
        return sscanf(buffer, format, address) == 1;
    }
    
    struct struc
    {
        int a;
    
        int b;
    
        int c;
    
        int add;
    
        int grade;
    };
    
    struct struc ques_db[MAXQUESTION];    //database to hold all the previous questions
    
    int ques_db_count = 0;    //count of question currently in the database
    
    //function to traverse the question in database and
    // see if the current question has already been asked
    int find_in_db(struct struc *t)
    {
        int i;
        for (i = 0; i < ques_db_count; i++)
        {
            // check to see if the question in database is same as
            // the current generated one. It compares value of a, b
            // add (i.e. result) if all of them are same then the
            // question was same as the current one
    
            if (ques_db[i].a == t->a &&
                ques_db[i].b == t->b &&
                ques_db[i].add == t->add)
                return -1;
        }
    
        return 0;
    }
    
    int add_in_db(struct struc *t)    //function to add the currently generated question to database
    
    {
        //first check if the question is already there in the db
        if (-1 == find_in_db(t))
            return -1;
        else
        {
            // if not there then add to the db for future reference
            ques_db[ques_db_count++] = *t;
            return 0;
        }
    }
    
    int sj(int n)
    {
        int t;
    
        t = rand() % n;
    
        return t;
    }
    
    void ctm_i(struct struc *t)
    {
        do {
            t->a = sj(101);
            t->c = sj(4);
            if (t->c == 1)
            {
                t->b = sj(101 - (t->a));
                t->add = (t->a) + (t->b);
            }
            else
            {
                t->b = sj((t->a) + 1);
                t->add = (t->a) - (t->b);
            }
            t->grade = 0;
        }
        while (add_in_db(t) != 0);    //process repeats if question is not added due to repetition
    }
    
    void print_positive_message()
    {
        char positive_words[8][50] = { "\n Bingo!",
            "\n Great job!",
            "\n Very good!",
            "\n Brilliant!",
            "\n That's correct!",
            "\n You got it!",
            "\n Bravo!",
            "\n Awesome!" };
        // Replace your print statement here
        printf("%s", positive_words[rand() % 8]);
    }
    
    void tcm_i(struct struc *t, int n)
    {
        int ad;
    
        printf(" ***********************************************************************"
            "*********\n");
    
        printf(" ......................................................................."
            ".........\n");
    
        printf(" Question %d\n\n", n + 1);
    
        printf(" You have 3 attempts for this question\n\n");
    
        if (t->c == 1)
            printf(" %d+%d= ", t->a, t->b);
        else
            printf(" %d-%d= ", t->a, t->b);
    
        myread("%d", &ad);
        if (ad == t->add)
    
        {
            t->grade = 10;
    
            print_positive_message();
    
            printf(" You earned 10 marks\n\n");
        }
        else
        {
            printf("\n Incorrect, you have 2 attempts remaining\n\n");
            printf(" ");
            myread("%d", &ad);
    
            if (ad == t->add)
    
            {
    
                t->grade = 7;
    
                print_positive_message();
    
                printf(" You earned 7 marks\n\n");
            }
            else
            {
                printf("\n Incorrect, you have 1 attempt remaining\n\n");
                printf(" ");
                myread("%d", &ad);
    
                if (ad == t->add)
    
                {
    
                    t->grade = 5;
    
                    print_positive_message();
    
                    printf(" You earned 5 marks\n\n");
                }
                else
                {
                    t->grade = 0;
    
                    printf("\n Failure, 0 mark\n\n");
    
                    printf("\n The correct answer is %d\n\n", t->add);
                }
            }
        }
    
        printf(" ......................................................................."
            ".........\n");
    
        printf(" ***********************************************************************"
            "*********\n");
    }
    
    void display_instructions()
    {
        // function created only to display instructions of quiz
        printf(" ***********************************************************************"
            "************\n");
    
        printf(" ......................................................................."
            "............\n");
    
        printf(" *************************************Welcome! ************************************\n");
    
        printf(" ......................This program is for students Grades 1-2......................\n");
    
        printf("\n Program description:\n");
    
        printf(" (1)10 questions are randomly generated, each question is worth 10 points.\n");
        printf(" (2)Only addition and subtraction within 100 is allowed.\n    The sum and the difference of the two numbers do not exceed the range of 0-100.\n    Negative numbers are not included.\n");
        printf(" (3)There are 3 attempts for each question.;\n");
        printf(" (4)For each question:\n        1. 10 points will be awarded for the first successful attempt.\n        2. 7 points for the second attempt.\n        3. 5 points for the third attempt.\n");
        printf(" (5)At the end of the program enter:\n        'P' to start a new game;\n        'S' to show the results;\n        'Q' to quit.\n\n");
        printf(" ......................................................................."
            ".........\n");
    }
    
    void quiz(char name[])
    {
        int rounds = 0;
        int highest = 0;
        int lowest = INT_MAX;
        float allScore = 0;
        int avg = 0;
    
        int i, j, g = 0;
        struct struc test[MAX_TESTS];
    
        srand((unsigned) time(NULL));
    
        for (;;)
        {
            rounds++;
            for (i = 0; i < MAX_TESTS; i++)    // generate all questions
            {
                ctm_i(&test[i]);
    
                for (j = 0; j < i; j++)
    
                    if (test[i].a == test[j].a && test[i].b == test[j].b && test[i].c == test[j].c)
                        //if question is already present
                        ctm_i(&test[i]);    //then re-generate
            }
            printf("\n Are you ready? Press Enter key to continue. ");
            myread("",NULL);
    
            for (i = 1; i <= 5; i++)
            {
                printf(" *******************************************************************"
                    "**"
                    "***********\n");
    
                printf(" ..................................................................."
                    ".."
                    "...........\n");
            }
    
            // Take quiz
            for (i = 0; i < MAX_TESTS; i++)
                tcm_i(&test[i], i);
    
            printf(" End\n\n");
    
            bool done = false;
            bool unsure = true;
            bool showS = true;
    
            while (unsure)
            {
                unsure = false;
                puts("\n");
                if (showS)
                {
                    puts(" Enter 'S' to show results");
                }
                puts(" Enter 'P' to play another round");
                puts(" Enter 'R' to return to main menu");
                char choice;
                printf(" ");
                myread("%c", &choice);
                if (choice == 'r' || choice == 'R')
                {
                    done = true;
                }
                else
                {
    
                    ///////////////////////// Changes    /////////////
    
                    g = 0;
                    // calculate total score for current round
                    for (i = 0; i < MAX_TESTS; i++)
                    {
                        g += test[i].grade;    //add score of each question
                    }
                    allScore += g;    //add current round's score to total
                    avg = allScore / rounds;    //average of all rounds
    
                    if (g > highest)
                    {
                        highest = g;
                    }
    
                    if (g < lowest)
                    {
                        lowest = g;
                    }
    
                    if (choice == 'S' || choice == 's')
                    {
                        showS = false;
                        if (rounds == 1)
                        {
                            printf(" Final score: %d/100\n", g);    //display round score
                            printf(" ******Player: %s ******\n", name);
                        }
                        else
                        {
                            printf(" Round %d score: %d/100\n", rounds, g);    //display round score
                            printf(" Highest score: %d/100\n", highest);
                            printf(" Lowest score: %d/100\n", lowest);
                            printf(" Average score: %d/100\n", avg);
                            printf(" ******Player: %s ******\n", name);
                        }
                        unsure = true;
                    }
                    else if (choice == 'P' || choice == 'p')
                    {
                             /// nothing to be done here
                        //we will display next test
                    }
                    else
                    {
                        puts(" Invalid input!");
                        unsure = true;
                    }
    
                    ////////////////////////////////////
    
                }
            }
            if (done)
                break;
        }
    }
    
    char choiceY(char option[30])
    {
        char choice;
        myread(" %c", &choice);    //take user input
        if (choice == 'y' || choice == 'Y')
            return 'y';
    
        else
        {
            if (strcmp(option, "Quit") == 0)    //if the input is for quit check wheather entered No
            {
                if (choice == 'n' || choice == 'N')
                    return 'n';
                printf(" Invalid input! Please enter 'Y' to Quit or 'N' to return to the main menu:\n");
                printf(" ");
            }
            else
                printf("\n Invalid input! Please enter 'Y' to return to the main menu:\n");
            printf(" ");
    
            return choiceY(option);    //if enter invalid input recursive call the choiceY function
        }
        return '0';
    }
    
    int main()
    {
        char i1 = '1';
        char name[25];    // ig;
        printf(" Enter your name: ");    // Prompting the user to enter his/her name
        myread("%[^\n]%*c", name);
        printf("\n Welcome %s\n", name);
        printf("\n Press Enter key to continue.");
        myread("",NULL);
    
        printf("\n");
        while (i1 != 0)
        {
            int len = (int) strlen(name) + 1;    //to calculate the length of the input string plus the ! mark
            int welcome_len = 10;    //to calculate the length of the welcome word plus the blank spaces
            int s = 76 - len - welcome_len;    //to calculate the total no of stars to print
            int star = (s / 2);    //to calculate the no of start to print each side.
            printf(" ");
            if (s % 2 == 1)    //to check if the string is of even length or odd
            {
                for (int i = 0; i < star + 1; i++)    //if odd add 1 extra star on left side
                {
                    printf("*");
                }
            }
            else
            {
                for (int i = 0; i < star; i++)
                {
                    printf("*");
                }
            }
    
            printf(" Welcome %s! ", name);    //print the name
    
            for (int i = 0; i < star; i++)    //print *on the right side
            {
                printf("*");
            }
    
            printf("\n");
            //printf(" **********************Welcome %s! *********************\n", name);
            printf(" *                     Main Menu of Maths Quiz                            *\n");
            printf(" *1.Enter Quiz                                                             *\n");
            printf(" *2.Instructions                                                           *\n");
            printf(" *3.Quit                                                                   *\n");
            printf(" ****************************************************************************\n");
            printf(" Please choose one from 1-3:\n");
            printf(" ");
            myread("%c", &i1);
            switch (i1)
            {
                case '1':
                    printf("\n Enter Quiz:\n");
                    quiz(name);    // calling quiz function defined in file "maincode.c"
                    break;
                case '2':
                    printf("\n Instructions:\n\n");
                    display_instructions();    // calling display_instructions function defined in file "maincode.c" to display instructions of quiz
                    printf("\n Back to main menu? ");
                    printf(" Press 'Y' for Yes.\n");
                    printf(" ");
                    choiceY("Instructions");    //to validate user input
                    break;
                case '3':
                    printf(" Are you sure you want to quit this program?\n");    // Confirming if user really wants to quit
                    printf(" Press 'Y' for Yes or 'N' for No: ");
                    char choice = choiceY("Quit");    //to validate user input
                    if (choice == 'y')
                    {
                        i1 = 0;
                        printf(" Quit.\n");
                    }
                    else
                        continue;
    
                    break;
    
                default:
                    printf("\n Invalid input! Please select from options 1, 2 or 3\n\n");
            }
        }
        return 0;
    }
    The tail of the output looks like this.
    Question 10

    You have 3 attempts for this question

    64+9= 73

    Awesome! You earned 10 marks

    .................................................. ..............................
    ************************************************** ******************************
    End



    Enter 'S' to show results
    Enter 'P' to play another round
    Enter 'R' to return to main menu
    S
    Final score: 100/100
    ******Player: fred ******


    Enter 'P' to play another round
    Enter 'R' to return to main menu
    R
    ******************************* Welcome fred! ******************************
    * Main Menu of Maths Quiz *
    *1.Enter Quiz *
    *2.Instructions *
    *3.Quit *
    ************************************************** **************************
    Please choose one from 1-3:
    3
    Are you sure you want to quit this program?
    Press 'Y' for Yes or 'N' for No: Y
    Quit.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  4. #4
    Registered User
    Join Date
    Nov 2020
    Posts
    12
    TQ! I think all of my issues are resolved now.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. remove redundant white spaces in string
    By ph3s in forum C Programming
    Replies: 16
    Last Post: 03-18-2012, 07:50 PM
  2. Redundant conditional inclusion macros?
    By Aculaniveus in forum C Programming
    Replies: 3
    Last Post: 03-19-2010, 01:18 PM
  3. non-redundant use of &*
    By @nthony in forum C++ Programming
    Replies: 9
    Last Post: 11-25-2008, 02:15 PM
  4. redundant allocation
    By George2 in forum C++ Programming
    Replies: 22
    Last Post: 03-06-2008, 06:43 PM
  5. redundant function call
    By Chaplin27 in forum C++ Programming
    Replies: 4
    Last Post: 01-06-2005, 12:49 AM

Tags for this Thread