5.4 CS50

5.4.1 Introduction

  • Course covers Scratch, C, Python, and SQL, with a focus on problem-solving and critical thinking skills.
  • Unary notation, also known as base one, is a system where counting is done using individual units, such as fingers, with each unit representing one digit, and this system is used when counting people or objects one by one, literally using fingers as digits
  • The question of how high one can count with one human hand is posed and the correct answer is actually 31, which can be achieved by using patterns and combinations of fingers
  • The binary system, also known as base 2, is a system that uses two potential states, such as down or up, or black and white, to represent information, and this system is used by computers to understand and process data
  • In the binary system, information is represented using binary digits, also known as bits, which can have a value of either zero or one, and this is in contrast to the decimal system, which uses 10 digits to represent information
  • Computers use millions of tiny light switches, known as transistors, to store information, and these transistors can be turned on or off to represent zeros and ones, allowing computers to store and process information
  • To count higher than zero or one, multiple bits, or light bulbs, are needed, and with three bits, a computer can represent numbers up to seven, using different combinations of zeros and ones to represent each number
  • Computers represent numbers using a binary system, where a series of switches or light bulbs can be turned on or off to represent different values, such as 0 and 1, with the pattern off off off representing 0, off on off representing 2, and on on on representing 7
  • The binary system uses a base 2 number system, where each digit can have one of two values, 0 or 1, and the columns are weighted differently, with the rightmost column being the ones column, the next column being the twos column, and so on, using powers of 2
  • The powers of 2 are used to weight the columns in the binary system, with the first column being 2 to the 0, the second column being 2 to the 1, and so on, allowing computers to count from 0 to 7 using only 3 digits
  • A byte, or eight bits, can represent a range of decimal numbers from 0 to 255, and this range is calculated by adding the powers of two represented by each bit, so if all the bits are ones, the total is 128 + 64 + 32 + 16 + 8 + 4 + 2 + 1, which equals 255
  • The use of powers of two, such as 255 and 256, is common in the computer world and programming because these are the typical units of measurement used by systems, and understanding these concepts can help clarify how computers represent and process information

5.4.1.1 Unicode

  • Computers initially used eight bits to represent characters, which limited the number of possible characters to 256, sufficient for the English alphabet but not for other languages that have more glyphs, and nowadays computers use more bits, such as 16, 24, or 32 bits, to represent a wider range of characters
  • With 32 bits, it is possible to represent as many as 4 billion possible characters, which is a significant increase from the initial 256 characters, and this has enabled the representation of all human languages, past, present, and future, as well as pictograms like smiley faces and emojis
  • The goal of the Unicode system is to be backwards compatible with the existing character set, known as ASI, and to represent all human languages, as well as pictograms and emojis, using a super set of representations that can be 16, 24, or 32 bits
  • The Unicode Consortium releases new emojis every year, which can cause compatibility issues if devices are not updated with the latest software, resulting in some emojis not being displayed correctly, and the popularity of emojis can be seen in a cloud diagram that shows the size of each emoji indicating its relative popularity

5.4.1.2 Color

  • Computers represent color using a system called RGB, which stands for red, green, and blue, and this system is used to allocate some number of bits or bytes to represent the color of a single dot, or pixel, on the screen
  • The RGB system typically uses three numbers, or three bytes, which is 24 bits per pixel, to represent the color of a pixel, with each number representing the amount of red, green, and blue in the color
  • Each of the three numbers in the RGB system uses eight bits, or one byte, to represent the amount of red, green, and blue, with the highest possible value being 255, and the actual value representing a proportion of this maximum amount
  • When a computer combines the wavelengths of light represented by the RGB values, it produces a specific color, such as a medium amount of red, a medium amount of green, and a little bit of blue, which results in the color code for a single dot, representing a specific shade of yellow
  • The pattern of three bytes, such as 72, 73, and 33, is used to represent the color of a single pixel, and this pattern is repeated for every pixel on the screen, with the combination of these pixels creating the image that is perceived by humans
  • Digital photographs are made up of millions of bytes, with each byte corresponding to one of the pixels on the screen, and at least three bytes are used to represent every one of these dots, resulting in large file sizes, such as 1 megabyte or 10 megabytes, depending on the resolution of the image
  • Representation: Computers represent colors using a combination of bytes, with millions of bytes used to represent images, and this representation is made possible by fancy compression software that can use fewer bytes, but in general, it is the combination of these bytes that allows for color representation
  • Videos are represented as a series of images, similar to flipbooks, where the human mind perceives motion when individual images are displayed in rapid succession, with videos typically consisting of 30 or 24 frames per second, making them large files to download due to the high number of images
  • Sound can be represented using numbers that correspond to specific frequencies, which have a direct relationship to the pitch of a note, and additional numbers can be used to represent volume and duration, allowing for the digital representation of music
  • The representation of musical notes can be achieved by assigning specific patterns to each note, such as A, A sharp, and C, and using multiple bytes to represent the pitch, volume, and duration of each note, similar to how RGB values represent colors
  • The interpretation of zeros and ones depends on the context in which they are used, such as a calculator program interpreting a pattern as numbers, a text messaging program interpreting it as letters, or Photoshop interpreting it as a color, and programmers have the power to write code that tells the computer how to treat these patterns

