Thread: New C Programmer, Struggles with nested if Statements and Loops

  1. #1
    Registered User
    Join Date
    Feb 2017
    Posts
    27

    New C Programmer, Struggles with nested if Statements and Loops

    So, I'm a 1st year CS student who is learning C for the first time. The jump from Python to Java was already a hurdle for me that I'm slowly starting to overcome, but learning C has been a struggle.

    My first assignment is to make a program that takes in user input to convert measurements of their choice. 1 is for Kilogram - Pound, 2 is for Litre - Gallon, etc., with 5 to exit.

    However, I'm struggling to even code the first option, let alone surrounding it all in a loop, and to code for invalid user input.

    Here is what I have so far:

    Code:
    int main(void){
        // initialize variables
        int convertOption;
        char directionChar;
        float initialMeasure, finalMeasure;
    
    
        // prompt for user input
        printf("Enter '1-4' depending on the conversion you wish to perform, or '5' to exit: ");
        scanf("%d", &convertOption);
        printf("You entered the integer %d\n", convertOption);
    
    
        if (convertOption == 1){
            printf("Enter 'K' for Kilograms to Pounds, or 'P' for Pounds to kilograms: ");
            scanf(" %c", &directionChar);
            printf("You entered the character %c\n", directionChar);
    
    
            if (directionChar == "K"){
                printf("Please enter the number of kilograms: ");
                scanf("%f", &initialMeasure);
                finalMeasure = initialMeasure / 2.2;
    
    
                printf("The equivalent number of pounds is: %.1f\n", finalMeasure);
            }
        }
        return 0;
    }
    However, based on output, it doesn't make it to the 2nd if statement, or fails to pass it, and I'm not sure why this is the case.

    Any help would be appreciated, thanks!

  2. #2
    Registered User
    Join Date
    Feb 2017
    Posts
    27
    Never mind, found out the issue.

    Supposed to use single quotes instead of double quotes around 'K'.

    If I have any further questions I guess I will reply here

  3. #3
    Registered User
    Join Date
    Feb 2017
    Posts
    27

    Handling Alphabetical Input

    So, my program seems to be running correctly now, with one exception:

    Code:
    #include <stdio.h>
    
    int main(void)
    {
        // initialize variables
        int convertOption;
        char directionChar;
        float initialMeasure, finalMeasure;
    
    
        // prompt for user input
        while(convertOption != 5){
            convertOption = 0;
            printf("Enter '1-4' depending on the conversion you wish to perform, or '5' to exit: ");
            scanf("%d", &convertOption);
    
    
            if (convertOption == 1){
                printf("Enter 'K' for kilograms to pounds, or 'P' for pounds to kilograms: ");
                scanf(" %c", &directionChar);
    
    
                if (directionChar == 'K'){
                    printf("Please enter the number of kilograms: ");
                    scanf("%f", &initialMeasure);
                    finalMeasure = initialMeasure * 2.2;
                    printf("The equivalent number of pounds is: %.1f\n", finalMeasure);
                }
    
    
                else if (directionChar == 'P'){
                    printf("Please enter the number of pounds: ");
                    scanf("%f", &initialMeasure);
                    finalMeasure = initialMeasure / 2.2;
                    printf("The equivalent number of kilograms is: %.1f\n", finalMeasure);
                }
            }
    
    
            else if (convertOption == 2){
                printf("Enter 'L' for litres to gallons, or 'G' for gallons to litres: ");
                scanf(" %c", &directionChar);
    
    
                if (directionChar == 'L'){
                    printf("Please enter the number of litres: ");
                    scanf("%f", &initialMeasure);
                    finalMeasure = initialMeasure / 3.79;
                    printf("The equivalent number of gallons is: %.1f\n", finalMeasure);
                }
    
    
                else if (directionChar == 'G'){
                    printf("Please enter the number of gallons: ");
                    scanf("%f", &initialMeasure);
                    finalMeasure = initialMeasure * 3.79;
                    printf("The equivalent number of litres is: %.1f\n", finalMeasure);
                }
            }
    
    
            else if (convertOption == 3){
                printf("Enter 'C' for centimetres to inches, or 'I' for inches to centimetres: ");
                scanf(" %c", &directionChar);
    
    
                if (directionChar == 'C'){
                    printf("Please enter the number of centimetres: ");
                    scanf("%f", &initialMeasure);
                    finalMeasure = initialMeasure / 2.54;
                    printf("The equivalent number of inches is: %.1f\n", finalMeasure);
                }
    
    
                else if (directionChar == 'I'){
                    printf("Please enter the number of inches: ");
                    scanf("%f", &initialMeasure);
                    finalMeasure = initialMeasure * 2.54;
                    printf("The equivalent number of centimetres is: %.1f\n", finalMeasure);
                }
            }
    
    
             else if (convertOption == 4){
                printf("Enter 'C' for Celsius to Fahrenheit, or 'F' for Fahrenheit to Celsius: ");
                scanf(" %c", &directionChar);
    
    
                if (directionChar == 'C'){
                    printf("Please enter the degrees in Celsius: ");
                    scanf("%f", &initialMeasure);
                    finalMeasure = ((initialMeasure * 9) / 32) + 32;
                    printf("The equivalent temperature in Fahrenheit is: %.1f\n", finalMeasure);
                }
    
    
                else if (directionChar == 'F'){
                    printf("Please enter the degrees in Fahrenheit: ");
                    scanf("%f", &initialMeasure);
                    finalMeasure = ((initialMeasure - 32) * 5) / 9;
                    printf("The equivalent temperature in Celsius is: %.1f\n", finalMeasure);
                }
            }
    
    
            else if (convertOption == 5){
                printf("Thanks for using my program!");
                break;
            }
    
    
            else{
                printf("Sorry, that is not a valid conversion option.  Please choose 1-5.");
                convertOption = 0;
            }
        }
    
    
        return 0;
    }
    The program runs infinitely when the user enters a letter instead of a number.

    Entering invalid numbers (i.e. <5) causes the program to reprompt the user correctly, however inputting letters causes the program to infinitely loop.

    What causes this? Is there an easy fix?

    Also, is there a way in general to use functions to make my code more efficient? I don't like how it's just one giant function.

  4. #4
    Registered User
    Join Date
    Jun 2015
    Posts
    1,640
    Uninitialized variables can contain any value, so it's possible that convertOption starts with the value 5 which would stop your loop from running at all. Initialize it to 0 (or any non-5 value) before the loop. Your other initializations to 0 are not really needed.

    You should be printing a menu of the options, otherwise how do I know what 1, 2, 3, 4 mean?

    A switch would be better than if/else if's here.

    scanf returns the number of conversions that it was able to complete. You're asking it to perform 1 conversion, so it will return 1 if it was able to do that. Therefore you can test for a non-numeric input like this:
    Code:
        int convertOption = 0;
    
        while (convertOption != 5) {
            printf("Enter 1 to 4 blah blah blah\n");
            if (scanf("%d", &convertOption) != 1) { // non-numeric input
                while (getchar() != '\n')  // eat the line
                    ;
                continue;  // redo loop
            }
            
            switch (convertOption) {
            case 1:
                convert_KG_Pounds();
                break;
            case 2:
                convert_Litres_Gallons();
                break;
            // ...
            case 5:
                // don't need to do anything here
                break;
            default:
                // invalid number
            }
        }
    In general, scanf is fraught with dangers. You'd have to check for bad or extraneous inputs with all your scanf's. It is better to read an entire line of input with fgets (into a relatively large buffer, say 500) and then use sscanf on that string.

    Instead of completely separate functions, it may be possible to generalize the conversion to one function. It might be called something like this:
    Code:
    convert("Kilograms",   "Pounds",     0.45,     0);
    convert("Liters",      "Gallons",    3.79,     0);
    convert("Centimeters", "Inches",     2.54,     0);
    convert("Celsius",     "Fahrenheit", 5.0/9.0, 32);
    BTW, there's an error in your Celsius to Fahrenheit conversion!

  5. #5
    Registered User
    Join Date
    Feb 2017
    Posts
    27

    Thanks <3

    Hey algorism, thanks so much for the help!

    Here's where my code sits after editing and fixing that typo in my Celsius conversion:

    Code:
    #include <stdio.h>
    
    float convert_KtoP();
    float convert_LtoG();
    float convert_CtoI();
    float convert_CtoF();
    
    
    int main(void){
    
    
        char menuOption = 0;
    
    
        while (menuOption != 5){
            printf("Main menu: \n");
            printf("1: Kilograms - Pounds \n");
            printf("2: Litres - Gallons \n");
            printf("3: Centimetres - Inches \n");
            printf("4: Celsius - Fahrenheit \n");
            printf("5: Exit program. \n");
            printf("Please enter (1-5), corresponding to the options above. ");
            if (scanf("%d", &menuOption) != 1) {
                while (getchar() != '\n');
                continue;
            }
    
    
        switch(menuOption){
        case 1:
            convert_KtoP();
            break;
        case 2:
            convert_LtoG();
            break;
        case 3:
            convert_CtoI();
            break;
        case 4:
            convert_CtoF();
            break;
        case 5:
            printf("Thank you for using my program!\n");
            break;
        default:
            printf("Sorry, that is not a valid option.\n");
            break;
        }
        }
        return 0;
    }
    
    
    float convert_KtoP(){
        char directionChar;
        float initialMeasure, finalMeasure;
    
    
        printf("Enter 'K' for kilograms to pounds, or 'P' for pounds to kilograms: ");
        scanf(" %c", &directionChar);
    
    
        if (directionChar == 'K'){
            printf("Please enter the number of kilograms: ");
            scanf("%f", &initialMeasure);
            finalMeasure = initialMeasure * 2.2;
            printf("The equivalent number of pounds is: %.2f\n\n", finalMeasure);
        }
    
    
        else if (directionChar == 'P'){
            printf("Please enter the number of pounds: ");
            scanf("%f", &initialMeasure);
            finalMeasure = initialMeasure / 2.2;
            printf("The equivalent number of kilograms is: %.2f\n\n", finalMeasure);
        }
        return 0;
    }
    
    
    float convert_LtoG(){
        char directionChar;
        float initialMeasure, finalMeasure;
    
    
        printf("Enter 'L' for litres to gallons, or 'G' for gallons to litres: ");
        scanf(" %c", &directionChar);
    
    
        if (directionChar == 'L'){
            printf("Please enter the number of litres: ");
            scanf("%f", &initialMeasure);
            finalMeasure = initialMeasure / 3.79;
            printf("The equivalent number of gallons is: %.2f\n\n", finalMeasure);
        }
    
    
        else if (directionChar == 'G'){
            printf("Please enter the number of gallons: ");
            scanf("%f", &initialMeasure);
            finalMeasure = initialMeasure * 3.79;
            printf("The equivalent number of litres is: %.2f\n\n", finalMeasure);
        }
    }
    
    
    float convert_CtoI(){
        char directionChar;
        float initialMeasure, finalMeasure;
    
    
        printf("Enter 'C' for centimetres to inches, or 'I' for inches to centimetres: ");
        scanf(" %c", &directionChar);
    
    
        if (directionChar == 'C'){
            printf("Please enter the number of centimetres: ");
            scanf("%f", &initialMeasure);
            finalMeasure = initialMeasure / 2.54;
            printf("The equivalent number of inches is: %.2f\n\n", finalMeasure);
        }
    
    
        else if (directionChar == 'I'){
            printf("Please enter the number of inches: ");
            scanf("%f", &initialMeasure);
            finalMeasure = initialMeasure * 2.54;
            printf("The equivalent number of centimetres is: %.2f\n\n", finalMeasure);
        }
    }
    
    
    float convert_CtoF(){
        char directionChar;
        float initialMeasure, finalMeasure;
    
    
        printf("Enter 'C' for Celsius to Fahrenheit, or 'F' for Fahrenheit to Celsius: ");
        scanf(" %c", &directionChar);
    
    
        if (directionChar == 'C'){
            printf("Please enter the degrees in Celsius: ");
            scanf("%f", &initialMeasure);
            finalMeasure = ((initialMeasure * 9) / 5) + 32;
            printf("The equivalent temperature in Fahrenheit is: %.2f\n\n", finalMeasure);
        }
    
    
        else if (directionChar == 'F'){
            printf("Please enter the degrees in Fahrenheit: ");
            scanf("%f", &initialMeasure);
            finalMeasure = ((initialMeasure - 32) * 5) / 9;
            printf("The equivalent temperature in Celsius is: %.2f\n\n", finalMeasure);
        }
    }
    Any other advice to make it more efficient is fine, though I think this is suitable for the purposes of this part of my assignment.

    Thanks so much!

  6. #6
    Registered User
    Join Date
    Jun 2015
    Posts
    1,640
    Looking good! A few tips:

    menuOption should be an int, which will match the %d format specifier in the scanf.

    Your conversion functions should have a void return type since they don't return anything, and remove the return 0 from convert_KtoP. Remember to change your prototypes, too.

    Your switch statement should be indented.

    You might want to use toupper on directionChar so it can be entered in either lowercase or uppercase:
    Code:
        scanf(" %c", &directionChar);
        directionChar = toupper(directionChar);
    You need to include <ctype.h> for toupper's prototype.

  7. #7
    Registered User
    Join Date
    Feb 2017
    Posts
    27

    One final issue

    Hey algorism (and anyone else checking this post out)!

    I implemented the changes you suggested, and everything is still working great for the most part! It compiles correctly on Unix (the end goal), which is perfect.

    Code:
    #include <stdio.h>
    
    void convert_KtoP(void);
    void convert_LtoG(void);
    void convert_CtoI(void);
    void convert_CtoF(void);
    
    
    int main(void){
    
    
        char menuOption = 0;
    
    
        while (menuOption != '5'){
            printf("Main menu: \n");
            printf("1: Kilograms - Pounds \n");
            printf("2: Litres - Gallons \n");
            printf("3: Centimetres - Inches \n");
            printf("4: Celsius - Fahrenheit \n");
            printf("5: Exit program. \n");
            printf("Please enter (1-5), corresponding to the options above. ");
            scanf(" %c", &menuOption);
            switch(menuOption){
                case '1':
                    convert_KtoP();
                    break;
                case '2':
                    convert_LtoG();
                    break;
                case '3':
                    convert_CtoI();
                    break;
                case '4':
                    convert_CtoF();
                    break;
                case '5':
                    printf("Thank you for using my program!\n");
                    break;
                default:
                    printf("Sorry, that is not a valid option.\n");
                    break;
        }
        }
        return 0;
    }
    
    
    void convert_KtoP(void){
        char directionChar;
        float initialMeasure, finalMeasure;
    
    
        printf("Enter 'K' for kilograms to pounds, or 'P' for pounds to kilograms: ");
        scanf(" %c", &directionChar);
    
    
        if (directionChar == 'K'){
            printf("Please enter the number of kilograms: ");
            scanf("%f", &initialMeasure);
            finalMeasure = initialMeasure * 2.2;
            printf("The equivalent number of pounds is: %.2f\n\n", finalMeasure);
        }
    
    
        else if (directionChar == 'P'){
            printf("Please enter the number of pounds: ");
            scanf("%f", &initialMeasure);
            finalMeasure = initialMeasure / 2.2;
            printf("The equivalent number of kilograms is: %.2f\n\n", finalMeasure);
        }
    }
    
    
    void convert_LtoG(void){
        char directionChar;
        float initialMeasure, finalMeasure;
    
    
        printf("Enter 'L' for litres to gallons, or 'G' for gallons to litres: ");
        scanf(" %c", &directionChar);
    
    
        if (directionChar == 'L'){
            printf("Please enter the number of litres: ");
            scanf("%f", &initialMeasure);
            finalMeasure = initialMeasure / 3.79;
            printf("The equivalent number of gallons is: %.2f\n\n", finalMeasure);
        }
    
    
        else if (directionChar == 'G'){
            printf("Please enter the number of gallons: ");
            scanf("%f", &initialMeasure);
            finalMeasure = initialMeasure * 3.79;
            printf("The equivalent number of litres is: %.2f\n\n", finalMeasure);
        }
    }
    
    
    void convert_CtoI(void){
        char directionChar;
        float initialMeasure, finalMeasure;
    
    
        printf("Enter 'C' for centimetres to inches, or 'I' for inches to centimetres: ");
        scanf(" %c", &directionChar);
    
    
        if (directionChar == 'C'){
            printf("Please enter the number of centimetres: ");
            scanf("%f", &initialMeasure);
            finalMeasure = initialMeasure / 2.54;
            printf("The equivalent number of inches is: %.2f\n\n", finalMeasure);
        }
    
    
        else if (directionChar == 'I'){
            printf("Please enter the number of inches: ");
            scanf("%f", &initialMeasure);
            finalMeasure = initialMeasure * 2.54;
            printf("The equivalent number of centimetres is: %.2f\n\n", finalMeasure);
        }
    }
    
    
    void convert_CtoF(void){
        char directionChar;
        float initialMeasure, finalMeasure;
    
    
        printf("Enter 'C' for Celsius to Fahrenheit, or 'F' for Fahrenheit to Celsius: ");
        scanf(" %c", &directionChar);
    
    
        if (directionChar == 'C'){
            printf("Please enter the degrees in Celsius: ");
            scanf("%f", &initialMeasure);
            finalMeasure = ((initialMeasure * 9) / 5) + 32;
            printf("The equivalent temperature in Fahrenheit is: %.2f\n\n", finalMeasure);
        }
    
    
        else if (directionChar == 'F'){
            printf("Please enter the degrees in Fahrenheit: ");
            scanf("%f", &initialMeasure);
            finalMeasure = ((initialMeasure - 32) * 5) / 9;
            printf("The equivalent temperature in Celsius is: %.2f\n\n", finalMeasure);
        }
    }
    The one exception I failed to account for however is when the user inputs multiple numbers (i.e. '123'); my program currently takes in the first char and reads it as a '1', and progresses to the switch '1' case.

    Is there an easy & efficient fix for this? scanf seems to be problematic in this regard, but we haven't learned any other method.

    Do I have to use type conversion and convert it into an int?

  8. #8
    Registered User
    Join Date
    Jun 2015
    Posts
    1,640
    Just do what I suggested and make menuOption an int (and use the %d format in the scanf).

  9. #9
    Registered User
    Join Date
    Feb 2017
    Posts
    27
    Hey algorism,

    Unfortunately, I'm required to use characters :\

    Looking at converting menuOption into an int after reading it, but I'm not sure how that would work with letters and other invalid characters.

  10. #10
    Registered User
    Join Date
    Jun 2015
    Posts
    1,640
    In that case, simply eat the excess characters like this:
    Code:
    scanf(" %c", &menuOption);
    while (getchar() != '\n')
        ;
    And if you'd like to accept lowercase letters for the conversion options but don't want to use toupper, you can do the following for all the ifs and elses:
    Code:
    if (directionChar == 'K' || directionChar == 'k'){

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Help with nested if statements
    By sean_cantab in forum C++ Programming
    Replies: 7
    Last Post: 05-14-2016, 09:22 PM
  2. Breaking out of a While loop with Nested If statements
    By tmac619619 in forum C Programming
    Replies: 4
    Last Post: 03-14-2014, 01:34 PM
  3. Help with nested loops(im a new programmer)
    By cuo741 in forum C++ Programming
    Replies: 3
    Last Post: 06-29-2010, 04:57 AM
  4. nested for statements
    By EvilPickles in forum C++ Programming
    Replies: 5
    Last Post: 07-01-2006, 05:36 AM
  5. Nested if statements
    By jdinger in forum C Programming
    Replies: 3
    Last Post: 02-11-2002, 01:31 PM

Tags for this Thread