Command Palette

Search for a command to run...

MTH 4300

Lecture 2

WIP

This lecture is still a work-in-progress. Feel free to preview it, but note that major sections are still incomplete

Introduction to the terminal

The terminal is a text-based interface that allows us to interact with the computer's operating system.

Navigating the terminal at the end of the day is an essential skill for software engineers, which is why we'll be spending some time navigating the terminal and some basic commands.

Terminal apps

You have an array of choices when it comes to terminal emulators.

Some of the most popular options these days are the following:

If you're curious about what I'm using, it's a newer terminal emulator called cmux which runs libghostty under the hood which is the same core terminal emulation engine that Ghostty uses.

Of course you're also free to just use your stock terminal which should be Terminal on macOS and Powershell in Windows.

Note that if you decide to use Powershell on Windows, you may have a different set of commands that you'll run. I'll do my best to provide the equivalent command, but you may have to use AI or Google to figure it out.

Windows Subsystem for Linux

Another option for Windows users who want an experience closer to UNIX systems is to use WSL (Windows Subsystem for Linux). This allows you to install a Linux distribution on your machine and run the commands that macOS users are using as well.

You can find more details here about this feature. Highly recommend it given how finnicky it can get to work with Windows!

Step-by-step tutorial

We'll approach learning the terminal by creating a directory called mth-4300/ at our home directory

  1. Figuring out where you currently are in the terminal

    Suppose that you've opened the terminal, most of the time you'll start at the home directory, but if you find yourself somewhere else, how do you figure out the path to your current directory?

    pwd
  2. What is in the current directory?

    Now that you're in some directory, how do you know what files and directories are nested within your current directory? To get a list of files and directories you can use the following commands

    ls

    We do have to note though that there are files that are typically hidden when using the above command. These hidden files typically start with a . such as .gitignore or .env.local

    In order to force these to show up in the terminal, we have to run an alternative set of commands.

    ls -la
  3. Navigating the file system with the terminal

    In order to navigate to our home, we can use the following command

    cd ~
    # or
    cd 

    However, the cd command is more powerful than that. We can use the cd command in order to jump to any directory as long as we know the path to to it.

    Suppose that we have the following directory structure:

    ~/
    - documents/
        - mth-4300/
    - downloads/
        - textbooks/

    Suppose that I wanted to jump to textbooks. How would I do that?

    cd ~/downloads/textbooks

    There are also relative paths we can take. Suppose now that I'm in ~/downloads/textbooks but now I want to go up to just ~/downloads/. To get up there, I would have to enter the following command into the terminal

    cd ..

    If you wanted to go up several parent directories, then you'll have to do something like the following

    # goes up two directories
    cd ../..
    # goes up three directories
    cd ../../..
  4. Creating a directory and a file

    Now that we're in a directory where we want to create out mth-4300 directory. How do we go about doing that?

    mkdir mth-4300

    Now let's cd into that newly created directory and create a test.cpp file. To create this file, we'll need to run the following commands after we cd into mth-4300

    touch test.cpp
  5. Copying files and directories

    Suppose that you want to create a copy (not deleting the source) of a file or a directory. Let's say that we want to create a new file called test2.cpp from the content of test.cpp

    cp test.cpp test2.cpp

    Now suppose that we have a directory called project-template/ and we want to create a new project called todo/.

    cp -r project-template/ todo/
  6. Moving/renaming files

    Note that cp duplicates the resource. If we want to make sure that we're moving the resource to a new location then we'll have to use the mv command

    mv test.cpp test_deprecated.cpp
  7. Deleting files and directories

    To delete a file, we use the rm command. Note that you should generally be careful what you're deleting because this could damage your operating system.

    rm test.cpp

    For directories, you'll use the infamous rm -rf command

    rm -rf todo/

It'll take time to become comfortable with the terminal, but it's a worthy investment!

Types in C++

Types

In Python, types are inferred from the value or are hinted.

For example, this was how we could initialize variable with and without types.

Python variable initialization
name = "morty"
another_name: str = "rick"

Modern C++ actually works in a similar manner! Except we don't consider typing a variable a hint. Providing the type is actually the default behavior

C++ variable initialization
#include <string>

auto name = "morty"
std::string another_name = "rick";

Note that the auto keyword allows us to infer the type from the right-hand value. These days, it's considered a best practice to use the auto keyword especially if you're initializing the variable.

Declaration vs initialization

Something that wasn't prevalent in Python is the idea of declarations. In C++, you're allowed to declare a variable without assigning it a value.

Declaration vs initialization
int declared_variable;
int initialized_variable = 10;

Declarations are a way to reserve space for a variable without needing it to have a value right away.

The different ways we learn how to reserve or request space for data in C++ is part of the memory control that we're exposed to with the language. The distinction will become a lot more obvious in the future once we demystify the distinction between stack and heap allocations

Data types in C++

Numbers

When we were in Python, we had two types for numbers: int and float. Complexities around overflows and size of the number were abstracted away into something that just works.

C++ uncovers this layer of abstraction for us by forcing us to choose the type for our number.

int

You would declare your variable to be an int if you wanted to store whole numbers. However, like I mentioned before, our choice of type is driven by how large of a number we expect to store in this variable. When you choose to use an int, you are guaranteed that the int is at least 16 bits wide.

Different hardware and compilers can choose a larger size as long as it meets the minimum. You'll see that in practice,

Platformsizeof(int)
x86-64, ARM644 bytes (32 bits)
Old 16-bit embedded systems2 bytes (16 bits)
Some historical systems8 bytes (64 bits)

In most cases, this means that int will have a size of 32 bits. So the range of values that fit within an int fall between [−231,231−1][-2^{31}, 2^{31} - 1]

We also have something called an unsigned int which has the same size as int, but does not allow for negative numbers. This means that the range of values it falls within actually doubles on the positive side. Therefore, the range of values for an unsigned int within a 32-bit system is [0,232−1][0, 2^{32} - 1]

Examples
int a, b, c;

int signed_integer = 10;
unsigned int index = 0;

long long / long long int

You would use long long if you wanted to store whole numbers that are at least 64 bits wide. Because we know that it's at least 64 bits wide, then the range of values should fall from [−263,263−1][-2^{63}, 2^{63} - 1]

There is also a long type, but because of its cross-platform behavior, it's recommended to use long long if we want to guarantee at least 64 bits.

  • By cross-platform behavior, I meant to say that Windows will have a different size for long depending on whether you're using a 32-bit or 64-bit system. MacOS and Linux both treat long as something that's at least 64 bits wide.
Examples
// A common thing to do is create a type alias for long long
typedef long long ll;

ll a_number = 100000;
long long result = 0;

float / double

If you need real numbers, then float and double are the types you'll need.

The difference between the two types is the amount of precision you have with the decimal places.

  • float has about ~6-7 significant decimal digits
  • double has about ~15-16 significant decimal digits

In most cases, you'll want to use double unless memory or performance is a hard constraint.

Examples
float a = 1.234567;
double b = 1.234567891;

Booleans

bool

Characters

char

std::string

Type Casting

I/O operations

Operators in C++

Arithmetic operators

Increment and decrement operators

Comparison operators

Assignment operators

Logical operators