5.4.1.3 Algorithms

  • An algorithm is a set of step-by-step instructions for solving a problem, and it is essential to express oneself correctly and precisely when creating an algorithm, as explored in the concept of converting problems to solutions
  • The notion of an algorithm is introduced as a precise description of how to do something, with the operative word being “precise”, and an example of trimming a beard is used to illustrate this concept
  • Pseudocode: Implementing algorithms as programmers or computer scientists involves translating conceptual ideas into code, which can be expressed in various programming languages such as C, C++, Python, R, or Ruby, and for now, pseudo code can be used as an intermediate step
  • Pseudo code is not a formal language and can be written in various ways, with the goal of being precise and finite, and it can be used to break down complex tasks into step-by-step instructions, as demonstrated with the example of finding a person in a phone book
  • The process of finding a person in a phone book can be broken down into steps, including picking up the phone book, opening to the middle of the book, looking at the page, and checking if the person is on the page, with conditional actions based on the outcome of each step
  • The example of finding a person in a phone book illustrates the importance of considering all possible scenarios, including the case where the person is not in the book, which can be a common source of errors in software development if not properly handled
  • Pseudo code can include verbs or actions, which are referred to as functions, and conditional statements, such as if-else statements, which are used to make decisions based on Boolean expressions, which are questions with a yes or no answer
  • Boolean expressions are named after mathematician Boolean and are used to make decisions in code, with indentation playing a crucial role in determining the logical flow of the program, as seen in the example of finding a person in a phone book
  • The use of pseudo code and conditional statements can help programmers anticipate and handle potential errors, such as the case where a person is not in the phone book, and can help prevent bugs and mistakes in software development
  • The characteristics of pseudo code, including the use of functions, conditionals, and Boolean expressions, will be used throughout the discussion, with a focus on developing a more technical understanding of these concepts
  • The example of finding a person in a phone book demonstrates the importance of using indentation to convey logical significance in pseudo code and many programming languages, with the indentation determining which actions to take based on the outcome of conditional statements
  • Most computer programs have four fundamental characteristics, including the ability to make decisions and create cycles or loops, and even in relatively simple real-world algorithms, these characteristics are present, as seen in the example of searching for John Harvard in a phone book
  • The use of loops in programming can potentially create an infinite loop, where the program gets stuck in a cycle forever, but in the case of the phone book algorithm, the loop will eventually stop because the problem is being divided and conquered, and the phone book will eventually run out
  • The algorithm for searching the phone book will stop when John Harvard is found or when the entire phone book has been searched, and this is guaranteed to happen because the problem is being broken down into smaller parts
  • When writing code, it is possible to accidentally create an infinite loop, which can cause the computer to become unresponsive, but there are ways to terminate or break out of these conditions, and these techniques will be explored later
  • The concepts of loops and decision-making will be used to solve real-world problems, including visual and audio problems, and these solutions will be explored after a break
  • The ability to write code that can solve complex problems and potentially take control of the computer is a powerful tool, but it requires careful attention to detail to avoid creating bugs or infinite loops
  • The techniques for terminating or breaking out of infinite loops and solving real-world problems will be demonstrated, allowing users to write code that can be used to solve a wide range of problems

