CS 312 - Week 1.1
CS 312 Audio Programming Winter 2020

Table of Contents

1.1 Class

WCC 138 Lab Setup

The /StuWork/<email_name> folder inside the courses folder is where you'll save your files before you submit your homework. The hand-in is where you'll submit your homework when finished. We'll set up scripts that make it possible to work during class in the WCC lab and finish your homework in any CMC lab using the course folder. We'll also set up a backup folder inside your CMC home folder as a safety net.

There is only one user account in that lab and her/his name is labuser. You'll have to go through these steps at the beginning of each class. The steps to setup your account in CMC are similar and will be explained in the CMC Lab Setup section below.

1. Start the Mac and login.

2. Mount your courses folder for CS312

Choose Go to Server from the Go menu in Finder.

hw1110.png

Login with your Carleton email name and password.

Mount your cs312 courses folder.

smb://courses.ads.carleton.edu/COURSES/cs312-00-w20

hw1111.png

A courses folder icon will appear on the Desktop.

hw1112.png

3. Open Mac Terminal in /Applications/Utilities

4. Execute setup312 your_email_name

Type this command and press Return.

setup312 <your_email_name>

Type this command to display your current directory
The # is comment. You don't have to type comments.

# This is a comment. Read and learn but don't type
# Print Working Directory
pwd
# should display something like
/Volumes/COURSES/cs312-00-w20/StuWork/<your_email_name>

Execute this command.

echo $HOME312
# should display same thing
/Volumes/COURSES/cs312-00-w20/StuWork/<your_email_name>

If everything worked continue. If not ask me for help.

Terminal Commands

The terminal runs a command line application called a shell. There are many shells available. Mac OS uses bash.

Quit and restart Terminal.

Test the following commands.

echo $PATH

You want to see
/Volumes/COURSES/cs312-00-w20/StuWork/<your_email_name>/bin
at the beginning of the $PATH.

Aliases
Define typing shortcuts for lengthy commands
Prints a list of all defined aliases.

alias

Decimal to Hex and Hex to Decimal
Functions written as a bash script.

dtoh 147 #Decimal to Hex

You should see 0x93.

htod 0xC5 #Hex to Decimal

You should see 197
You can view the code for these two bash functions in .bashrc.

ls variations for listing files in a directory. Try each.

cd           # go to your account home directory
ls           # default listing
ls -l        # long listing
ls -a        # list hidden files, omit . and ..
ls ls -d */  # directories only
ls -lS       # long listing sorted by size descending
ls -lR       # long and recursive

You can make your own aliases for any commands you use frequently and take too long to type.
You can do this in CMC but not in WCC.
Just add them to .bash_aliases and then execute.

cd
source .bash_aliases

Terminal Keyboard shortcuts

Memorize and start using these Terminal shortcuts.
Ctrl is the Control key not the Command key.

up and down arrow
move backward and forward through your command history
Ctrl-a
Move the cursor to the beginning of the command
Ctrl-e
Move the cursor to the end of the command
Ctrl-k
Delete everything to the right of the cursor
Ctrl-u
Delete everything to the left of the cursor
Option right and left arrow
move the cursor right or left quickly by word boundaries

Copy/paste

Select some text in Terminal and then press the mouse scroll wheel to paste.

Pipes

The vertical bar | is the Unix pipe symbol. It pipes the output of the command on the left to the input of the command on the right. The tail -10 command prints the last 10 lines of history. The grep command searches is a very powerful search command. In this example grep searches for cs312 in your command history.

history | tail -10
history | grep cs312
ls | sort    # Upper case before lower case
ls | sort -f #ignore case

man pages

You can read documentation for any Terminal command, by typing man followed by the command name.

man ls
man bash # very long

Scrolling man pages with the mouse scroll wheel is specific to the Mac. These three commands are universal.

Action command
scroll mouse scroll wheel (Mac only)
page down Ctrl-f or space bar
page up Ctrl-b
quit q

c111_hello.cpp

"Hello world!" as a test message was influenced by an example program in the seminal book The C Programming Language[citation needed]. The example program from that book prints "hello, world" (without capital letters or exclamation mark), and was inherited[citation needed] from a 1974 Bell Laboratories internal memorandum by Brian Kernighan, Programming in C: A Tutorial, which contains the first known version:

https://en.wikipedia.org/wiki/%22Hello,_World!%22_program

Open Terminal in /Applications/Utilities and execute these commands. Execute means typing Enter after you've typed the command.

cd $HOME312
 # IMPORTANT: make certain you are in your courses folder
pwd

If pwd returned /Volumes/COURSES/cs312-00-w20/StuWork/<your_email_name> continue. If not do not continue and ask me for help.

Setup for class11

Copy/paste/execute these commands.

# folder and directory mean the same thing
# the directory and file separator is /
cd $HOME312
mkdir bin
mkdir common
mkdir cs312
cd cs312/
mkdir hw11
cd hw11
mkdir class11
cd class11
touch c111_hello.cpp
touch c112_putto.cpp
touch c113_numberbase.cpp
touch c114_print_overload.cpp
touch c115_arithmetic_types.cpp
touch c116_struct_test.cpp
code .

