Beginning to Program in C - CS50 pset1

I've been continuing my way through Harvard's CS50 course, and have begun programming in C! Again, since I've already had quite a bit of experience programming, I've been flying through the coursework, but I've been spending plenty of time in the recommended textbooks and diving into C.

This is my first time working with a compiled language (I know, I know, JavaScript is technically a compiled language, it just happens at run time. But this is the first time I've been extensively using a language that requires compilation by me as a developer). Because of this, I've actually been drawing a lot out of the process and have actually really enjoyed working in C! Here's why:

Types are kind of awesome

Again, I know all languages have types, but C requires you to declare which types your variables are going to store. I admit it is occasionally a pain to not be able to rely on the language to discern what you want.

But it requires me as a developer to really think about what values I will be passing around and allows me to also know that a function will always return what I want it to, or the compiler will throw a fit. Which brings me to...

Compilers are pretty cool

I admit there is something pretty cool about being able to run JavaScript/Python/etc. without having to do any compiling to see your changes. But being able to know my program will run without any major errors, plus getting some linting thrown in for free if I made typos anywhere, is pretty cool.

At this point, all of the programs I'm writing compile instantly, so it's not prohibitive. I do know larger programs can take a really long time to compile, so I wonder if I would be as excited when working on larger apps. But for now I'm liking it!

JavaScript and Python grab a lot from C

I knew that a lot of compilers are written in C, and because of it's widespread usage a lot of other languages borrow from C, but it's a lot of fun as I'm working through the exercises to see just how much is the same!

JavaScript's syntax is almost identical (which is helpful). For example:

JavaScript

function someFunction(x) {
    for (var i = 0; i < x; i++) {
        console.log(i);
    }
}

C

void someFunction(int x)
{
    for (int i = 0; i < x; i++)
    {
        printf("%i", i);
    }
}

Other than having to declare some types, and do some replacement in strings (which you might recognize is very similar to Python, it's super similar!

Some of my first programs

Here are a few of my first programs in C that required me to go beyond the usual Hello World type of exercise.

Mario.c

// Hacker edition of Mario

#include <cs50.h>
#include <stdio.h>

int main(void)
{
    int height, i, j, k;
    
    // Get height of pyramid from user
    do
    {
        printf("Height: ");
        height = GetInt();
    }
    while (height < 0 || height > 23);
    
    // Print lines
    for (i = 1; i <= height; i++)
    {
        // Print spaces
        for (j = 0; j < (height - i); j++)
        {
            printf(" ");
        }
        
        // print hashes
        for (k = 0; k < i; k++)
        {
            printf("#");
        }
        
        printf("  ");
        
        // print hashes again
        for (k = 0; k < i; k++)
        {
            printf("#");
        }
        
        printf("\n");
    }
    
    return 0;
}

This was a fun little program that required getting some user input and then outputting a "pyramid" like the one in the first level of Mario.

Greedy.c

// Program to determine the minimum number of coins needed when making change

#include <cs50.h>
#include <math.h>
#include <stdio.h>

int main(void)
{
    float change;
    int coins, cents;
	
    printf("O hai! ");
	
    // Get change owed, must be positive
    do
    {
        printf("How much change is owed?\n");
        change = GetFloat();
	}
    while (change < 0);
	
    // Avoid imprecision by converting to cents
    cents = (int) round(change * 100);
	
    // Initialize coins
    coins = 0;
	
    // Modulo math - Quarters
    coins += cents / 25;
    cents %= 25;
	
    // Modulo - Dimes
    coins += cents / 10;
    cents %= 10;
	
    // Modulo - Nickels
    coins += cents / 5;
    cents %= 5;
	
    // Pennies
    coins += cents;
	
    // Print Result
    printf("%i\n", coins);
	
    return 0;
}

This one asked how much change is needed, convert to cents (and ints to avoid imprecision with floats), and then determine the least amount of coins required using modulo math.

Credit.c

// Program to check if a credit card number is valid

#include <cs50.h>
#include <stdbool.h>
#include <stdio.h>

int main(void)
{
    long long   card_number, orig_number;
    string      card_type;
    int         digits = 0, temp = 0, current = 0, 
                even_digits = 0, odd_digits = 0, total_sum = 0;
    bool        is_even = false;
    
    // Get Card number
    do
    {
        printf("Number: ");
        card_number = GetLongLong();
    }
    while (card_number < 0);
    
    // Save card number for later check;
    orig_number = card_number;
    
    // Process Card Number
    while (card_number != 0)
    {
        // Get last digit of number
        current = (card_number % 10);
        
        // Increase number of digits in card number
        digits += 1;
        
        // Check if digit is even or odd and increase appropriate sum
        if (is_even == true)
        {
            // Multiply digit by 2
            temp = current * 2;
            
            // Add each digit of product
            while (temp != 0)
            {
                even_digits += temp % 10;
                temp /= 10;
            }
            
            // Tell program next digit is odd
            is_even = false;
        }
        else
        {
            odd_digits += current;
            
            // Tell program next digit is even
            is_even = true;
        }
        
        // Remove last digit and continue
        card_number /= 10;
    }
    
    // Get total sum
    total_sum = even_digits + odd_digits;
    
    // Check sum and card type by first digit
    if (total_sum % 10 == 0)
    {
        // Check AMEX
        if (digits == 15)
        {   
            if ((orig_number / (long long) 10E12) == 34 || 
                (orig_number / (long long) 10E12) == 37)
            {
                card_type = "AMEX";
            }
            else
            {
                card_type = "INVALID";   
            }
        }
        else if (digits == 16)
        {
            // Check Mastercard
            if ((orig_number / (long long) 10E13) >= 51 && 
                (orig_number / (long long) 10E13) <= 55)
            {
                card_type = "MASTERCARD";
            }
            // Check some Visas
            else if ((orig_number / (long long) 10E14) == 4) 
            {
                card_type = "VISA";
            }
            else
            {
                card_type = "INVALID";   
            }
        }
        // Check Visa
        else if (digits == 13)
        {
            if ((orig_number / (long long) 10E11) == 4)
            {
                card_type = "VISA";
            }
            else
            {
                card_type = "INVALID";   
            }                
        }
        else
        {
            card_type = "INVALID";
        }
    }
    else
    {
        card_type = "INVALID"; 
    }
    
    // Print result
    printf("%s\n", card_type);
    
    return 0;
}

I'm not going to lie, this one was a lot harder... This one required me to check credit card numbers against an algorithm to not only discern if it was a valid number, but also what type of card it was! There might be a more elegant solution out there, but I at least got it working.

Getting "closer to the metal"

So, as you can tell, I'm really enjoying my foray into programming in C. It's not always the most concise or easy language to program in, but I feel like I'm really learning a lot about what exactly I'm doing when I program commands for my computer to execute.

While I probably won't become a full-time C developer anytime soon, I've really enjoyed the challenge. If you have been making good headway in languages like Python or JavaScript, I really think you should give C a try as an exercise. I think you'll learn a lot too!