Review of last time

Logging in to the server:

Editing, compiling, linking, and running

When you first login to the server, you are in the shell. The shell is different from C++. It is similar to the desktop on Windows or Mac; it’s a place from which you can start programs and look at your files, but it’s different from the programs/files themselves. Most of the things I’m going to show you today are shell commands, which means they will only work when you are in the shell; they won’t work in your C++ programs.

Review:

(A lot of this is covered in the FC CSci server handout on the website.)

To start on the first assignment, you can use the do-assignment command:

do-assignment 1

This will open all the .cpp files from assignment 1 in Micro for you to edit.

When you log in you are in your home directory. This is roughly equivalent to Documents on Windows, desktop on Mac. It’s where your stuff goes. It takes the form of

/home/cs/username/

(replace username with your username)

But I should back up.

Paths

This whole thing is called a “path”. A path is a sequence of directory names, separated by forward slashes, possibly ending in a file name.

If it ends in a directory name, then a path identifies that directory (like the home directory above). If it ends in a file name, it identifies a file.

E.g., suppose you have a subdirectory of your home named “projects”, containing “project.cpp”. Then the full path of that file is

/home/cs/username/projects/project.cpp

while the full path of the directory it is in is

/home/cs/username/projects/

(Directory is the technical term for “folder”.)

If you ever forget what directory you are in, you have two options

The prompt

What it tells you:

What’s the ~ in the prompt? ~ is a shortcut for “your home directory”. That is, ~ means exactly the same thing as /home/cs/username/. You’ll notice as you move around, the prompt will change. E.g., if we moved into the aforementioned “projects” subdirectory, it would show ~/projects indicating that you are in the projects subdirectory of your home directory.

Moving around

You can use the cd command to move down a level, into a subdirectory.

E.g., if you are in your home directory, and you want to move down into the projects subdirectory, you would do

cd projects

The prompt will change, and if you type pwd it will print /home/cs/username/projects.

You can in fact type an entire path. E.g., if you had projects/potato/ you could change into it from home by doing

cd projects
cd potato

or you could do it in one step by doing

cd projects/potato

Moving up a level

If cd subdirectory moves down a level, how do you move back up?

The special directory .. always means “one level up from current”. So if you are in projects, and you do

cd ..

Where will you be? In your home. You can use .. in paths. E.g.

../projects

would first move up one level, and then go down into projects.

Example:

Suppose we had this directory structure

/home/cs/username
  │
  ├─── projects/
  │       │
  │       ├──── codename/
  │       └──── agi/
  │
  ├─── practice/
  │
  ├────── my_notes.txt
  │
  └────── assignments/
              │
              └──── assign1/
                     │
                     ├──── main.cpp
                     ├──── utility.cpp
                     └──── utility.h

(The first time you run do-assignment, it will create projects, practice, and assignments for you.)

Starting from home/cs/username, how do we get to

Creating new directories

You can use the mkdir command to make a new subdirectory in the current directory:

mkdir subdirectory

I’d suggest making yourself a “work” directory, for experiments and things that aren’t connected to any particular assignment:

mkdir ~/work

(By using ~, we create work as a subdirectory of your home directory, regardless of where you currently are.)

Listing stuff

When you’re in a directory, how do you know what’s in it?

ls

will print all the files and subdirectories in the current directory.

ls -l

will print a longer listing, with more details. (File size, modification date, etc.)

If you want a bigger picture, use tree:

tree

It will print all the files in the current directory, and all subdirectories, and all the files in those, and so forth, all the way down. (Demonstrate)

You can also start tree from any directory of your choice. For example, this will start it at your home directory

tree ~

You might want to run this after your first few commands to create new files/subdirectories, to see how they affect the total structure.

Copying and moving files

To copy a file from one place to another, use

cp path1 path2

E.g.,

cp practice/practice3/main.cpp ~/projects/agi/test.cpp