5.4.1.4 Artificial Intelligence

  • Artificial intelligence has been a prominent topic in recent months and years, and it will be revisited at the end of the course to explore its connection to the concepts learned throughout, particularly in relation to writing code
  • Implementing a chatbot that answers questions and has conversations can be done using pseudo code, which may involve conditional statements, such as responding with “hello” if the user says “hello”, but this approach can become impractical with a large number of possibilities
  • The number of conditional statements required to handle various questions and responses can escalate quickly, making it impossible for programmers to write an infinite number of conditionals, and this is where artificial intelligence comes in to figure out the responses based on probability and statistics
  • Artificial intelligence, such as chatbots, is typically trained on large amounts of data, allowing it to learn and respond to questions without requiring an infinite number of conditional statements, and this is often achieved using large language models and neural networks
  • Neural networks are inspired by the human brain’s neural structure, where each circle represents a neuron, and the arrows represent pathways between them, and these networks are trained on huge amounts of data to produce answers to questions based on probability and statistics
  • The goal of neural networks is to output the most probabilistically likely answer to a given question, and this approach is used by companies like Google and Microsoft to power their AI systems, without relying on programmers to anticipate every possible question
  • The concept of using a rubber duck as a debugging tool has been around for a long time, where programmers talk to the duck to explain their code and identify errors, and this idea is also used in CS50’s own AI persona, which takes the form of a rubber duck
  • The technique of “rubber duck debugging” or “rubber ducking” involves talking through a problem to a physical or virtual entity, like a duck, to help clarify and solve the issue, and this technique can be a valuable programming tool
  • Virtual tools, such as chat GPT, are not allowed to be used in the class due to policy, but students are encouraged to use CS50’s own AI-based tools, which are designed to guide students towards solutions without providing outright answers
  • CS50’s AI-based tools will be available throughout the course and can be accessed through a specific URL, as well as being embedded in the Visual Studio code programming environment, where a virtual “duck” will also be present
  • The course will cover programming concepts, including the use of AI, and will start with writing code in a language other than C, as the code written in C can look cryptic and is not the focus of the initial lessons
  • The initial focus of the course will be on a more visual incarnation of programming, rather than the zeros and ones that the computer understands as input, and actual programming will be done after a short break
  • The programming environment that will be used is a cloud-based version of Visual Studio code, where students will be able to access the virtual “duck” and other tools to help with their programming tasks
  • Computers only understand code written in zeros and ones, but programmers will be writing code at a higher level, using languages that are more understandable and easier to work with, such as C, Python, and JavaScript, with the understanding that computers can represent higher numbers using zeros and ones
  • The programming language C is an older language that remains popular due to its speed and ability to make devices operate quickly, and it will provide a conceptual foundation for introducing other languages, even though it may seem scary at first due to its punctuation and syntax
  • The value of learning C is not that it will be used directly in most jobs, but rather that it will provide a foundation for understanding other languages, such as Python and JavaScript, which offer more functionality and abstract away some of the details that will be focused on in the coming days

5.4.2 C

5.4.2.1 Running CS50 locally

  1. Download the CS50 Library from https://github.com/cs50/libcs50/releases
  2. 1b. Extract/unzip the downloaded zipped folder
  3. Open Terminal and change directory to the unzipped CS50 library folder. For example if folder is on desktop and the folder is named libcs50-10.1.0 , then terminal command should be: cd desktop/libcs50-10.1.0
  4. Still in terminal after changing directory, then run the command: sudo make install
  5. After installation, close terminal, go to visual studio and write your C program #include <cs50.h>
export DYLD_LIBRARY_PATH=/usr/local/lib
g++ cppTest/helloworld.cpp -o cppTest/helloworld -lcs50

\\ if in same directory
./FileName

link to set up. https://stackoverflow.com/questions/76893704/how-can-i-include-the-cs50-h-file

Better yet, add this to your profile so you don’t need to set it up every time you open a new terminal window. Add the following line to your ~/.bash_profile or ~/.zshrc file:

Configure the c_cpp_properties.json file to inclute the path to the CS50 library (header file).

            "includePath": [
                "${workspaceFolder}/**",
                "/usr/local/include/"
            ],

Not discussed in this lecture, but make default make settings do not work on my local computer. Create a Makefile in the directory with my C programs with the following content.

CC = gcc
CFLAGS = -lcs50

# Default target: compile the executable with the same name as the .c file (without extension)
%: %.c
    $(CC) $< -o $@ $(CFLAGS)

Then by make command, the executable will be created with the same name as the .c file, and it will link to the cs50 library.

