Week 1
Lecture 1
Compiler and Interpreter
- Compiler: convert source code to machine code (binary 1 and 0 bits) before program is run
- Interpreter: convert code into machine code, when the program is run
- Related article
Command line in termimal window
make hello
./hello
. means this directory, / means to execute this file
Other Command lines
- to remove a file:
rm filename- list all files:
lsNote: Among the listed files, the filename in green color and followed by an asterisk, indicates that the file is executable- make directory:
mkdir foldername- change directory:
cd folder- make a file / open an existing file:
code filename- go back to parent directory:
cd ..- go back to default folder:
cd- to remove a file:
rm filename- to remove a folder:
rmdir foldername
Format code
string answer = get_string("What's your name? ")
printf("hello, %s\n", answer);
In C, you need to tell the computer the type of value of a new varaible!
| %c | char |
|---|---|
| %i | integer |
| %s | string |
| %f | float / double |
| %li | long integer |
Note:
- to specify decimal number:
%.2f(two decimal places) - to use
get_string()function, you need to importcs.hlibrary
Syntactic sugar
counter = counter + 1;
counter += 1;
counter++;
Single quote or double quote
In C, a char is surrounded by single quotes, ', instead of double quotes for strings. (And strings with just a single character will still have double quotes, since they are a different data type.)
Defining functions
void function_name(void)
{
}
When we move the function declaration to the bottom of file, we need to declare our function with a prototype before main, which just tells the compiler that we’ll define our function later with the return type and argument type specified:
void function_name(void);
To take in parameters:
void function_name(value_type param1, value_type param2, ...)
do-while loop (check the condition last instead of first)
int n;
do
{
n = get_int("Size: ");
}
while (n < 1);
//function similar to:
while (true)
{
n = get_int("Size: ");
if (n > 1)
{
break;
}
}
floating-point imprecision
-
floating-point imprecision: the inability for computers to represent all possible real numbers with a finite number of bits, like 32 bits for a float. So, our computer has to store the closest value it can, leading to imprecision.
-
Truncation: divide an integer by an integer, get back an integer, throw away all the numbers behind decimal point
int main(void) { int x = 2; int y = 3; float z = x / y; printf("%.50f\n", z); } //output 0.00000000000000000000000000000000000000000000000000To solve the problem, use type conversion:
float z = (float)x / y; printf("%.50f\n", z); //output 0.66666668653488159179687500000000000000000000000000 -
integer overflow: when we had three bits and needed to count higher than seven (or 111), we added another bit to represent eight with 1000. But if we only had three bits available, the “next” number would be 000, since we wouldn’t have a place for the extra 1.
Example: In 2038, we’ll also run out of bits to track time, since many years ago some humans decided to use 32 bits as the standard number of bits to count the number of seconds since January 1st, 1970. But since a 32-bit integer can only count up to about two billion, in 2038 we’ll also reach that limit. The 32 bits of an integer representing 2147483647 look like:
01111111111111111111111111111111
When we increase that by 1, the bits will actually look like:
10000000000000000000000000000000
But the first bit in an integer represents whether or not it’s a negative value. so the decimal value will actually be -2147483648, the lowest possible negative value of an
int. So computers might actually think it’s sometime in 1901.
Related terms
Integrated Development Environment (IDE)
Command Line Interface (CLI)
shorts
Data types
- int: take up 4 bytes of memory (32 bits); Range: -231 to 231-1
- unsigned int: unsigned is a qualifier that can be applied to certain types (including int), which effectively doubles the positive range of variables of that type; Range: 0 to 232-1
- char: used to store single variables, take up 1 byte of memory (8 bits); Range: -128 to 127
- float: also known as real numbers, take up 4 bytes of memory. Some of the 32 bits might be used for an integer part
- double: also known as real numbers; doubles are double precision, take up 8 bytes of memory (64 bits);
- void: a type, not a data type
In cs50, there are two additional types
- bool boolean value, true and false
- string
Variables
To create multiple variables to the same type, only need to specify the type name once: int height, width, length
int number; // declaration
number = 17; // assignment
int number = 17; // initialization
Operators
Arithmatic operators
%: modulus operator, gives the remainder
Boolean expressions
In C, every nonzero value is equivalant to true, and zero is false.
Logical operators
&&: and||: or!: not
Relational operators
<, >, <=, >=
== (equality), != (inequality)
Conditional statements
Switch statement
switch(x)
{
case 1:
printf("One!\n");
break;
case 2:
printf("Two!\n");
break;
case 3:
printf("Three!\n");
break;
default:
printf("Sorry!\n");
}
Note: it's important to break, or you will "fall through" each case (unless that is the desired behavior).
?: (ternary operator)
int x = (expr) ? 5 : 6;
the same effect:
int x;
if (expr)
{
x = 5;
}
else
{
x = 6;
}
Useful for writing trivially short conditional branches
Loops
do-while loop
do
{
}
while (boolean-expr);
for loop
for (start; expr; increment)
{
}
Comparison
| while | Use when you want a loop to repeat an unknown number of times, and possibly not at all |
|---|---|
| do-while | Use when you want a loop to repeat an unknown number of times, but at least once |
| for | Use when you want a loop to repeat a discrete number of times, though you might not know the number at the moment the program is compiled |
Command line
ls: list the content in the current directorycd <directory>: change directory. the shorthand name for parent directory is.., for current directory is.pwd: present working directorycd: navigate to home directorymkdir <directory>: create directorycp <source file> <destination file>: copy a filecp -r <source dir> <destination dir>: copy a directory and everything inside it (recursively)rm <file>: remove a filerm -f <file>: remove a file without being asked to confirmrm -r <directory>: remove a dir recursivelyrm -rf <directory>: recursively and forcibly remove a dirmv <source> <destination>: move file to destination can be used for renaming a file
Pset1
Credit
Note 1:
How to count the lenght of a number
int length = floor(log10(num)) + 1;
Note 2:
How to deal with imprecision when the float is too long
At first, I intended to get every digit of the num without changing the original num:
for (int i = 1; i < lenght; i++)
{
int last_digit = num % pow(10, i);
int last_two_digits = num % pow(10, i + 1);
int secend_to_last = (last_two_digits - last_digit) / pow(10, i)
}
Output: didn't work out, even produced negative numbers in digits. Possible Reason: limited precision when it comes to float / double numbers Correct way: After I get the last and second-to-last digits and add them to sum, modify the original number so that the last two digits are sliced off, making the number shorter by two digits after every loop:
long num_new = num;
// length is even
for (int i = 0; i < round(length / 2); i++)
{
// get the last_one and second_to_last digit
int last_two = num_new % 100;
int last_one = num_new % 10;
int second_to_last = (last_two - last_one) / 10;
// slice off the last two digits of original num
num_new = (double)num_new / 100 - last_two * 0.01;
// multiply every secont_to_last by two
int digit_multiplied = second_to_last * 2;
// get the digit of digit
int digit_0 = ((digit_multiplied % 100) - (digit_multiplied % 10)) / 10;
int digit_1 = digit_multiplied % 10;
// calculate the sum of every other digit
sum_0 = sum_0 + digit_0 + digit_1;
// calculate the sum of left-over digits
sum_1 = sum_1 + last_one;
}
// calculate sum of all
sum = sum_0 + sum_1;
// length is odd
if (length % 2 == 1)
{
// the first digit should be added to sum_1
sum += first_num;
}