This will make a copy of a file, in a new path.

To move or rename a file, you can use:

mv path1 path2

Finally you can (permanently!) delete a file using

rm filename

There’s no way to get a deleted file back, so be very careful with this!

Working on assignments

Assignments are posted every Sunday (sometimes Monday morning). You can download a specific assignment to the server using the command

do-assignment #

replacing # with the number of the assignment you want to download. This command will download the assignment’s file(s) into ~/assignments/assign#/ and then ask if you want to open them in Micro. If you answer y (yes), all the assignment files will be opened.

If you want to resume an assignment that you were working on before, you can two options:

do-assignment also automatically creates directories ~/projects and ~/practice, so you are ready to go for working on the projects and practice problems.

Working in Micro

Micro has a number of keyboard shortcuts, some of which will be familiar:

Command Description
Ctrl-S Saves the file you are editing
Ctrl-O Opens a different file for editing
Ctrl-Q Quits micro, taking you back to the shell
Ctrl-T Opens a new tab containing a new file for editing
select with mouse Select some text for operations
Ctrl-C Copy selected text
Ctrl-V Paste previously-copied text
Ctrl-X Cut selected text (copy and then delete)
Tab (with selection) Indents the selected text one level
Shift-Tab Unindents one level
Ctrl-B Run a shell command without quitting micro

You should save (Ctrl-S) often, as Micro sometimes crashes. Note that you can use Ctrl-T to open more than one file in Micro: just press Ctrl-T, then Ctrl-O and type the name/path of another file you want to open. You can also do this when starting Micro:

micro file1.cpp scratch.cpp

will start Micro with two tabs open, one for each file.

Ctrl-B is useful because it allows us to compile, and run, C++ programs without leaving micro. If you are editing scratch.cpp in Micro and you want to try it out, just do

  1. Ctrl-S to save

  2. Ctrl-B and type compile scratch.cpp and press Enter, to compile

  3. Ctrl-B and type ./scratch and press Enter, to run

Advanced Micro commands

Micro has a kind of “internal shell” that accepts a different set of commands. You can access it by pressing Ctrl-E, typing a micro command, and pressing Enter. The most useful commands are probably

The C++ Programming Language

Parts of speech

The traditional first program in C++ looks like this:

/*
 * hello.cpp
 * Prints hello world! 
 */
#include <iostream>
using namespace std;

int main() 
{
    cout << "Hello, world!" << endl;
}

You can type this into a file (and you should!) and compile, link, and run it, and see what it does.

What are the basic components from which a program is built? What kinds of things correspond to “punctuation” vs. “words” vs. upper and lower-case? That’s what we’re going to look at today.

There are some broad categories that you can break things up into (you might want to take a separate piece of paper and write these on it, and put it at the beginning of your notes, so you can add to it when we discuss new things).

The two most important/difficult parts of C++ are statements and expressions; we’ll spend most of our time learning new forms of them, and new ways of putting them together.

The difference between statements and expressions is sometimes subtle. Think of the sentence “Go to the store and buy whatever brand of grape soda is on sale.”. The whole sentence is a command, an instruction to do something. “whatever brand of grape soda is on sale” is not a command, rather, it is a description of some particular thing that the command depends on. Similarly, expressions describe or compute things: values, objects, whatever you want to call them. An expression gives you a value, but it doesn’t say what to do with it. In order to say what should happen with it, you have to embed that expression into a statement.

Some basic points to touch on first:

The template program

Initially, every program you write will have this template:

/*
   name.cpp
   Description

   Your Name
   Date
*/
#include <iostream>
using namespace std;

int main() 
{
    // Stuff goes here
}

All the interesting bits will be between the curly braces.

Special names

In C++ there are some names that are special. By special, I mean special the way “the” and “it” are special in English. You can’t substitute another word for them. On the other hand, if a sentence has a noun in it, you can replace it with another noun and it will still make grammatical sense.