5.4.2.2 Source code

  • Programmers in the real world write source code, which is a little English-like but has its own patterns and special syntax, and this is what software developers and engineers do, but computers only understand zeros and ones, also known as binary system
  • Computers use patterns of bits to represent not only numbers, letters, colors, images, and sounds but also fundamental functionality such as printing, playing, and loading, and these patterns are built into devices like Macs, PCs, and phones
  • The process of translating source code into machine code that computers understand is done using a compiler, a special program that takes source code as input and produces machine code as output, and the course will focus on a compiler that supports the C language
  • Visual Studio Code for CS50: The tool used for CS50 problem sets is Visual Studio Code, or VS Code for short, which is a popular industry standard tool that can be accessed through a cloud-based version at cs50.dev, requiring a free GitHub account to sign in
  • The cloud-based version of VS Code has CS50-specific features pre-installed, and users can download the software for free onto their Mac or PC later in the term to program offline, although it is suggested to wait until they are comfortable with the cloud-based environment
  • The VS Code interface includes tabs for code at the top right, a terminal window at the bottom for a command line interface, a File Explorer at the top left, and an activity bar with icons for various features, including a CS50-specific chat bot
  • VS Code automatically highlights and colorizes code to draw attention to different ideas in the program, and it allows users to use their keyboard more efficiently than their mouse or trackpad
  • The terminal window in VS Code is a command line interface, abbreviated as CLI, where users can type commands to run programs, which may feel like a step backwards initially but will provide more power and efficiency
  • The graphical user interface, abbreviated as GUI, in VS Code includes buttons, icons, and menus, and it is built into the software along with the command line interface
  • The activity bar in VS Code includes a duck icon, which is a CS50-specific chat bot that users can ask questions to throughout the process, and it can be accessed by logging in to the cloud-based version of VS Code
  • The command line interface in VS Code will be introduced and used, allowing users to type commands to run programs and providing more efficiency and power beyond the graphical user interface
  • The use of VS Code will involve a combination of graphical and command line interfaces, providing users with a comprehensive programming environment
  • Hello, World: The problem sets each week are where students will learn how to program, with the lectures introducing concepts, ideas, and primitives to get started, and it is through actually doing the problem sets that muscle memory and practice will come
  • To get started with programming, the code will be written in a terminal window, and the file will be named with a dot C extension by convention, such as hello.c, with attention to details like lowercase letters and no spaces
  • When writing code in C, it is important to be precise, as computers are not forgiving, and mistakes like miscapitalization, misspelling, or adding too many spaces can occur, but muscle memory will come with practice
  • The program will be typed out in VS Code, including lines like include stdio.h, int main void, and printf, with curly braces and proper punctuation, and this code will be automatically saved by VS Code or can be saved manually with control or Command S
  • The written code will be displayed in the Code tab, with color coding, and a visual icon will indicate that the file exists in the account, which is stored in a cloud container, similar to iCloud or Google Drive

5.4.2.3 From Scratch to C

  • The idea is to compare Scratch programs with their equivalent in C, using the example of a “Hello, world” program, and understanding that the syntax may seem overwhelming at first, but there is a rhyme and reason to how Scratch was designed
  • In Scratch, there is a function called “say” that takes an input or argument, which is provided in a white oval, and the equivalent in C is the word “print”, or more specifically “printf”, which allows for formatting text in various ways
  • The input or argument in C is surrounded by double quotes, and not single quotes, and it can include escape sequences such as “” to indicate a new line, which is essential for telling the computer exactly what to do
  • The backslash “n” in C is an escape sequence that indicates a new line, and it is necessary to include it at the end of a “printf” statement to move the prompt to the next line, which is considered good practice
#include <stdio.h>

int main(void) 
{
    printf("hello, world\n");
    return 0;
}
## /opt/homebrew/opt/llvm/bin/clang -I"/Library/Frameworks/R.framework/Resources/include" -DNDEBUG   -I/opt/homebrew/opt/llvm/include    -fPIC  -falign-functions=64 -Wall -g -O2  -c c5e903e9eaf68.c -o c5e903e9eaf68.o
## /opt/homebrew/opt/llvm/bin/clang -dynamiclib -Wl,-headerpad_max_install_names -undefined dynamic_lookup -L/Library/Frameworks/R.framework/Resources/lib -L/opt/homebrew/opt/llvm/lib -Wl,-rpath,/opt/homebrew/opt/llvm/lib -o c5e903e9eaf68.so c5e903e9eaf68.o -F/Library/Frameworks/R.framework/.. -framework R
  • If the backslash “n” is omitted, the prompt will appear on the same line as the output, which may look confusing and is not the intended behavior of the program