Important:
Often the last line is not executed and is still showing at the Terminal prompt. You'll have to type Return/Enter to execute it. If a closing return is missing in the last line will still be sitting there. Once all commands have been executed you'll return to a blank prompt. This frequently happens. Always check.

Notes:

#
comments begin with #
cd
Change Directory
mkdir
Make Directory
touch
Create a file
code
Open the class11 directory in Visual Studio Code

When I develop a series of commands like this I often don't get it right the first time. It that case execute one line at a time and observe the results.

Visual Studio Code

Hereafter called vsCode.
The vsCode window should be open and displaying the contents of the class11 directory on the left.

hw1105.png

The vsCode Terminal

vsCode has a built in terminal. Open it using the shortcut below.
Shortcut: Control-backtick

Check output of these commands in vsCode Terminal

# change to your user home directory
cd
# is an alias in .bash_aliases
cd312
# Print Working Directory
pwd
# LiSt files
ls

pwd: It should be /Volumes/COURSES/cs312-00-w20/StuWork/<your_email_name>/cs312
ls: LiSt files in your cs312 directory.

You should see this directory structure in Mac Finder looking at the cs312 folder inside your cs312-00-w20 course folder.

hw1104.png

The bin directory will be used throughout the course to hold executable commands you'll write.
The hw11 directory for your homework assignments and class lab projects.

Folder names
Every class will add a new hwNN folder from hw11 to hw93.
Class projects are kept in a classNN folder.
The first N is week, the second N is class session.
\hw12\ folder is week one, Wednesday.

File names
Class lab projects are prefixed with cNNN_.
The first N is week, the second N is class session, the third N is class lab project number.
\c132_filename\ is week 1, Friday, lab project 2.

cs312/hw11/class11
├── c111_hello.cpp
├── c112_putto.cpp
├── c113_numberbase.cpp
├── c114_print_overload.cpp
├── c115_arithmetic_types.cpp
└── c116_struct_test.cpp

You should finish all class projects on the web page even if they are not specifcally marked as homework. Class projects often contain code that help with the homework.

Execute this command.

echo $PATH
# should display something like at the beginning
/Volumes/COURSES/cs312-00-w20/StuWork/<your_email_name>/bin:

If everything worked continue. If not ask me for help.

For class11 the homework assignments are named

  • hw111_boilerplate.cpp
  • hw112_helloMidi.cpp

c111_hello.cpp
Click the c111_hello.cpp filename on the left and type this code into the c111_hello.cpp window.
hw1106.png

c111_hello.cpp notes

#include <iostream>

#include is C++ directive that tells the compiler which files are required to compile a program.
<iostream> is a C++ library that provides functions to read from standard input and write to standard output. Standard input and output is provided through the Terminal.

#include <file> vs. #include "file"

File names in angle brackets <…> are system library header files that were installed by the operating system and compiler language.

File names in double quotes "…" are user or third party header files that are supplied by the programmer and are required to compile the program.

#include <string>
<string> is a C++ library that provides functions to manipulate a sequence of text characters.
"hello, world"
Text enclosed in double quotes is a C++ string.
int main()
main( ) is a function that takes no parameters and returns an int.
{ }
Curly braces enclose code blocks and are scope delimiters. Any local variables declared with the curlies are allocated on the stack and are only visible to the program within that scope.
}
The closing brace is the closest thing C++ has to garbage collection. When execution reaches the closing }, all local variables declared within that code block are destroyed.
std::cout

cout is the C++ library function that outputs text to the Terminal. If you've done any C programming it's a modern replacement of the printf() function.

std is a C++ namespace. All C++ library functions are declared in the namespace std. The double colons are the namespace scope operator. Tying function names to namespaces helps avoid name collisions that might otherwise occur between C++ libraries, third party libraries, and user defined names.

<< (put to)
The double less than is called the "put to" operator and sends whatever is on the right to the device on the left. In this case the device is the Terminal. It can also be used to write data to a memory locations, strings, and files.
>> (get from)
The double greater than than is called the "get from" operator that reads input from the Terminal and uses it to set the value of the variable on the right.
std::endl
std::endl is the name of a function that outputs a return character, or endline. It is defined in the namespac std.
You can include an endline character in a string using the \n escape character.
; (semicolon)
Normal C++ statements end with a semicolon. There are other uses that you'll learn about as the course continues.

Header and Source files

header files
End with .h (In older code you may see .hh and .hpp used)
Header files are declarations that make constants, variables, and functions visible to other files that #include them.
implementation (source) files
End with .cpp and should be paired with a header file of the same name.
Source files contain code for the functions declared in their header file and often contain many other supporting functions that are not visible to the outside world.

Compile

Execute this command in vsCode terminal. You should read the comments but you don't have to type them.

# clang++ (C Language ++) is the name of the C++ compiler used by Apple
# it is open source and is part of the LLVM compiler suite for many languages
# According to wikipedia its contributors include Apple, Microsoft, Google, ARM, Intel
clang++ c111_hello.cpp

Run

a.out is the default name for executables unless otherwise specified. It's name appeared in the first edition of UNIX in 1971. I'm sure most of you know that the underlying OS used in Macs is a flavor of UNIX.

# ./ refers to the current directory and is required
 ./a.out

Output

hello, world

This time name the output hello using the -o option.

clang++ c111_hello.cpp -o hello

Run

./hello

Output

