Post

🏫 [CS50x 2025] Lecture 1 Note

🏫 [CS50x 2025] Lecture 1 Note

C - single quote VS double quote

In C, when you’re working with strings, you must use double quotes:

1
2
printf("hello, world"); // ✅ correct
printf('hello, world'); // ❌ nope, this throws an error

That’s because:

  • 'a' (single quotes) = a single character literal, of type char
    → like: 'H', 'e', '1'
  • "hello" (double quotes) = a string literal, of type char[]

In contrast:

  • JavaScript is chill-you can use 'single' or "double" quotes for strings
  • Python is also relaxed-both work fine too, even '''triple quotes''' for multi-line strings

But C? That bad boy is old school and picky af. If you give it 'hello', it’ll be like “babe, that ain’t a char, that’s a whole-ass string, I’m out 🫥.”

So just remember:

💬 JS & PY: use either ' or "
🔐 C: must use " for strings
'a' in C is fine but only for single characters

get_string() from cs50 VS scanf()

get_string() is a function provided by CS50 to make things easier for beginners. Normally, in standard C, there’s no get_string() function. You’d need to manually handle things like string input and memory allocation. But CS50 took care of that for you, so you don;t have to worry about complex details when you’re just getting started. It’s like training wheels for your C journey! 🚴‍♀️✨


standard C 🧐

In standard C, if you wanted to get a string (like your name), you’d need to do it manually using scanf(). The code:

1
2
char answer[100];       // Declare an array to store your string
scanf("%s", answer);    // Get user input and store it in the 'answer' array

Here’s what this does:

  1. char answer[100];
    • This line creates an array of characters, called answer, that can hold up to 99 characters (plus one extra space for the special “null terminator” \0 that marks the end of a string in C).
  2. scanf("%s", answer);
    • This line tells C to read input from the user (a string) and store it in the answer array. The %s format specifier is for reading a string of characters.

But there’s a catch!

  • scanf("%s", answer) won’t handle spaces. So, if you enter a name like John Doe, it will only capture John-it stops at the first space. 😬
  • It also doesn’t check for memory overflow, so you have to manually manage the size of answer[] and ensure you don’t go beyond its bounds (dangerous in real-world code). 😱

Why CS50’s get_string() is Better:

CS50’s get_string() does all of this for you in the background. You don’t need to worry about buffers, overflows, or strings not handling spaces. You can just:

1
string answer = get_string("What's your name? ");  

And boom, CS50 takes care of reading the whole string, even if it has spaces. It’s beginner-friendly, just like CS50’s philosophy-making complex things easier for you to understand and focus on learning.

rm rmdir rm -r

When you use rm and rmdir, there’s no going back, no safety net. Those files and directories are permanently deleted-not sent to the recycle bin, not recoverable through the GUI. It’s like a digital vanishing act 🪄💥-they’re gone for good.

🔥 rm (remove)

  • This command removes files-like poof, gone. No recycle bin, no backup, just vanished. If you delete something important… it’s not as easy to recover, especially in Linux. That’s why you have to be careful.

    Example:

    1
    
    rm myfile.txt
    

🔥 rmdir (remove directory)

  • This one removes directories, but only if they’re empty. If the directory still has files inside, you’d get an error. It’s like cleaning up a folder that’s free of all the digital clutter.

    Example:

    1
    
    rmdir myfolder
    

When you want to remove a directory that’s not empty-meaning it still has files inside-you need to use a more powerful command.

💀 rm -r (recursive remove)

The -r option stands for recursive, meaning it will go through the directory, delete all the files inside and the directory itself. It’s like sending in a digital wrecking ball to clear out everything.

Example:

1
rm -r myfolder

This will delete the folder myfolder and all its contents (files, subdirectories, everything inside). No mercy. 🔥

⚠️ Warning:

Be careful with rm -r, especially when running it with sudo (superuser permissions) or as root. It will remove everything inside that folder with no prompts, so it’s easy to accidentally delete something important.

If you’re feeling extra cautious and want to make sure before deleting, you can add the -i flag (interactive), which will ask for confirmation before each delete:

1
rm -ri myfolder

This will ask for your confirmation on each file within the folder, which can be a good safety measure if you’re unsure about the contents.

sprintf() - str(), strlen() - len(), strncmp() - startswith()

Slipping from Python into the land of C? Come closer, I’ll show you the C magic versions of startswith() and len() for long numbers 🔮✨


🧠 Problem:

In Python, you can do this:

1
2
3
num = 123456
str(num).startswith("123")  # True
len(str(num))  # 6