output:

hello, world$
  • In programming, it is essential to tell the computer exactly what to do, and using escape sequences like “” is a way to do that, rather than relying on physical line breaks in the code, which can be confusing for the computer
  • The use of functions like printf is similar to f of x notation in mathematics, where f is a function, x is an argument or input, and the output is a side effect, which is something that happens on the screen, visually
  • In C, there are several escape sequences, including backslash n for a new line and backslash r, which moves the cursor to the beginning of the line, and to print an actual double quote, it needs to be escaped to avoid confusion
\n
\r
\"
\'
\\
  • The computer reads code top to bottom, left to right, and needs precise instructions, so when printing a quotation mark, it should be escaped to be displayed literally on the screen
  • To print a literal backslash, it is necessary to use backslash backslash, as the backslash is used as a special character to indicate escape sequences, and this convention was developed to solve problems that humans encountered in the past
  • The concept of side effects from functions will be contrasted with other types of outputs from functions, and the use of single quotes in other contexts will be discussed later

5.4.2.4 Header Files

  • At the top of a C program file, there is typically a line that includes a header file, which is a file that ends in .h and contains functionality that comes with the system or programming language, such as standard io.h, which is included using the line #include <stdio.h>
  • If a header file is not included at the top of the code, the program will not have access to the library, which is a collection of code written by someone else, and will result in an error, such as a call to an undeclared library function, when trying to compile the program
  • Contains the code for functions like printf, and including this file in a program allows the programmer to use these functions
  • Correct filename is stdio.h, not studio.h, which is a common mistake
  • Manual pages were documented long ago for those more comfortable with programming. A user friendly version is available at manual.cs50.io as well as the original documentation

5.4.2.5 Hello, You

  • Use cs50.h to make our life easier to get user input until the training wheels are taken off

example get_string function:

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

int main(void) 
{
    string answer = get_string("What's your name? ");
    printf("Hello, %s\n", answer);
}
  • A semicolon is required at the end of the line of code to complete the statement

  • Printf can take multiple inputs, inputs are separated by commas, with no need for multiple parentheses or ovals, and it is a good practice to separate arguments with single spaces

  • Functions in C, like in math class, follow a pattern of function name, parentheses, and inputs separated by commas, and each statement in C should end with a semicolon, as seen on lines 6 and 7 of the code

  • Besides running a program, there are other commands that can be run in the terminal window, such as “ls”, and the user can interact with the program by entering input, like “What’s your name?”, and the program will respond accordingly

5.4.2.6 Terminal Commands

cd
cp 
ls 
mkdir 
mv 
rm 
rmdir

mv hello.c old.c
mv old.c hello.c 

cp hello.c backup.c
rm backup.c

mv hello.c .. 
  • cp for copy
  • mkdir for make directory
  • mv for move
  • rm for remove
  • rmdir for remove directory, which can be used to manage files and folders

5.4.2.7 Types

cd50 library

get_char // %c 
get_double // %d ?
get_float // %f
get_int // %i
get_long // %li
get_string // %s

5.4.2.8 Conditionals

if (x < y)
{
    printf("x is less than y\n");
}
else
{
    printf("x is not less than y\n");
}

less code is more

if (x < y)
{
    printf("x is less than y\n");
}
else if (x > y)
{
    printf("x is greater than y\n");
}
else
{
    printf("x is equal to y\n");
}

5.4.2.9 Variables and compare.c

int counter = 0;
counter = counter + 1;
counter += 1;
counter++; // only works for incrementing by 1
counter--; // only works for decrementing by 1
  • Bad code wastes computing time. Make the code simple and it will be efficient.

5.4.2.10 agree.c

bool 
char 
double 
float 
int 
long 
string 

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

int main(void) 
{
    char c = get_char("Do you agree? (y/n) ");
    if (c == 'y')
    {
        printf("Agreed\n");
    }
    else if (c == 'n')
    {
        printf("Not agreed\n");
    }
}
  • Use single quotes for single chars
  • Use double quotes for strings
  • get_char, prompts the user again and again until a single char is entered, and it ignores inputs that are too long, such as “YES”