hello, world

This time name do it all on one line using the cl alias.
The code to the right of the && will only execute if the code on the left was successful.

cl c111_hello.cpp -o hello && ./hello

c112_putto.cpp

<< (put to) operators can be chained together

Open c112_putto.cpp
Copy/paste.

/*
  This example demonstrates the chaining property of
  the "put to" operator<< to std::cout.
*/
#include <iostream>

int main() {
  std::cout << "hello, world" << std::endl;
  // is equivalent to
  std::cout << "hello"
            << ", "
            << "world" << std::endl;
  // is equivalent to
  std::cout << "hello, w "
            << "o"
            << " r l d"
            << std::endl;
  // \n can be used inside a string as a return character
  std::cout << "\nhello,\nworld" << std::endl;
}

Build and Run

Output

hello, world
hello, world
hello, w o r l d

hello,
world

c113_numberbase.cpp

the "put to" operator << can be used to display integers in different number bases
std::dec decimal base 10
std::hex hexadecimal base 16
std::showbase will use 0x prefix with hexadecimal base 16
std::oct octal base 8

Open c113_numberbase.cpp
Copy/paste.

/*
  This example demonstrates formatting integers in decimal, hexadecimal, and octal
*/
#include <iostream>

int main() {
  const int i = 1234;   // decimal base 10
  const int h = 0xBAD;    // hexadecimal base 16 prefix 0x
  const int o = 04567;    // octal base 8 prefix 0

  std::cout << "DECIMAL(dec) HEXADECIMAL(hex) OCTAL(oct)"<< std::endl << std::endl;

  std::cout << "DECIMAL"<< std::endl;
  std::cout << "dec 1234 base(10)\t" << i << std::endl;
  std::cout << "hex 0xBAD base(10)\t" << h << std::endl;
  std::cout << "oct 04567 base(10)\t" << o << std::endl;
  std::cout << std::endl;

  std::cout << "HEXADECIMAL"<< std::endl;
  std::cout << "dec 1234 base(16)\t" << std::hex << i << std::endl;
  std::cout << "hex 0xBAD base(16)\t" << std::hex << h << std::endl;
  std::cout << "oct 04567 base(16)\t" << std::hex << o << std::endl;
  std::cout << std::endl;

  std::cout << "OCTAL"<< std::endl;
  std::cout << "dec 1234 base(8)\t" << std::oct << i << std::endl;
  std::cout << "hex 0xBAD base(8)\t" << std::oct << h << std::endl;
  std::cout << "oct 04567 base(8)\t" << std::oct << o << std::endl;
  std::cout << std::endl;

  std::cout << "AS DECLARED" << std::endl; 
  std::cout << "dec 1234 base(10)\t" << std::dec << i << std::endl;
  std::cout << "hex 0xBAD base(16)\t" << std::hex << h << std::endl;
  std::cout << "oct 04567 base(8)\t" << std::oct << o << std::endl;
  std::cout << std::endl;

  std::cout << "back to hex using int 1234" << std::endl;
  std::cout << std::hex << i << std::endl; // set to hex
  std::cout << i << std::endl;             // remains hex
  std::cout << "WATCH OUT - conversions remain until changed" << std::endl;
  std::cout << "meant to be decimal but forgot << std::dec" << std::endl;
  std::cout << h << std::endl; // set to decimal
  std::cout << std::endl;
}

Build and run

Output

DECIMAL(dec) HEXADECIMAL(hex) OCTAL(oct)

DECIMAL
dec 1234 base(10)       1234
hex 0xBAD base(10)      2989
oct 04567 base(10)      2423

HEXADECIMAL
dec 1234 base(16)       0x4d2
hex 0xBAD base(16)      0xbad
oct 04567 base(16)      0x977

OCTAL
dec 1234 base(8)        02322
hex 0xBAD base(8)       05655
oct 04567 base(8)       04567

AS DECLARED
dec 1234 base(10)       1234
hex 0xBAD base(16)      0xbad
oct 04567 base(8)       04567

back to hex using int 1234
0x4d2
0x4d2
WATCH OUT - conversions remain until changed
meant to be decimal but forgot << std::dec
0xbad

Number base prefixes

You'll notice that all numbers look like base 10 numbers, excluding the bad one. C++ uses standard prefixes for different number bases: 0x for base 16 and 0 for base 8. Try the running c113_numberbase.cpp again after making the two changes underlined in red.

hw1109.png

Build and Run

Output

DECIMAL(dec) HEXADECIMAL(hex) OCTAL(oct)

DECIMAL
dec 1234 base(10)       1234
hex 0xBAD base(10)      2989
oct 04567 base(10)      2423

HEXADECIMAL
dec 1234 base(16)       0x4d2
hex 0xBAD base(16)      0xbad
oct 04567 base(16)      0x977

OCTAL
dec 1234 base(8)        02322
hex 0xBAD base(8)       05655
oct 04567 base(8)       04567

AS DECLARED
dec 1234 base(10)       1234
hex 0xBAD base(16)      0xbad
oct 04567 base(8)       04567

back to hex using int 1234
0x4d2
0x4d2
WATCH OUT - conversions remain until changed
meant to be decimal but forgot << std::dec
0xbad


c114_print_overload.cpp