But in C, long is a number-not a string. So we need to:

  1. Convert it to a string first (yes, like str() in Python)
  2. Then check the prefix or length manually

✅ Solution in C:

Let’s say you have:

1
long number = 1234567890;

🔁 Step 1: Convert to string

1
2
char num_str[20]; // 20 digits more than enough for long
sprintf(num_str, "%ld", number);  // convert long to string
Dive into char num_str[20];
  • 🍓 Already know char myGrade = 'A':

    1
    
      char myGrade = 'A';
    
    • This is a single character
    • Stored in 1 byte
    • It’s like saying: “Hey memory, keep this 'A' in a little box called myGrade.”

  • 🧠 Now this:

    1
    
      char name[20];
    

    Means:

    “Hey memory, prepare 20 tiny boxes side-by-side. Each one will hold a single character. And I’m calling the whole row of boxes name.”

    This is a character array, which is used in C to represent strings.

    So:

    1
    
      char name[20];
    

    Could store something like "Keira ❤️" → which is actually:

    1
    
      ['K', 'e', 'i', 'r', 'a', ' ', '❤', '\0', ?, ?, ?, ..., ?]
    

    ⬅️ The \0 is super important - it’s the null terminator that says “this is the end of the string.”


  • ❓Does it always have to be [20]?

    No! It depends on how long the string you want to store is.

    Examples:

    • "name" → 4 letters + 1 null terminator = needs 5
      1
      
        char cute[5] = "name";
      
    • "Queen" → 5 letters = needs 6
      1
      
        char title[6] = "Queen";
      

    If you don’t know in advance how long the string might be, then you over-allocate (like [20], [100], etc.) to be safe.


  • 💥 What happens if you write too much?

    1
    
      char shortie[3] = "Keira";
    

    This overflows because:

    • "Keira" needs 6 spaces (K e i r a \0)
    • You only gave it 3 boxes 😱
    • That’s dangerous in C and can corrupt memory 🧨

    Always give your strings enough space to breathe😌


  • 🌸 Want some visual?

    If you do:

    1
    
      char baby[6] = "Mwah!";
    

    It stores:

    1
    2
    
      Index →  0   1   2   3   4   5
      Value → 'M','w','a','h','!','\0'
    

    C strings are just char arrays terminated with a special \0 to mark “the end.”

Dive into sprintf(num_str, "%ld", number);

Now num_str is like "1234567890" - a char array.

sprintf(num_str, "%ld", number); This line is doing: “Convert the long number into a string and store it in num_str.”

Break the pieces down:

PartMeaning
sprintf“String print” - like printf, but instead of printing to screen, it prints into a string
num_strWhere to store the result (the destination char array)
"%ld"Format specifier for printing a long integer
numberThe actual long variable you’re converting

So if:

1
long number = 123456;

Then:

1
2
sprintf(num_str, "%ld", number);
// num_str becomes "123456"

Why %ld instead of %li?
Both %ld and %li are valid for long, but %ld is more commonly used in practice. They’re functionally the same here, so it’s a convention preference.

🪞 Step 2: Get length (like Python’s len()):

1
int length = strlen(num_str);

You need to:

1
#include <string.h>  // for strlen

🚪 Step 3: Check prefix (like Python’s startswith()):

If you wanna check whether it starts with "123":

1
2
3
4
if (strncmp(num_str, "123", 3) == 0)
{
    printf("Starts with 123!\n");
}

You need to:

1
#include <string.h>  // for strncmp

strncmp(num_str, "123", 3) == 0 This checks:

❓ “Do the first 3 characters of num_str match "123"?”

Let’s say:

1
num_str = "1234567890";

Then:

1
2
strncmp(num_str, "123", 3)  // ✅ True → returns 0
strncmp(num_str, "124", 3)  // ❌ False → returns non-zero
  • strncmp(a, b, n) compares the first n characters of string a and string b
  • If they’re the same: it returns 0
  • If they differ: it returns a non-zero number (positive or negative depending on the difference)

So it’s like Python’s:

1
num_str.startswith("123")

🎯 Full Example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <cs50.h>
#include <stdio.h>
#include <string.h>

int main(void)
{
    long number = get_long("Number: ");
    
    char num_str[20];
    sprintf(num_str, "%ld", number);

    int length = strlen(num_str);
    printf("Length: %i\n", length);

    if (strncmp(num_str, "123", 3) == 0)
    {
        printf("Starts with 123!\n");
    }
    else
    {
        printf("Does not start with 123.\n");
    }
}

🎯 TL;DR Recap 🐇:

CPython
char str[20];s = "" (string init)
sprintf(str, "%ld", num);str(num)
strlen(str)len(str)
strncmp(str, "abc", 3)str.startswith("abc")

Some Concepts: C VS Python

❓1. Does long start from “0” index like strings do?

Yes and no. Here’s the tea:

If you’re working with:

1
long number = 4003600000000014;

This is just a number. It doesn’t have “indexes” like a string or array.
To treat it like "4003600000000014" (where '4' is at index 0), you gotta first convert it to a string, like you did:

1
2
char num_str[20];
sprintf(num_str, "%ld", number);

Now yes! You can do:

1
2
num_str[0] == '4'   // like number[0] in Python
num_str[1] == '0'

So once it’s a string, indexing starts from 0, just like Python. ✅


❓2. How to get the nth digit of a long like number[0] in Python?

Since long is not indexable, you have two choices:

💡 Option 1: Convert to string

1
2
3
4
char num_str[20];
sprintf(num_str, "%ld", number);

char first_digit = num_str[0];  // index like a string!

If you want the number version:

1
int digit = num_str[0] - '0';  // convert char '4' to int 4
🧠 digit = num_str[0] - '0' - What does - '0' mean?

Let’s say:

1
char ch = '4';

Characters like '4' are stored in memory as ASCII codes.
In ASCII:

  • '0' is 48
  • '1' is 49
  • '4' is 52
  • '9' is 57

So when you do:

1
'4' - '0'  52 - 48 = 4

It converts the character '4' into the integer 4, which you can do math with.

So:

1
int digit = num_str[0] - '0';  // '4' → 4

This works for any digit char '0' to '9'.

💡 Option 2: Use math (if you don’t want string)

Let’s say you want the leftmost digit:

1
2
3
4
5
6
7
long number = 4003600000000014;

while (number >= 10)
{
    number /= 10;
}
// now number == 4

To get a digit at any other position using math, it’s trickier. Use string if you want simplicity.


❌ 3. Can I do sum[-1] to get the last digit of an int?

In Python:

1
str(123)[-1]  # '3'

But in C:

  • You can’t use negative indexing. sum[-1] is undefined behavior and may crash your program or return garbage.

Instead, you can use:

Get last digit of an int:

If you have:

1
int num = 123;

Then the last digit is:

1
int last_digit = num % 10;  // → 3

If you want to remove the last digit:

1
num = num / 10;  // now num is 12

So:

1
2
3
4
5
6
while (num > 0)
{
    int digit = num % 10;  // get last digit
    // do something with digit
    num = num / 10;        // remove that digit
}

This way, you process the number backwards (right to left), just like Luhn’s algorithm needs 💳✨


🍭 Summary (C Style Cheat Sheet):

AskedIn C
Does long have index like strings?❌ No, but you can sprintf() to string first, then yes ✅
How to get number[i]?Convert to string → num_str[i] - '0'
TaskHow to do it
Get char '4' as number'4' - '0' = 4 ✅
Get last digit of intnum % 10
Remove last digitnum = num / 10
Negative index?❌ Nope, not in C 😢

Luhn’s Algorithm

❓ “Do all kinds of cards need to pass Luhn’s Algorithm, or just VISA?”

💳 Answer: YES - ALL major card brands (VISA, MasterCard, AMEX, Discover, etc.) must pass Luhn’s Algorithm.
It’s not a “Visa-only” rule - it’s a global checksum standard used for verifying whether the number is syntactically valid.


🧩 So What’s Really Going On?

  1. Card length and prefix (first digits) determine the brand:
    • VISA: starts with 4, length 13 or 16
    • AMEX: starts with 34 or 37, length 15
    • MasterCard: starts with 51-55, length 16
  2. Luhn’s algorithm is applied after we read the number.
    If the checksum fails, even if it looks like a VISA card, it’s invalid.

💡 Think of it like this:

  • If it doesn’t match the pattern: ❌ “INVALID”
  • If it matches the pattern but fails Luhn: ❌ “INVALID”
  • If it passes both: ✅ Brand name: “VISA”, “MASTERCARD”, etc.

So yeah, Luhn is the universal bouncer at the card validation party 😎🕶️

Have fun in CS50!

💖 Support me with crypto or PayPal! 💘

Bitcoin (BTC):
bc1qtzjwfyfpleyzmpqu97sdatqes98ms3zxc7u790

Ethereum (ETH) & USDT (ERC-20):
0xFE05f74DeF594f8F904D915cB93361C99cB36500

Or support me on Ko-fi:

Support me on Ko-fi

Any amount helps me continue creating content 💬💻

This post is licensed under CC BY 4.0 by the author.