#include <cs50.h>
#include <stdio.h> 

int main(void) 
{
    char c = get_char("Do you agree? (y/n) ");
    if (c == 'y')
    {
        printf("Agreed\n");
    }
    else if (c == 'Y')
    {
        printf("Agreed\n");
    }
    else if (c == 'n')
    {
        printf("Not agreed\n");
    }
        else if (c == 'N')
    {
        printf("Not agreed\n");
    }
}
  • The improved program still has limitations, but redundent
#include <cs50.h>
#include <stdio.h> 

int main(void) 
{
    char c = get_char("Do you agree? (y/n) ");
    if (c == 'y' || c == 'Y')
    {
        printf("Agreed\n");
    }
    else if (c == 'n' || c == 'N')
    {
        printf("Not agreed\n");
    }
}
  • Use ||, meaning “or”, to expand on conditionals without being redundant. && is to for “and”.

5.4.2.11 Loops cat.c

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

int main(void) 
{
    printf("meow\n");
    printf("meow\n");
    printf("meow\n");
}
  • Use loops to reduce redundancy
#include <cs50.h>
#include <stdio.h> 

int main(void) 
{
    print i = 3;
    while (i > 0)
    {
        printf("meow\n");
        i --;
    }
}
  • Alternatively, count up, which is more conventional.
#include <cs50.h>
#include <stdio.h> 

int main(void) 
{
    int i = 0;
    while (i < 3)
    {
        printf("meow\n");
        i++;
    }
}
  • So commonly used there’s another way to express this with “for”
#include <cs50.h>
#include <stdio.h> 

int main(void) 
{
    for (int i = 0; i < 3; i++)
    {
        printf("meow\n");
    }
}

Bad code, meow forever

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

int main(void) 
{
    while (true)
    {
        printf("meow\n");
    }
}

5.4.2.12 Functions

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