In C++ two or more functions can have the same name as long as their parameters are of different numbers or types. In this example the print() function is overloaded.

Open c114_print_overload.cpp
Copy/paste.

#include <iostream>
#include <string>

void print()
{
  const std::string str(64, '*');
  std::cout << str << std::endl;
}

void print(std::string msg)
{
  std::cout << msg << std::endl;
}

int main()
{
  print();
  print("\tHello World!");
  print();
}

Build and run

Output

****************************************************************
  Hello World!
****************************************************************

c115_arithmetic_types.cpp

Arithmetic types can be divided into integer types and floating point types. Integer types represent whole numbers, floating point types represent numbers with decimal places. There are different sizes of both types. The size of a type tells how much space it occupies in memory as well as setting its minimum and maximum values.

Integer types
There are six integer types if you count bool which is either true or false. False is defined as zero and true is anything else.
bool    
char signed char unsigned char
short signed short unsigned short
int signed int unsigned int
long signed long unsigned long
long long signed long long unsigned long long

According to Bjarne Stroustrup you should use int unless you have a good reason not to.

Floating point types
There are two floating point types: float and double.
type size (bytes)
float 4
double 8
long double 16

This program displays the size of each arithmetic type in bytes and bits using the sizeof() function.

Open c115_arithmetic_types.cpp
Copy/paste

#include <iostream>

int main()
{
// integer types
    bool mybool;
    char mychar;
    short myshort;
    int myint;
    long mylong;

// floating point types
    float myfloat;
    double mydouble;
    long double mylongdouble;

    std::cout << std::endl;
    std::cout << "Size of variable types in bytes" << std::endl;
    std::cout << "sizeof bool            " << sizeof( mybool ) << std::endl;
    std::cout << "sizeof char            " << sizeof( mychar ) << std::endl;
    std::cout << "sizeof short           " << sizeof( myshort ) << std::endl;
    std::cout << "sizeof int             " << sizeof( myint ) << std::endl;
    std::cout << "sizeof long            " << sizeof( mylong ) << std::endl;
    std::cout << "sizeof float           " << sizeof( myfloat ) << std::endl;
    std::cout << "sizeof double          " << sizeof( mydouble ) << std::endl;
    std::cout << "sizeof long double    " << sizeof( mylongdouble ) << std::endl;

    std::cout << std::endl;
    std::cout << "There are 8 bits in a byte" << std::endl;
    std::cout << std::endl;

    std::cout << "Size of variable types in bits" << std::endl;
    std::cout << "sizeof bool            " << sizeof( mybool ) * 8 << std::endl;
    std::cout << "sizeof char            " << sizeof( mychar ) * 8 << std::endl;
    std::cout << "sizeof short          " << sizeof( myshort ) * 8 << std::endl;
    std::cout << "sizeof int            " << sizeof( myint ) * 8 << std::endl;
    std::cout << "sizeof long           " << sizeof( mylong ) * 8 << std::endl;
    std::cout << "sizeof float          " << sizeof( myfloat ) * 8 << std::endl;
    std::cout << "sizeof double         " << sizeof( mydouble ) * 8 << std::endl;
    std::cout << "sizeof long double   " << sizeof( mylongdouble ) * 8 << std::endl;
}

Build and Run

Output

Size of variable types in bytes
sizeof bool            1
sizeof char            1
sizeof short           2
sizeof int             4
sizeof long            8
sizeof float           4
sizeof double          8
sizeof long double    16

There are 8 bits in a byte

Size of variable types in bits
sizeof bool            8
sizeof char            8
sizeof short          16
sizeof int            32
sizeof long           64
sizeof float          32
sizeof double         64
sizeof long double   128

c116_struct_test.cpp

Struct

A C++ struct is an object that can contain data as well as the functions that process that data. The data can be of mixed types. All data and functions in a struct is public and is visible to any other class that uses it.

Here's a simple example that contains two string types and two functions that print the strings.

struct Hello {
  // delcare struct variables
  std::string str1;
  std::string str2;
  // delcare struct function
  void print();
  void print( const std::string a, const std::string b);
}; // structs end with semicolon

Open c116_struct_test.cpp
Copy/paste

#include <iostream>
#include <string>

struct Hello {
  // delcare struct variables
  std::string str1;
  std::string str2;
  // delcare struct function
  void print();
  void print( const std::string a, const std::string b);
}; // structs end with semicolon

// implement struct function
void Hello::print() {
  std::cout << str1 << str2 << std::endl;
}

void Hello::print( const std::string a, const std::string b) {
  std::cout << a << b << std::endl;
}

int main() {
  // create an Hello struct
  Hello hs;

  // initialize struct variables
  hs.str1 = "Hello,";
  hs.str2 = " World!";

  hs.print();
  hs.print("Hi", " CS 312 :>)");

  hs.str1 = "What's, ";
  hs.str2 = "up?";
  hs.print();

  return 0;
}

Build and Run

Output

Hello, World!
Hi CS 312 :>)
What's, up?

More C++

C++ Libraries

During the course we'll be using functions from these C++ std libraries. The libraries we'll use the most are shown in bold.
<iostream>
<string>
<vector>
<sstream>
<fstream>
<chrono>
<cmath> <random>
<algorithm>
<numeric>
<ios> <iomanip> <regex> <map>

