🏫 [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 typechar
→ like:'H'
,'e'
,'1'
"hello"
(double quotes) = a string literal, of typechar[]
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:
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).
- This line creates an array of characters, called
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.
- This line tells C to read input from the user (a string) and store it in the
But there’s a catch!
scanf("%s", answer)
won’t handle spaces. So, if you enter a name likeJohn Doe
, it will only captureJohn
-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:
- Convert it to a string first (yes, like
str()
in Python) - 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 calledmyGrade
.”
🧠 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 51
char cute[5] = "name";
"Queen"
→ 5 letters = needs 61
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:
Part | Meaning |
---|---|
sprintf | “String print” - like printf , but instead of printing to screen, it prints into a string |
num_str | Where to store the result (the destination char array) |
"%ld" | Format specifier for printing a long integer |
number | The 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 forlong
, 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 firstn
characters of stringa
and stringb
- 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 🐇:
C | Python |
---|---|
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):
Asked | In 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' ✅ |
Task | How to do it |
---|---|
Get char '4' as number | '4' - '0' = 4 ✅ |
Get last digit of int | num % 10 ✅ |
Remove last digit | num = 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?
- Card length and prefix (first digits) determine the brand:
- VISA: starts with
4
, length 13 or 16 - AMEX: starts with
34
or37
, length 15 - MasterCard: starts with
51
-55
, length 16
- VISA: starts with
- 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 😎🕶️