Example:

I ate all the cookies.

I can’t change “the” into anything else; it’s special and required. On the other hand, I can replace “I” with another proper noun or pronoun (“You”, “She”, President Trump"). Similarly, 'ate’ can be replaced with a verb, “all” with another quantifier (“some of”, “most”, “none”), and “cookies” with any plural noun. Now, if I said something like

I ate all the numbers.

That doesn’t make sense, but it is grammatical. The problem with it isn’t one of the words being in the wrong order.

I’ll point special names out as we go along, but here are the ones in this program:

int: int is short for “integer”, meaning “whole number”. It’s the name of a type. We’ll talk about types later, but for now, just know that int is one of the built-in ones that stores whole numbers, both positive and negative, within some range (generally plus-or-minus some very large number).

main: Every C++ program needs an entry point, a place where it starts. This is usually called main (although it depends on what kind of system you are working on; on Windows it’s called WinMain and yes, capitalization matters to C++). For now, virtually every program you write will have a main and that’s where all the interesting stuff goes.

using namespace: “using namespace” is actually a single thing, even with the space in the middle. There are other things that start with using (all of these are collectively called “using-declarations”) but for now, all our programs will start with this one

using namespace std;

std is not something special, it’s just a normal name. It’s like a noun in a sentence: changing it changes the meaning of the declaration, but it’s still a declaration. On the other hand, if we wrote:

using potato std;

that’s no longer a declaration at all, but just nonsense.

A longer program

/*
   bmi.cpp
   Computes the user's BMI.

   Andy Clifton
   Feb 1 2017
*/
#include <iostream>
using namespace std;

int main() 
{
    // The formula for BMI is 703 * weight / (height * height) 
    // where weight is in pounds and height is in inches

    int weight = 0;
    cout << "What is your weight, in pounds? ";
    cin >> weight;

    int height = 0;
    cout << "What is your height, in inches? ";
    cin >> height;

    int bmi = 703 * weight / (height * height);
    cout << "Your bmi is " << bmi << endl;
}

Let’s walk through this.

cout – cout is the name of the box containing something that represents the screen. << “sends” the thing(s) on its right, to the thing on its left, so in this case, cout << whatever means “print whatever”. Whatever can be a string literal (as we saw) or it can be the name of a box (to print whatever is inside that box).

cin is the name of a box containing something that represents your keyboard. >> “extracts” something from the thing on its left, and stores it on the thing on its right (note that the thing on its right must be the name of a box; it has to be someplace where we can store things).

When we write int bmi = ... we are not only creating the box, but storing something in it. Instead of reading it from the keyboard, we’re calculating it from the existing boxes height and weight.

Statements

A statement is a single “do something”. The statements we’ve seen so far:

Every statement ends with a semicolon. Remember, that’s the “period” on C++‘s sentences.

What about an empty statement? Can we do this?

cout << "Hello ";
;
cout << "world!" << endl;

Yes, in fact, you can. But at the same time, the empty statement doesn’t do anything. You might wonder about a do-nothing statement, when statements are “do something” things. There are a few places in C++ where you must put a statement. So what if you don’t want anything in particular to happen in those places? Just put a lone semicolon, and nothing will happen.

Blocks

A sequence of statements enclosed in curly braces is called a block. You can use a block anywhere where a statement is allowed, and it counts as if it was just one statement. What does this mean? It means we could (but shouldn’t!) rewrite the above as

int main() 
{
    // The formula for BMI is 703 * weight / (height * height) 
    // where weight is in pounds and height is in inches
    {
        int weight;
        cout << "What is your weight, in pounds? ";
        cin >> weight;

        {
            int height;
            cout << "What is your height, in inches? ";
            cin >> height;

            {    
                int bmi = 703 * weight / (height * height);
                cout << "Your BMI is " << bmi << endl;
            }
        }
    }
}

Also note how I’ve indented things? that’s kind of a convention; we use indentation to show structure. Your program is kind of like an outline, with statements inside of blocks inside of definitions. Using indentation helps make it clear what 'level’ something is at.

(Maybe mention how names are local to blocks, and aren’t visible outside the current one?)

You can even use an empty block, as another form for the empty statement:

cout << "Hello ";
{}
cout << "world!" << endl;

Note that while you can use a block anywhere you can use a statement, the converse is not necessarily true. You can’t always replace a curly-brace block with a single thing. For example, you can’t rewrite

int main() 
{
    // Does nothing at all
}

with just

int main() 

That won’t work. There are a few other places where blocks are absolutely required; I’ll point them out when we get to them.

Chains of >> and <<

When we do something like this

cout << "Hello, world!" << endl;

Why does it print out both the string literal, and the end-of-line?

It has to do with how the << works, when you put them in a row like this. Think of it as similar to how “1 + 2 + 3” works. First we do 1+2 and get 3, which leaves us with 3+3. Then we do that and get 6.

First we do cout << "...". That prints, but then it reduces to cout again. So now we have cout << endl. That prints the end of line, and then reduces to cout;. That doesn’t do anything. Just a name by itself is a perfectly valid statement, but it doesn’t do anything. You could write

int bmi = ...;
bmi;

If you want, you could even write

12;

and the computer won’t complain, it just won’t do anything.

The reason this behavior is allowed is for things like cout <<, where its useful to have something left in case we want to continue the chain, but if we don’t, it just does nothing at all.

(Technically, the idea here is that any expression can also be a statement. We’ll talk about expressions next week.)

Step-by-step execution

Walking through your program, either on paper or in your head, is a very useful skill to have. Sure, you can just run it and see what happens, but what will you do if it doesn’t work right? How will you find the spot in your program where what it actually does diverges from what you want it to do?

Let’s walk through the process of executing this program, line by line (starting with the first line inside main):

We’re going to need some space representing memory, where we’ll draw our boxes, and a representation of the screen, where we’ll write our output. (Draw)

int weight;

What does this do? (Creates a box named “weight”, draw box)

cout << "What is your weight, in pounds? ";

(Writes the text to the screen.)

cin >> weight;

What does this do? (Reads from the screen) What do we want to type in? (Write in the weight box)

int height;

(Box named height)

cout << "What is your height, in inches? ";

(Prints some text)

cin >> height;

(read into height box)

int bmi = 703 * weight / (height * height);

(Create box named bmi, and then stores the result of the calculation from the other boxes’ values into it. Walk through the order of operations in the expression. Note that the = here is very different from the equals in algebra. Here, it’s a one way thing: take the thing on the right, and store it in the box on the left; there must be a box on the left, but the right can be a calculation, as here, or a literal value, or another box.)

You might wonder, since we can both create the bmi box and store a value in it, can we do the same thing with the other boxes? That is, can we do something like

cin >> int weight; // or
int weight << cin;

Unfortunately, no. The first one doesn’t work because the thing on the right isn’t the name of a box, it’s something that creates a box. The second one doesn’t work because only an = is allowed after int weight. And we can’t do

int weight = cin;

Because cin isn’t a number; it’s some kind of thing that represents the keyboard. So creating a box and reading its value from the keyboard must be a two step process.

You might then wonder, what is the value in the box weight before we fill it in? The answer is, it’s undefined. That means we don’t know what’s in there. I draw the box as empty, but there is a value in there, it’s just one we don’t know (and it might change from one run of the program to the next, or from my computer and yours, that’s why its undefined!).

cout << "Your BMI is " << bmi << endl;

(This prints more than one thing. First the text, then the value in the bmi box, and finally the endl. Note that we could also have written this as

cout << "Your BMI is ";
cout << bmi;
cout << endl;

)

In fact, if we wanted to, we could skip the creation of the bmi box completely, and embed the calculation in the printing:

cout << "Your BMI is ";
cout << (703 * weight / (height * height));
cout << endl;

But here it’s not totally clear what this calculation represents. Creating a variable named bmi, and then storing the result of the calculation in it, makes it absolutely clear that the result of the calculation is the bmi.


Does tracing through the program make sense? Do you think you could do it if I gave you an example, on paper on your own?

These programs don’t read anything from the keyboard, and only prints something at the end, so you really only need to worry about the boxes inside it.

Problem 1:

int a = 1;
int b = 2;
int c = 3; 
int d = 4;

a = b + c;
b = d - c;
c = d - a;
d = b + c;

cout << "a = " << a << 
   " and b = " << b << 
   " and c = " << c << 
   " and d = " << d;

Problem 2:

int x = 5;
int y = -12;

x = x + y;
y = x - y;
x = x - y;

cout << "x is " << x << endl;
cout << "y is " << y << endl;

Walking through it:

x = x + y; // x = -7
y = x - y; // y = 5
x = x - y; // x = -12

These three lines have the effect of swapping the values in the two boxes.

Statement flow

I left it implicit, assuming that you’d figure it out, but I should mention the “flow of control”. This just means, how do we move from one statement to the next (or rather, when we’re looking at one statement, what is the next statement). For now, it just flows from one statement to the next, straight through the program. If we write all our statements on separate lines (as we’ll do for now), then things just flow top to bottom.

This is true even if we mix things up with blocks: each block is executed straight through, beginning to end, so

cout << "Hello ";
{
    cout << " to ";
    cout << " you ";
}
cout << "and your friends!" << endl;

Is just the same as if we wrote it without the block:

cout << "Hello ";
cout << " to ";
cout << " you ";
cout << "and your friends!" << endl;

In a bit we’ll explore ways to make our programs more interesting, by breaking up the flow of control. We might want to choose between two different “paths” of statements, based on some criteria, or maybe we want to repeat some statements a number of times.

Basic Input and Output

(input and output is usually abbr. to I/O)

We’ve already used some basic I/O, via cin and cout. We can do things like this:

cout << "Hello, world!" << endl;
int magic_number = 12;
cout << "Your magic number is " << magic_number << endl;

We can print string literals, we can mix string literals with variables (box names), allowing us to print messages that have some fixed parts, that are always the same, and some parts the vary depending on the values of boxes. We can even print the results of calculations:

cout << "The square of x is " << (x*x) << endl;

Let’s take a look at some ways we can control how things are printed.

float radius;
cout << "Enter the radius of a circle: ";
cin >> radius;

cout << "The area of the circle is " (3.14159265359 * radius * radius) << endl;

float is another type, like int. It stands for “floating point”, which is a programming term that basically means “numbers that can have a decimal point”.

Reading multiple inputs from a single line

In the BMI calculator, we read in height and weight separately, on separate input lines. Can we have the user input them on the same line? Yes:

cout << "Enter your height and weight, separate by a space: ";
cin >> height;
cin >> weight;

(It would work the same if we split it up like this:

cin >> height >> weight;

but that way has disadvantages, see below.)

How does this work? cin will automatically skip over any whitespace before it tries to read an input. Whitespace means spaces, tabs, hitting enter, etc. When it’s reading height, it will stop when it encouters whitespace. When it starts reading width, it will skip over whitespace, and then start reading. So your input can actually look like this:

> 72            165

with a whole bunch of spaces and tabs between.

What happens if cin doesn’t read something it can recognize as a number? E.g., if we do

int age = 0;
cin >> age;

and the user types “potato”?

Unfortunately, two things happen

We’ll look at how to recover from badness later, but for now, this is the reason why we generally prefer

cin >> height;
cin >> weight;

to

cin >> height >> weight;

because the earlier one gives us the opportunity to check for “badness” in between and try to fix it.

For now, you can safely assume that the user will never make mistakes when typing things in to your program. :)