main()

You'll see the main() function called in different ways.

The original main function dates back to C, predating C++. In those days many programs were executed from the command line. The two function parameters allowed data to be passed in to the program. The argc parameter held the number of parameters. The argv was a variable length array that contained the data passed in. Data of different types could be passed in but the program had to have knowledge of the order and type of the parameters expected. If they didn't match, the program failed.

int main(int argc, char const *argv[])
{
  std::cout << "hello, world" << std::endl;
  return 0;
}

These invocations also work if you're not passing data to the executable.

Does not return a value.

void main()
{
  std::cout << "hello, world" << std::endl;
}

Returns a value of zero. The zero return value of a C++ function indicates "success", no errors occurred.

int main()
{
  std::cout << "hello, world" << std::endl;
  return 0;
}

Declares a return value but ignores it. The program exits at the closing brace whether it succeeded or failed.

int main()
{
  std::cout << "hello, world" << std::endl;
}

C++ Comments

⁄ ⁄
The double slash is used as a single line comment. The double slash and any remaining text on that line is ignored by the compiler.
⁄* *⁄
Multiple lines comments are enclosed by /* and */.
/*
  Line 2 comment
  Line 2 comment
  Line 3 comment
*/

It's easy to comment out blocks of code with the #if ... #endif directives.

#if 0 // or #if false
  code statement;
  code statement;
  code statement;
#endif

Operators

Arithmetic
+ add x + y
- subtract x - y
* multiply x * y
% modulo (remainder) x % y
Comparison
== equal to x == y
!= not equal x != y
< less than x < y
> greater than x > y
<= lesss than or equal to x <= y
>= greater than or equal to x >= y
Assignment
= assignment x = y
++ increment (pre) ++x
++ increment (post) x++
-- decrement –x, x--
+= add and assign x += y ⇔ x = x + y
-= subtract and assign x -= y ⇔ x = x - y
*= multiply and assign x *= y ⇔ x = x * y
/= divide and assign x /= y ⇔ x = x / y
%= modulo and assign x %= y ⇔ x = x % y
Logical
&& and if (x && y) == true
|| or if (x || y) == false
! not if x != y
Bitwise
& and 1010 & 0010 = 0010 (10 & 2 = 2)
| or 1010 \vert 0100 = 1110 (10 & 4 = 13)
^ xor 1010 ^ 1001 = 0011 (10 & 9 = 3)
<< shift left 0010 << 1 = 0100 (2 << 1 = 4)
>> shift right 1000 >> 1 = 0100 (8 >> 1 = 4)

CS 312 C++ style guidelines

A lot of CS 312 style formatting happens auto-magically when you save your files in vsCode, but it can't do everything. These are additional guidelines you should follow for CS 312.

Naming Conventions - snake_case and camelCase

C++ standard libraries and TCPP2 use snake case. Many other third party libraries uses camel case. We'll use a mixture of both styles.

Snake case
a_variable_using_snake_case // preferred
Camel case
aVariableUsingCamelCase

Variables

Use descriptive names for variables
It may mean more typing in the short term but will save time in the long term when you have to update your code in the future. Descriptive names can often take the place of comments. Short names are ok for local variables within smallish function bodies. Use longer desciptive names for functions and variables used by other functions in the same file or in other files.
variable names are lower_snake_case (preferred)
double radians_per_second = kTWO_PI * 440;
Avoid magic numbers
Especially if they're used more than once.
const double kPIover4 = 0.78540;
const int kMAXLENGTH = 13;

// good
double x = std::cos(kPIover4);
int y = x * kMAXLENGTH;

// Bad
double x = std::cos(0.78540);
int y = x * 13;

One variable definition per line
// Good
int x;
int y;
int z;

// Bad
int x, y, z;

Declare variables near point of use
// some code above
bool done = false;
while (!done) {
  // some lenghty process
  done = true;
}
Initialize every variable when it comes into existence
 int x;
 //  lots of code follows
 // finally
 std::cout << x << std::endl; // prints garbage, x never defined

 // should have said
int x{9999}; // assign it to something, you can always change it later.
int x = 9999; // same thing

Constants

lowercase k followed by UPPER_SNAKE_CASE
kSPEED_OF_SOUND

Function names

Use descriptive lower_snake_case names for functions
void calc_duration_of_track_1();

Function parameters

Use const & paramaters as much as possible

When the parameter is not changed within the function it should be declared as a const reference.

int add2( const int& x, const int& y )
{
  int z = x + y;
  return z;
}

Precedence

  • Use parens ( ) to make things clear, even if you know the C++ precedence rules
x = 12 * 3 + 5;   // precedence is * comes before +
x = (12 * 3) + 5; // makes it clear
x = 12 * (3 + 5); // this is really what I wanted

Prefer ++x over x++

++x avoids creating a temporary variable and it's faster than post increment
for ( int n = 0; n < 10; ++n)
    std::cout << n << std::endl;
Place pre and post increment statements on their own line
// Good
mystring[i];
++i;

// Bad
mystring[i++];

File names

No spaces in any file file name. Your choice of naming convention

Good
a_really_long_filename.cpp
aReallyLongFilename.cpp

OK
areallylongfilename.cpp

Bad
AREALLYLONGFILENAME.CPP

