DEV Community

Shin
Shin

Posted on • Updated on

// c-ntax, c-lections, and the basics of c

I've quite an experience with programming particularly in high-level languages like Python and Javascript with the exception of Java, but learning C is something different in terms of how it works on a deeper level. Similar to Java, the program must be compiled first before you can run it. Some syntax from Java and C are also similar so there's a degree of familiarity that I am comfortable with, but there are also vastly different things as well which this post will tackle.

With that said, my journey with C have started with this problem set:

"Create a C program that will compute for the body-mass index of a given height and weight. After calculating the BMI, the program will also tell under which category (underweight, normal weight, overweight, or obese) it belongs to. The user will be given two (2) choices before entering the height and weight (those choices being metric and imperial measurements). The menu must loop repeatedly until the exit option is entered. Make sure to have proper error prompts."

Breaking the problem down, there are several things that are necessary for the program:

  • prompts and user input
  • selection for the two modes of calculating BMI (imperial and metric)
  • selection for the ranged categories the BMI belong to
  • the menu to loop indefinitely until the exit option is selected; and finally
  • error prompts for invalid inputs for
    • options that were not listed
    • weight and height being 0 and less
    • string inputs

Before I started coding, I wanted to list the possible variables that I will use. Since I have a menu, I would need an int option variable to store the user's choice. I would also need the variables weight, height, and BMI for the calculations, all of which are in float.

The Prompts and Inputs
Printing and scanning for inputs are one of the building blocks of any programming language, and printing/scanning in C works slightly differently from other languages.

For C, I need to import the library before I can take inputs first, and this is done by appending #include <stdio.h> on the first line, stdio.h being the library consisting the scanner.

I've added prompts that ask the user to select between the calculating options by using printf and take the input using scanf. That said, printing and scanning in C is a lot more nuanced, for one, to be able to scan (and print) variables, I have to put the format specifier of the variable. Since I've decided to use int data type for my option variable, I should use the %d specifier with scanf (and later on printf).

So far this is what I have:

#include <stdio.h>

int main() {
    int option;
    float weight, height, BMI;

    // MENU AND USER INPUT
    printf("\nSelect Mode:\n"
           "(1) Enter in kilogram and centimeters\n"
           "(2) Enter in pounds and feet\n"
           "Choice: ");
    scanf("%d", &option);

    return 0;
}
Enter fullscreen mode Exit fullscreen mode

The Selections
Next up are the selection statements. After the user selects the mode, the value is stored in option. I decided to use a switch statement for this, with case: 1 being the metric measurements and case: 2 being the imperial measurements. The formula for solving BMI changes with the mode being used, so this will be the body of my cases.
Metric System: BMI = weight / (height * height)
Imperial System: BMI = (703 * weight) / (height * height)

Aside from that, both cases will ask the user for the height and weight measurements. The only difference would be the user must provide the measurements according to the selected mode.

switch (option) {
    case 1:
        printf("\nEnter weight in kg: ");
        scanf("%f", &weight);
        printf("Enter height in cm: ");
        scanf("%f", &height);

        // BMI CALCULATION
        BMI = weight / (height * height);
        printf("\nYour BMI is: %f\n", BMI);
        break;
    case 2:
        printf("\nEnter weight in lbs: ");
        scanf("%f", &weight);
        printf("Enter height in in: ");
        scanf("%f", &height);

        // BMI CALCULATION
        BMI = (703 * weight) / (height * height);
        printf("\nYour BMI is: %f\n", BMI);
        break;
    default:
        break;
}
Enter fullscreen mode Exit fullscreen mode

I also need a selection for the BMI categories. Since the conditions for the categories are ranged, using a chain of if-else statements would be the appropriate choice. Using the basic 4-tier BMI table as the basis, this is what I had:

// BMI CATEGORIES
if (BMI < 18.5) {
    printf("Your BMI category is: Underweight\n"); 
} else if (BMI >= 18.5 && BMI < 25.0) {
    printf("Your BMI category is: Normal\n"); 
} else if (BMI >= 25.0 && BMI < 30.0) {
    printf("Your BMI category is: Overweight\n"); 
} else if (BMI >= 30) {
    printf("Your BMI category is: Obese\n"); 
}
Enter fullscreen mode Exit fullscreen mode

The Loops
This problem requires me to have a menu that will loop on and on until the exit option is selected. To do this, I started modifying the menu by putting it inside a while loop. I've made the loop run indefinitely by making the condition 1 which the loop reads as true. The only way this loop ends is by adding an if-else statement that breaks the loop if the option is equal 0.

while (1) {
    // MENU AND USER INPUT
    printf("\nSelect Mode:\n"
           "(1) Enter in kilogram and centimeters\n"
           "(2) Enter in pounds and feet\n"
           "(0) Exit\n"
           "Choice: ");
    scanf("%d", &option);

    if (option != 0) {
        // THE SWITCH STATEMENT COMES HERE
    } else {
        break;
    }
}
Enter fullscreen mode Exit fullscreen mode

The Input Validation and Error Prompts
The last thing that I need is to add validation for the user inputs. For the menu, there are two things to address:

  • numerical inputs that are not listed as an option
  • string inputs

I started by putting what I already have in the while loop in an if-else statement that prints out an error prompt if option was less than 0 or greater than 2, preventing the user from entering numerical inputs that are explicitly not the three allowed options.

if (option < 0 || option > 2) {
    printf("Error: please enter a number from 0 to 2. \n");
} else {
    if (option != 0) {
        // THE SWITCH STATEMENT COMES HERE
    } else {
        break;
    }
}
Enter fullscreen mode Exit fullscreen mode

However, I realized that this doesn't account for floating-point numbers between 0 to 2. Apparently, C programs only show warnings when there is a type mismatch and still compile and run regardless, as opposed to other programming languages. This made debugging input mismatches difficult since the program doesn't show any problems during runtime as warnings only show up before compilation.

The way input works in C is by input stream and the way I understand is when the user inputs various things like text, characters, numbers, and even the newline, the program reads everything as a single giant string that is split with spaces for every variable. This string is only cut when a period is typed.

Because of the decimal input being placed in an int data type, it results in this weird behavior where the input is split into two input streams by the decimal point. The whole number portion of the input is taken by the variable and the remainder is placed on the next variable, ultimately skipping the supposed scanf for that variable.

int x, y;

printf("Test: ");
scanf("%d", &x);
printf("Test: \n");
scanf("%d", &y);
Enter fullscreen mode Exit fullscreen mode

For instance, if I enter 1.5 in the first prompt, only 1 would be accepted in x while the decimal is interpreted as garbage and placed in y, preventing the user from entering a different value.

To deal with this, I added a helper float temp variable that takes whatever input and then I typecasted it to int before storing in option to kind of remove the decimal portion of the input. Not the best workaround by any means but it works with what I know so far.

Input validation for strings works in somewhat the same way. Strings typed into the scanf are interpreted as garbage when placed in an int variable. Regardless, because of the user pressing Enter, a newline character gets added to the input stream, also preventing the user from entering a correct value. To fix this, I added the following line every time the validation condition detects that the input is invalid:

while ((getchar()) != '\n');
Enter fullscreen mode Exit fullscreen mode

Essentially, the line continuously looks at the stream until a newline is found, then removing it to "clean" the stream for new input.

Conclusion
Overall, I have learned a lot about how C works in relation to what I already know. Of course, a good fraction of it is the fundamentals, like the data types, general structure of the main, selections and comparisons, operations, among many others. The one thing that stood out to me the most however is the way C handles user input. I found this to be quite difficult since it's different from what I am used to, like finding out that C programs do not detect type mismatches which was quite strange for me. And understandably, it should be as any first step to anything. I ended up poking around to see which works and which doesn't, and it definitely helped me discover things on my own.

Discussion (0)