Scanf skips variable and reuses old one

Viewed 132

I'm going through the C Programming Absolute Beginners Guide 3rd edition to learn programming and I'm having issues at Chapter8ex2.c where my program gets the cost and then is supposed to get the topping. It instead passes by that and reuses the first variable instead of using the correct second one.

here is my code

// This is a sample program that asks users for some basic data and prints it on 
// the screen in order to show what was entered
#include <stdio.h>

int main()
{
    char topping[24];
    int slices;
    int month, day, year;
    float cost;

    // The first scanf will look for a floating-point variable, the cost of the pizza
    // If the user doesn't enter a $ before the cost, it could cause problems

    printf("How much does a pizza cost in your area?");
    printf("enter as $XX.XX)\n");
    scanf(" $%f", &cost);

    // The pizza topping is a string, so your scanf doesn't need an &

    printf("What is your favorite one-word pizza topping?\n");
    scanf(" %s", topping);

    printf("How many slices of %s pizza", topping);
    printf("can you eat in one sitting?\n");
    scanf("%i", &slices);

    printf("What is today's date (enter it in XX/XX/XX format).\n");
    scanf(" %i/%i/%i", &month, &day, &year);

    printf("\n\nWhy not treat yourself to dinner on %i/%i/%i", month, day, year);
    printf("\nand have %i slices of %s pizza!\n", slices, topping);
    printf("It will only cost you $%.2f!\n\n\n", cost);

    return(0); 
}

here is the code being run

How much does a pizza cost in your area?enter as $XX.XX)
15.00
What is your favorite one-word pizza topping?
How many slices of 15.00 pizzacan you eat in one sitting?
1 Answers

scanf presents some problems. Consider using fgets for all input and parse as needed.
When scanf fails, the problematic input is left in the input stream and can cause subsequent scans to fail or behave unexpectedly. fgets will read and remove up to the size of the buffer from the input stream.
Parsing the input can be accomplished through numerous functions. sscanf and strcspn are used here but many others are available. strspn, strtod, strtol, strchr, strstr, strpbrk, strtok, strsep and more.
Avoid using %i especially for dates. An input of 08 or 09 for day or month will cause trouble. The leading zero tells %i to process an octal ( base 8) value, but 8 and 9 are not valid octal digits.
The do{}while(); allow for repeated inputs until acceptable results. The parsing here has limits but could be improved.

#include <stdio.h>
#include <string.h>

int main()
{
    char line[100] = "";
    char topping[100] = "";
    int result = 0;
    int slices = 0;
    int month = 0;
    int day = 0;
    int year = 0;
    float cost;

    do {
        printf ( "How much does a pizza cost in your area?");
        printf ( "enter as $XX.XX)\n");
        if ( ! fgets ( line, sizeof line, stdin)) {
            fprintf ( stderr, "fgets EOF\n");
            return 1;
        }
        result = sscanf ( line, " $%f", &cost);
        if ( 0 == result) {
            printf ( "be sure to use a $\n");
        }
    } while ( 1 != result);

    printf ( "What are your favorite pizza toppings?\n");
    if ( ! fgets ( topping, sizeof topping, stdin)) {
        fprintf ( stderr, "fgets EOF\n");
        return 1;
    }
    topping[strcspn ( topping, "\n")] = 0;//remove newline

    do {
        printf ( "How many slices of %s pizza", topping);
        printf ( " can you eat in one sitting?\n");
        if ( ! fgets ( line, sizeof line, stdin)) {
            fprintf ( stderr, "fgets EOF\n");
            return 1;
        }
        result = sscanf ( line, "%d", &slices);
        if ( 0 == result) {
            printf ( "enter a number\n");
        }
    } while ( 1 != result);

    do {
        printf ( "What is today's date (enter it in XX/XX/XX format).\n");
        if ( ! fgets ( line, sizeof line, stdin)) {
            fprintf ( stderr, "fgets EOF\n");
            return 1;
        }
        result = sscanf ( line, "%d /%d /%d", &month, &day, &year);
        if ( 3 != result) {
            printf ( "be sure to use a / between numbers\n");
        }
    } while ( 3 != result);

    printf ( "\n\nWhy not treat yourself to dinner on %i/%i/%i", month, day, year);
    printf ( "\nand have %i slices of %s pizza!\n", slices, topping);
    printf ( "It will only cost you $%.2f!\n\n\n", cost);

    return(0);
}
Related