Use fully qualified namespaces

You may read about the using namespace std directive. It may make things easier to type for quick one off tests but not for production code. CS 312 always writes production quality code and always uses the fully qualified std:: namespace scope operator.

Do this

#include <iostream>

  int main() {
      using namespace std;
      int x = (3 + 5) * 2;
      int y = 3 + (5 * 2);
      int z = 3 + 5 * 2;
      std::cout << "x = " << x << std::endl;
      std::cout << "y = " << y << std::endl;
      std::cout << "z = " << z << std::endl;
  }

Not this

#include <iostream>

int main() {
    using namespace std;
    int x = (3 + 5) * 2;
    int y = 3 + (5 * 2);
    int z = 3 + 5 * 2;
    cout << "x = " << x << endl;
    cout << "y = " << y << endl;
    cout << "z = " << z << endl;
}

Output

x = 16
y = 13
z = 13

Homework

  • CMC Labs 304 and 306 are both setup for CS312 homework.
  • All homework is to be done with a pair partner.
  • This homework is to be done in the CMC labs.
  • I would recommend doing all your homework in CMC although Weitz 138 is an alternive

Before starting the homework:

Complete the CMC Lab Setup
above
Do the reading
About CS312
This web page
TCPP2 (A Tour of C++ 2nd Edition)
  • Chapter 1 all
  • Chapter 2 through §2.3
  • Chapter 9 through §9.2.1
  • Chapter 10 §10.1-10.3
Watch this video
Learn C++ in one hour
Watch it more than once throughout the term.
Review
Homework Naming Conventions in About CS312

CMC Lab Setup

You have your own account and home folder in the CMC labs. We'll need to create/modify a few login scripts before you can follow the same steps we did in the WCC lab. In WCC the scripts were already there. I'd recommend you do your homework in the CMC because that resembles what you'd find in the workplace.

Create bash startup scripts for Terminal

Terminal runs a program called a shell. On the Mac the default shell is bash. All CS 312 assignments and examples assume you're using the bash shell. When Terminal starts up it executes commands found in the .bash_profile file in your home directory. You've may never have seen it because its filename begins with a dot. Dot files on the Mac are hidden. You can make them visible in a Finder window by typing Command-Shift-Period. You can see dot files in the Terminal using the ls -a command.

We'll use these two files to customize the bash Terminal for CS312:

.bash_profile
executed once at login and executes .bashrc
.bashrc
executed every time a new Terminal window or tab is opened

.bash_profile

In the CMC labs .bash_profile must be present in order to login. You'll need to append some specific CS312 commands to the end of ./bash_profile/.

Execute these terminal commands.
The # symbol is a bash comment you don't have to type.
Open .bash_profile.

# change directory to your home directory
cd
# open BBEdit to edit the file
bbedit .bash_profile

IMPORTANT: Do not delete or modify any text that is already present.
Move the text cursor to a blank line at the end of ./bash_profile/.
APPEND this text to the end of .bash_profile. Copy/paste

if [ -f ~/.bashrc ]; then
   source ~/.bashrc # execute commands in .bashrc
fi

Save and close file.

.bashrc

This file contains shortcuts for Termainal commands, PATH settings, and a variable, $HOME312, that refers to your cs312 courses folder.

Open .bashrc

# Change Directory to home
cd
# open/edit the file in BBEdit
bbedit .bashrc

IMPORTANT: Do not delete or modify any text that is already present.

  1. If .bashrc does not exist BBEdit will open to a blank window.
    Copy/paste the following script.
  2. If .bashrc exists there will be text in the window. Do not delete the text.
    APPEND the following script after the existing text.
export TERM=xterm-256color
export HISTCONTROL=ignoredups

# needed by VS Code to override an error message
# see last comment on https://github.com/Microsoft/vscode-cpptools/issues/1445
export CPPTOOLS_DEV=1

# useful commands
## from http://linuxcommando.blogspot.com/2008/04/quick-hex-decimal-conversion-using-cli.html
htod () { printf '%d\n' $1; }
dtoh () { printf '0x%x\n' $1; }

# interactive remove, asks yes/no
alias rm="rm -i"

# for ls
# G:colorize
# F:add slash suffix to directories
# h:use unit suffixes for size
alias ls="ls -GFh"

# C++ compiler no debug info
alias clang++="clang++ -std=c++17 -Wall "

# use cl for cs312 compiles -g flag adds debug information
alias cl="clang++ -g -std=c++17 -Wall "

# export PATH=~/bin:$PATH