void meow(void) 
{
    {
        printf("meow\n");
    }

int main(void)
{
    for (int i = 0; i < 3; i++)
    {
        meow();
    }
}

void meow(void) means no input no output

  • When creating and using a custom function, it should be placed before its usage in the code, or declared at the top of the file with a prototype to inform the compiler about the function’s existence and usage. Improves readibility and compilers read top to bottom.
#include <cs50.h>
#include <stdio.h> 

void meow(void);

int main(void)
{
    for (int i = 0; i < 3; i++)
    {
        meow();
    }
}

void meow(void) 

{
    printf("meow\n");
}
  • Final version
#include <cs50.h>
#include <stdio.h> 

void meow(int n);

int main(void)
{
    meow(3);
}

void meow(int n) 
{
    for (int i = 0; i < 3; i++)

    {
        printf("meow\n");
    }
}
  • prompt the user for number of meows
#include <cs50.h>
#include <stdio.h> 

void meow(int n);

int main(void)
{
    int n = get_int("Number: ");
    meow(n);
}

void meow(int n) 
{
    for (int i = 0; i < n; i++)

    {
        printf("meow\n");
    }
}
  • Scope means that variables only exist within the scope in which they are created, typically inside the curly braces where they are defined, and using the same variable name in different scopes does not refer to the same variable (i.e., only in the curly braces where it was defined)
  • You can declare the variable outside the scope and define it within a scope/ give it a Value
  • do while, will loop while a question is true
#include <cs50.h>
#include <stdio.h> 

void meow(int n);

int main(void)
{   
    int n;
    do
    {
      n = get_int("Number: ");
    } 
    while (n < 1);
    meow(n);
}

void meow(int n) 
{
    for (int i = 0; i < n; i++)

    {
        printf("meow\n");
    }
  • What about a positive number.get_positive_int that solves the common problem of prompting the user for a positive number, which can be reused in other programs. This method cleans the code for legibility.
#include <cs50.h>
#include <stdio.h> 

int get_positive_int(void);
void meow(int n);

int main(void)
{   
    int times = get_positive_int();
    meow(n);
}

int get_positive_int(void) 
{
    int n;
    do
    {
        n = get_int("Number: ");
    } 
    while (n < 1);
}

void meow(int n) 
{
    for (int i = 0; i < n; i++)

    {
        printf("meow\n");
    }
}
  • The function get_positive_int is supposed to return an integer value, (as declared in the prototype denoted by int), and has no input, whereas the meow function has input but no output, instead producing a visual side effect by printing to the screen. This is sort of opposite of what we want, so we need to correct the code for this,
#include <cs50.h>
#include <stdio.h> 

int get_positive_int(void);
void meow(int n);

int main(void)
{   
    int times = get_positive_int();
    meow(times); //fix this 
}

int get_positive_int(void) 
{
    int n;
    do
    {
        n = get_int("Number: ");
    } 
    while (n < 1);
    return n; //Here is the keyword
}

void meow(int n) 
{
    for (int i = 0; i < n; i++)

    {
        printf("meow\n");
    }
}

5.4.2.13 Correctness, Design, Style

  • Correctness is the most important aspect of programming, as it refers to whether the code does what it is supposed to do, and without it, the code is pointless
  • Design is a qualitative aspect of programming that involves structuring the code in a way that makes it better, similar to getting feedback on an English essay, and it can be improved with tools like “design50”
  • Style is a purely aesthetic aspect of programming that refers to how the code looks, whether it is nicely printed, and whether other people can read and understand it, with tools like “style50” available to evaluate it
  • The CS50 programming environment provides tools to evaluate the quality of code in terms of correctness, design, and style, including a command line tool called “check50” that checks for correctness, and “style50” and “design50” tools that provide feedback on style and design
  • Testing code is an important aspect of programming, not just for grading, but also in the real world, where colleagues or oneself would write tests to ensure that systems are designed correctly, with tools like “check50” available to help find mistakes
  • The “design50” tool, available in VS Code, provides qualitative advice on how to improve code, and users can also ask humans for feedback on their code, making it easier to improve design and style
  • After ensuring correctness, design, and style, users can move on to solving real-world problems, starting with simple ones, and can use the tools and feedback provided to improve their coding skills

5.4.2.14 Mario

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

int main(void)
{
    for (int row = 0; row < 3; row++)
    {
        for (int col = 0; col < 3; col++)
        {
          printf("#");
        }
      printf("\n");
    }
}

Here’s the next version of the bricks with a constant n

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

void print_row(int n);

int main(void)
{
    // Constant n
    const int n = 3;
    for (int i = 0; i < 3; i++)
    {
        print_row(n);
    }
}

void print_row(int n)
{
    for (int i = 0; i < n; i++)
    {
        printf("#");
    }
    printf("\n");
}

Here’s the final version modulized with input from user

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

void print_row(int bricks);

int main(void)
{
    // Constant n
    const int n = 3;
    for (int i = 0; i < 3; i++)
    {
        print_row(i + 1);
    }
}

void print_row(int bricks)
{
    for (int i = 0; i < bricks; i++)
    {
        printf("#");
    }
    printf("\n");
}

5.4.2.15 calculator.c

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

int main(void)
{
    int x = get_int("x: ");
    int y = get_int("y: ");

    int z = x + y;

    printf("%i\n", z);
}
  • We can eliminate the variable “z” and directly print the result of the addition, which simplifies the code and reduces the chance of bugs
#include <cs50.h>
#include <stdio.h> 

int main(void)
{
    int x = get_int("x: ");
    int y = get_int("y: ");

    printf("%i\n", x + y);
}
  • You can simplify the code, however, it is important to consider the design and readability of the code, as well as the potential for future changes or additions to the program. This is an example of bad code design:
#include <cs50.h>
#include <stdio.h> 

int main(void)
{
    printf("%i\n", get_int("x: ") + get_int("y: "));
}

Doubling calculation

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

int main(void)
{
    int x = get_int("x: ");

    printf("%i\n", x * 2);
}

But what if we want to write a proper program

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

int main(void)
{
    int dollars = 1;
    while (true)
    {
        char c = get_char("Here's $%i. Double it and give it to the next person?\n", dollars);
        if (c == 'y')
        {
            dollars *= 2;
        }
        else
        {
            break;
        }
    }
    printf("Here's $%i\n", dollars);
}
  • However, the code eventually encounters a problem where the number becomes too large to be stored, due to the limited number of bits available to store integers, typically 32 bits, which can only count up to 4 billion, due to interger overflow

5.4.2.16 Integer Overflow

  • Integer overflow is a fundamental problem with computers where if you count high enough, things will just start to break, especially when using languages like C or C++ that do not anticipate this issue, and it occurs because there is a finite amount of memory
  • When using a limited number of bits, such as 32 bits or even just three bits, you will eventually overflow, and this can be demonstrated with a simple example of counting in binary using three bits, where attempting to count to 8 results in an overflow and wrapping back to 0
  • One way to avoid integer overflow is to use a longer data type, such as a long, which is typically 64 bits and can count much higher than an int, but it is still finite and will eventually overflow if you need a 65th bit that the computer has not allocated.

5.4.2.17 Boeing

  • A real world issue with integer overflow occured with the Boeing 787 airplane. It could lose all electrical power after 248 days due to the generator control units going into failsafe mode, which was caused by a software counter overflow.
  • The software counter overflow occurred because Boeing used a 32-bit integer to count tenths of seconds, and after 248 days, the counter would overflow, causing the plane’s systems to malfunction
  • The solution is to reboot the plane. This resets all variables back to their original values, giving the system more time before the counter would overflow again, and this solution was used until the actual software issue was fixed.

5.4.2.18 Pacman

  • The original Pac-Man game from the 1980s had a limitation of only 255 levels due to its use of 8 bits, which can represent 256 values, but since counting starts at 0, it can only go up to 255
  • When skilled players reached level 256, the game exhibited unusual behavior, such as fruit overwriting other elements on the screen, because the game’s makers did not anticipate anyone reaching that level and did not allocate sufficient memory or implement a condition to handle this scenario

5.4.2.19 Truncation

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

int main(void)
{
    int x = get_int("x: ");
    int y = get_int("y: ");

    printf("%i\n", x / y);
}
  • When working with integers in programming, using big integers with 64, 128, or 256 bits is possible, but it requires a language or library that can dynamically allocate memory, which many languages do not support by default
  • int returns int values only
  • Potential solutions: format code with type casting or modifying the program to handle decimal numbers

5.4.2.20 Type Casting

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

int main(void)
{
    int x = get_int("x: ");
    int y = get_int("y: ");

    printf("%f\n", (float) x / y);
}
  • To format a float to a specific number of significant digits, the printf function can be used with a syntax that includes numbers in between the percent sign and the letter, such as “.5” to format the number to five significant digits
#include <cs50.h>
#include <stdio.h> 

int main(void)
{
    int x = get_int("x: ");
    int y = get_int("y: ");

    printf("%.3f\n", (float) x / y);
}
  • Formatting floats in printf %.#f
#include <cs50.h>
#include <stdio.h> 

int main(void)
{
    int x = get_int("x: ");
    int y = get_int("y: ");

    printf("%.50f\n", (float) x / y);
}
  • Floating-point imprecision is due to the way computers represent numbers with binary. This leads to small errors in calculations, and this imprecision can be observed when calculating simple divisions, such as 1 divided by 3, which results in a long string of digits that may not be entirely accurate

5.4.2.21 Floating-Point Imprecision

  • The issue of floating-point imprecision is similar to the problem of overflow, where the limited number of bits used to represent numbers can lead to mistakes in code, and using a finite number of bits means that only a limited number of patterns and thus a limited number of floating point values can be represented

  • The use of a finite number of bits to represent numbers means that computers can only represent a limited number of real numbers, which is a challenge because there are infinitely many real numbers in the world, and this limitation can be mitigated by using more bits, such as switching from float to double

  • A historical example of a similar problem is the Y2K problem, where computers were using only two digits to represent years, which caused concerns about what would happen when the year 2000 arrived, but the world was able to update its systems in time to avoid major issues

  • A similar problem is looming on the horizon, where computers have been using 32-bit integers to keep track of time, which will eventually max out and cause clocks to overflow on January 19, 2038, potentially causing problems, but this can be solved by using more bits

  • The solution to these problems is to use more bits, which is now more feasible due to the increased availability of storage, and this can be achieved by throwing both hardware and software at the problem

  • The problem of floating-point imprecision and overflow is not limited to floating-point numbers, but also applies to other areas, such as keeping track of time, and it is essential to be aware of these limitations to avoid mistakes in code and to find solutions to these problems

5.4.3 Arrays

5.4.4 Memory

5.4.5 Data Structures

5.4.6 Python

5.4.7 Artificial Intelligence

5.4.8 SQL

5.4.9 HTML, CSS, JavaScript

5.4.10 Flask

5.4.11 The End

5.4.12 ACE Reccomendation