# thanks to Danny Maya and Justin Washington
# for collaborating on setup312()
# and helping test between CMC and WCC labs
setup312() {
if [ 1 -ne $# ]; then
 echo "Usage:\tsetup312 <your_carleton_email_name>"
 exit 1
fi

student=$1

coursefolder=/Volumes/COURSES/cs312-00-w20/StuWork
export HOME312=$coursefolder/$student

echo "export PATH=$HOME312/bin:$PATH" >> "/Accounts/$student/.bashrc"
cd $HOME312
source ~/.bashrc
}

# shortcuts
alias cd312='cd $HOME312/cs312/'

Save and close .bashrc

Testing 1 2 3

1. Mount your courses folder for CS312

Choose Go to Server from the Go menu in Finder.

hw1110.png

Login with your Carleton email name and password.

Mount your cs312 courses folder.

smb://courses.ads.carleton.edu/COURSES/cs312-00-w20

hw1111.png

2. Execute this command in Terminal and press Return.

source .bashrc

3. Execute this command in Terminal and press Return.

setup312 <your_email_name>

4. Execute this command in Terminal and press Return.

# Print Working Directory
pwd
# should display
# /Volumes/COURSES/cs312-00-w20/StuWork/<your_email_name>

5. Execute this command.

echo $HOME312
# should display same thing
# /Volumes/COURSES/cs312-00-w20/StuWork/<your_email_name>

6. Execute these commands.

 # cd by itself should take you to your /Accounts home directory
cd
pwd
# cd312 should take you back to /Volumes/COURSES/cs312-00-w20/StuWork/<your_email_name>
# provided your courses folder is mounted
cd312
pwd

If you finished Ex1 Hellow World in C++ these folders will already be present in your courses folder.

cd $HOME312
ls

/Volumes/cs312-00-w20/StuWork/<your_email_name>
├── cs312
  ├── bin
  ├── hw11
  │   ├── class11
  │   │   └── c111_hello.cpp

If not you'll need to create that directory structure by hand.

If everything worked continue.
If not email jellinge@carleton.edu and explain the problem.

CMC homework commands

You should only have to do the above setup commands once. Each time you login after that you'll still need to start your homework with these two steps:

  1. Mount your courses folder for cs312
  2. Run this command in Terminal
setup312 <your_email_name>

hw111_boilerplate.cpp

Open Terminal in /Applications/Utilities and execute these commands. Execute means typing Enter after you've typed the command.

cd $HOME312
 # IMPORTANT: make certain you are in your cs312 courses folder
pwd

If pwd returned YOUR_COURSES_FOLDER/cs312 continue with these commands. If not, figure out why not. Repeat the CMC Lab Setup instructions.

touch hw111_boilerplate.cpp
touch hw112_helloMidi.cpp
code .
# the . at the end of the last command refers to the current directory

This should open the vsCode text editor that you will use for the first 2/3 of the course. You'll learn more about vsCode in class 1.2.

When vsCode opens, click the boilerplate.cpp code in the left side tree view.
Copy this code into the main editor section. Then save the file.

#include <iostream>
#include <string>

const std::string str_header{"/***************************************************************"};
const std::string str_footer{"***************************************************************/"};

void write_header() {
  std::cout << str_header << std::endl;
}

void write_body() {
  std::cout << "body" << std::endl;
}

void write_footer() {
  std::cout << str_footer << std::endl;
}

int main() {
  write_header();
  write_body();
  write_footer();
}

Open Terminal and execute this command.

cl hw111_boilerplate.cpp && ./a.out

You should see this output.

/***************************************************************
body
***************************************************************/

Assignment hw111_boilerplate

Implement write_body() to produce the following output.

Important : Use you and your partners names: Last First email.

/***************************************************************
hw111_boilerplate.cpp
Copyright (c) Carleton College CS312 free open source
Assignment: hw111
Duck Donald dduck@carleton.edu
Mouse Minny mmouse@carleton.edu
DATE: 2019-12-15
TIME: 14:46:25
****************************************************************/

Hint: Date and Time

Run this command in Terminal

date '+DATE: %Y-%m-%d' && date '+TIME: %H:%M:%S'

Google std::system for one way of capturing shell commands in C++.

Here's code I modified from one of the sites google returned: https://en.cppreference.com/w/cpp/utility/program/system

Copy/paste this code into a new file named /date.cpp.

#include <iostream>
#include <cstdlib>

int main()
{
}
    std::system("date"); // execute the UNIX command date

Compile and run

cl date && ./a.out

Output

Sun Dec 15 22:16:01 CST 2019

Modify it for use in boilerplate.cpp.

hw112_helloMidi.cpp

Open hw112_helloMidi.cpp in vsCode.

Copy/paste this code and Save.

// helloMidi.cpp
#include <iostream>
#include <string>

// write_comment()
// prints lines that start with # followed by string s
// string s does not contain the "# " (pound space) to start the line
void write_comment(const std::string &s) {
  std::cout << "  write_comment()\t\t// you write" << std::endl;
}

// write_midi_message_nodata2(...)
// 0xC0 status bytes are followed by one data byte
// prints lines that begin with numbers
void write_midi_message_nodata2(int32_t time_stamp, int16_t status,
                                int16_t data1) 
{
  std::cout << "  write_midi_message_nodata2()\t// you write" << std::endl;
}

// write_midi_message_hasdata2(...)
// 0x80 and 0x90 status bytes are followed by two data bytes
// use  hasData2() to insure that the 0xC0 does not output data2
void write_midi_message_hasdata2(unsigned int timeStamp, unsigned char status,
                                 unsigned char data1, unsigned char data2) 
{
  std::cout << "  write_midi_message_hasdata2()\t// you write" << std::endl;
}

// write formatted output exactly as shown below
// use the three functions you implemented above
int main() {
  std::cout << "If line begins with # use" << std::endl;
  write_comment(" ");

  std::cout << "\nIf midi message status is 0xC0 use" << std::endl;
  write_midi_message_nodata2(0, 0, 0);

  std::cout << "\nElse if midi message status is 0x80 or 0x90 use" << std::endl;
  write_midi_message_hasdata2(0, 0, 0, 0);
}

Execute this code in Terminal.

cl hw112_helloMidi.cpp -o helloMidi && ./helloMidi

You should see this.

If line begins with
  write_comment()   // you write

If midi message status is 0xC0 use
  write_midi_message_nodata2()  // you write

Else if midi message status is 0x80 or 0x90 use
  write_midi_message_hasdata2() // you write

We'll be using MIDI messages for the next several weeks. You'll need to implement these three functions to produce the output shown below. Study the comments in the output of this assignment.

Assignment hw112_helloMidi

Implement these three functions to produce the output shown below.

// write lines beginning with #
void write_comment(const std::string& s);

// write lines where the status byte does not use a data2 byte
void write_midi_message_nodata2(int32_t timeStamp,
                                int16_t status,
                                int16_t data1);

 void write_midi_message_hasdata2(unsigned int timeStamp,
                                  unsigned char status,
                                  unsigned char data1,
                                  unsigned char data2);

Output

Your final output must match this exactly. Study the comments (lines beginning with #)

# A MIDI message contains three or four numbers separated by a single tab character
# number 1 is a time stamp in milliseconds in decimal format
# number 2 is a MIDI status message in hexadecimal format without the 0x prefix (range 0x80 - 0xFF)
# number 3 is a MIDI data1 message in decimal format (range 0 - 127)
# number 4 is a MIDI data2 message in decimal format (range 0 - 127)

# status 0xC0 begins a a patch change message
# indicating which instrument sound to use
# patch change messages do not use data2
# data1 is the instrument number.
0	c0	0

# status 0x90 begins a Note On (NON) message
# NON messages use both data1 and data2
# data1 is the MIDI note number that corresponds to
# keys on a piano where Middle C is note number 60
# data2 is the velocity or how loud or soft the note sounds
0	90	60	110

# status code 0x80 begins a Note Off (NOF) message
# NOF messages use both data1 and data2
# data1 is the MIDI note number that corresponds to
# keys on a piano where Middle C is note number 60
# data2 should be set to zero
900	80	60	0

# Every NON must be followed by a NOF with a later time stamp
1000	90	55	80
1400	80	55	0

# You can also send a NOF using a NON with a velocity of 0
1500	90	55	60
1900	90	55	0

# More NON-NOF pairs
2000	90	56	100
2900	80	56	0
3000	90	55	80
4200	80	55	0

# Another patch change
4999	c0	56

# More NON-NOF pairs
5000	90	59	110
5900	80	59	0
6000	90	60	127
8000	80	60	0

Notes

  • The # symbol is a comment. Include it as the first character of the line followed by a space.
  • Non comment lines are MIDI messages that contain 3 or 4 numbers.
  • All numbers are separated by a single tab character.
  • A tab character can be coded like this.
const char kTAB = '\t';
std::cout << 0 << kTAB << 90 << kTAB << 60 << kTAB << 100 << std::endl

We'll play it in the next class and you can hear what it sounds like.

Submission Format

Feel free to email jellinge@carleton.edu on any part of the homework that is unclear to you. Chances are if you have questions other students do too. I will answer those questions by email to everyone in the class. The original sender will remain anonymous. I have tried to provide clues to the homework in the web pages, reading assignments, and labs. Sometimes what seems obvious to me is not obvious to students just learning C++.

Create a folder named hwNN_LastnameFirstname1_LastnameFirstname2.
Substitute your name and your partner's name for LastnameFirstname1_LastnameFirstname2.

Remember

  • Boilerplate header at top of every file.
  • Make sure your program compiles before submitting.
  • Programs that compile and produce partially correct output will be graded.
  • You can send notes to me in your homework files by enclosing them in block comments.
  • Programs that do not compile get an automatic F (59%).
  • Each partner must submit identical homework folders to the course Hand-in folder.
  • If only one partner submits the homework send me an email explaining why.
  • Empty your build or build-debug folders using the command emptyBuildFolder.sh
  • Only include .h, .cpp, Makefiles, CMakeLists.txt
  • Do not include these folders/files
    .git
    .vscode
  • Double check for the above two folders using this command

    ls -a hwNN_LastnameFirstname1_LastnameFirstname2
    # if either .git or .vscode exist in the folder you're submitting remove them with
    # rm -fR .git
    # rm -fR .vscode
    

Create a folder named hw11_LastnameFirstname_LastnameFirstname.
Substitute your name and your partner's name for LastnameFirstname_LastnameFirstname.
My folder would be called hw11_EllingerJohn_StroustrupBjarne. Yours will be named in a similar format.

Code to turn in

hw11_LastnameFirstname1_LastnameFirstname2
├── hw111_boilerplate.cpp
├── hw112_helloMidi.cpp

Example boilerplate header. Use yours not my example.

/***************************************************************
hw111_boilerplate.cpp
Copyright (c) Carleton College CS312 free open source
Assignment: hw111_boilerplate
Man Super sman@carleton.edu
Woman Wonder wwoman@carleton.edu
DATE: 2019-12-15
TIME: 14:46:25
****************************************************************/

Author: John Ellinger

Created: 2020-01-07 Tue 19:49

Validate