0% found this document useful (0 votes)
7 views

CS-210 Sample Codes Practice

how to code in C++
Copyright
© © All Rights Reserved
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
7 views

CS-210 Sample Codes Practice

how to code in C++
Copyright
© © All Rights Reserved
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 72

###################################################################################

##########################################################
1)

# includ <iostream>
using namespace std;

int main() {
int wage;

cin >> wage;

cout << "Salary is";


cout << wage * 40 * 52;
cout << endl;

return 0;

###################################################################################
##########################################################
2)

/* The following code (explained later) at the top of a file enables the program to
get input and put output: (# include <iostream> etc) */

#include <iostream>
using namespace std;

int main() {
int wage;

wage = 20;

cout << "Wage is: " << wage << endl;


cout << "Goodbye." << endl;

return 0;
}

###################################################################################
##########################################################
3)

In C++ There are two types of commenting, single line and multi line:

// This is a single line comment

/* This is
a double line
comment, examples
below */
#include <iostream>
using namespace std;

/*
This program calculates the amount of pasta to cook, given the
number of people eating.

Author: Andrea Giada


Date: May 30, 2017
*/

int main() {
int numPeople; // Number of people that will be eating
int totalOuncesPasta; // Total ounces of pasta to serve numPeople

// Get number of people


cout << "Enter number of people: " << endl;
cin >> numPeople;

// Calculate and print total ounces of pasta


totalOuncesPasta = numPeople * 3; // Typical ounces per person
cout << "Cook " << totalOuncesPasta << " ounces of pasta." << endl;

return 0;
}

###################################################################################
##########################################################
4)

# include <iostream>
using namespace std;

int main() {
int myFirstVar; // Aligned comments yield less
int yetAnotherVar; // visual clutter
int thirdVar;

// Above blank line seperates variable delcarations from the rest


cout << "Enter a number: ";
cin >> myFirstVar;

// Above blank line seperates user input statements from the rest
yetAnotherVar = myFirstVar; // Aligned = operators
thirdVar = yetAnotherVar + 1;
// Also notice the single-space on the left and right of + and =
// (except when aligning the second = with the first =)

cout << "Final value is " << thirdVar << endl; // Single-space on each side
of <<

return 0; // The above blank line seperates the return line from the rest
}
###################################################################################
##########################################################
5)

Below are some sample types of instructions that a processor might be able to
execute, where X, Y, Z, and num are each an integer.

Add X, #num, Y Adds data in memory location X to the number num, storing result
in location Y.
Sub X, #num, Y Subtracts num from data in location X, storing result in location
Y.
Mul X, #num, Y Multiplies data in location X by num, storing result in location
Y.
Div X, #num, Y Divides data in location X by num, storing result in location Y.
Jmp Z Tells the processor that the next instruction to execute is in memory
location Z.

###################################################################################
##########################################################
6) The following example is of a 'manipulator' which is a function that
overloads the insertion operator << or the extraction operator >> to adjust the
way output appears. Manipulators are defined in the iomanip and ios libraries in
namespace std.

#include <iostream>
#include <iomanip>
using namespace std;

int main() {
double miles = 765.4261;

cout << "setprecision(p) sets # digits" << endl;


cout << miles << " (default p is 6)" << endl;
cout << setprecision(8) << miles << " (p = 8)" << endl;
cout << setprecision(5) << miles << " (p = 5)" << endl;
cout << setprecision(2) << miles << " (p = 2)" << endl; //
scientific notation may result for smaller precision values
cout << miles << endl << endl; // this
demonstrates that last set precision works for next lines too

// fixed uses fixed point notation // uses fixed point


notation, now applies to number of decimal places
cout << fixed;
cout << "fixed: " << miles << endl;

// scientific uses scientific notation // uses scientific


notation but also has two decimals before the e
cout << scientific;
cout << "scientific: " << miles << endl;

return 0;
}

###################################################################################
##########################################################
7) Table of manipulators, descriptions, and examples.

Manipulator Description
Example

fixed Use fixed-point notation.


// 12.340000
From <iostream> cout <<
fixed << 12.34;

scientific Use scientific notation. //


1.234000e+01
From <iostream> cout <<
scientific << 12.34;

setprecision(p) If stream has not been manipulated to fixed or scientific:


// 12.3
Sets max number of digits in number
cout << setprecision(3) << 12.34;
// 12.34
cout <<
setprecision(5) << 12.34;

If stream has been manipulated to fixed or scientific:


// 12.3
Sets max number of digits in fraction only
cout << fixed << setprecision(1) << 12.34;
(after the decimal point). //
1.2e+01
From <iomanip> cout
<< scientific << setprecision(1) <<
12.34;

showpoint Even if fraction is 0, show decimal point and trailing 0s.


// 99
Opposite is noshowpoint. cout
<< setprecision(3) << 99.0;
From <iostream> // 99.0

cout <<
setprecision(3) << showpoint << 99.0;

###################################################################################
##########################################################
8) Example of text alignment manipulators.

#include <iostream>
#include <iomanip>
using namespace std;
int main() {
// Dog age in human years (dogyears.com)
cout << setw(10) << left << "Dog age" << "|";
cout << setw(12) << right << "Human age" << endl;

// Produce long line


cout << setfill('-') << setw(23) << "" << endl;

// Reset fill character back to space


cout << setfill(' ');

cout << setw(10) << left << "2 months" << "|"
cout << setw(12) << right << "14 months" << endl;
cout << setw(10) << left << "6 months" << "|";
cout << setw(12) << right << "5 years" << endl;
cout << setw(12) << left << "8 months" << "|";
cout << setw(10) << right << "9 years" << endl;
cout << setw(12) << left << "1 year" << "|";
cout << setw(12) << right << "15 years" << endl;

// Produce long line


cout << setfill('-') << setw(23) << "" << endl;

return 0;
}

###################################################################################
##########################################################
9) Table of Text-Alignment Manipulators

Manipulator Description
Example

setw(n) Sets the number of characters for the next output item only
// " Amy"
(does not persist, in contrast to other manipulators).
// " George"
By default, the item will be right-aligned, and filled with
spaces. cout << setw(7) << "Amy" << endl;
From <iomanip> cout
<< setw(7) << "George" << endl;

setfill(c) Sets the fill to character c. //


"****Amy"
From <iomanip> cout
<< setfill('*') << setw(7) << "Amy";

left Changes to left alignment. //


"Amy "
From <iostream> cout << left
<< setw(7) << "Amy";

right Changes back to right alignment.


// " Amy"
From <iostream> cout <<
right << setw(7) << "Amy";

###################################################################################
##########################################################
10) Table with descriptions and example of buffer manipulators.

Manipulator Description
Example

endl Inserts a newline character '\n' into the output buffer


// Insert newline and flush
and informs the system to flush the buffer.
cout << endl;
From <iostream>

flush Informs the system to flush the buffer.


// Flush buffer
From <iostream> cout <<
flush;

###################################################################################
##########################################################

Table 2.3.1: C++ reserved words / keywords.

alignas (since C++11)


alignof (since C++11)
and
and_eq
asm
auto
bitand
bitor
bool
break
case
catch
char
char16_t (since C++11)
char32_t (since C++11)
class
compl
const
constexpr (since C++11)
const_cast
continue
decltype (since C++11)
default
delete
do
double
dynamic_cast
else
enum
explicit
export
extern
false
float
for
friend
goto
if
inline
int
long
mutable
namespace
new
noexcept (since C++11)
not
not_eq
nullptr (since C++11)
operator
or
or_eq
private
protected
public
register
reinterpret_cast
return
short
signed
sizeof
static
static_assert (since C++11)
static_cast
struct
switch
template
this
thread_local (since C++11)
throw
true
try
typedef
typeid
typename
union
unsigned
using
virtual
void
volatile
wchar_t
while
xor
xor_eq
###################################################################################
##########################################################

Compound operators

Special operators called compound operators provide a shorthand way to update a


variable, such as userAge += 1 being shorthand for userAge = userAge + 1. Other
compound operators include -=, *=, /=, and %=.

###################################################################################
##########################################################

Scientific notation is useful for representing floating-point numbers that are much
greater than or much less than 0, such as 6.02 x 1023. A floating-point literal
using scientific notation is written using an e preceding the power-of-10 exponent,
as in 6.02e23 to represent 6.02 x 1023. The e stands for exponent. Likewise, 0.001
is 1 x 10-3 and can be written as 1.0e-3. For a floating-point literal, good
practice is to make the leading digit non-zero.

###################################################################################
##########################################################

2.9 Constant variables

A good practice is to minimize the use of literal numbers in code. One reason is to
improve code readability. newPrice = origPrice - 5 is less clear than newPrice =
origPrice - priceDiscount. When a variable represents a literal, the variable's
value should not be changed in the code. If the programmer precedes the variable
declaration with the keyword const, then the compiler will report an error if a
later statement tries to change that variable's value. An initialized variable
whose value cannot change is called a constant variable. A common convention, or
good practice, is to name constant variables using upper case letters with words
separated by underscores, to make constant variables clearly visible in code.

###################################################################################
##########################################################

2.10 Using math functions

Basics

Some programs require math operations beyond +, -, *, /, like computing a square


root. A standard math library has about 20 math operations, known as functions. A
programmer can include the library and then use those math functions.

#include <iostream>
#include <cmath>
using namespace std;

int main() {
double sideSquare;
double areaSquare = 49.0;

sideSquare = sqrt(areaSquare);

cout << "Square root of " << areaSquare


<< " is " << sideSquare << endl;

return 0;
}

Table 2.10.1: A few common math functions from the math


library.

Function Behavior Example

sqrt(x) Square root of x sqrt(9.0) evaluates to


3.0.
pow(x, y) Power pow(6.0, 2.0) evaluates
to 36.0.
fabs(x) Absolute value of x fabs(-99.5)
evaluates to 99.5.

###################################################################################
##########################################################

2.11 Integer division and modulo

Division: Integer rounding

When the operands of / are integers, the operator performs integer division, which
does not generate any fraction. If at least one operand is floating-point, then
instead / does floating point division.

###################################################################################
##########################################################

Modulo (%)

The basic arithmetic operators include not just +, -, *, /, but also %. The modulo
operator (%) evaluates the remainder of the division of two integer operands. Ex:
23 % 10 is 3.

Examples:

24 % 10 is 4. Reason: 24 / 10 is 2 with remainder 4.


50 % 50 is 0. Reason: 50 / 50 is 1 with remainder 0.
1 % 2 is 1. Reason: 1 / 2 is 0 with remainder 1.
10 % 4.0 is not valid. "Remainder" only makes sense for integer operands.

Modulo examples

Modulo has several useful applications. Below are just a few.


Example 2.11.1: Random number in range.

Given a random number randNum, % can generate a random number within a range:

randNum % 10
Yields 0 - 9: Possible remainders are 0, 1, ..., 8, 9. Remainder 10 is not
possible: Ex: 19 % 10 is 9, but 20 % 10 is 0.

randNum % 51
Yields 0 - 50: Note that % 50 would yield 0 - 49.

(randNum % 9) + 1
Yields 1 - 9: The % 9 yields 9 possible values 0 - 8, so the + 1 yields 1 - 9.

(randNum % 11) + 20
Yields 20 - 30: The % 11 yields 11 possible values 0 - 10, so the + 20 yields
20 - 30.

GETTING DIGITS WITH MODULO

Example 2.11.2: Getting digits.

Given a number, % and / can be used to get each digit. For a 3-digit number userVal
like 927:

onesDigit = userVal % 10; // Ex: 927 % 10 is 7.


tmpVal = userVal / 10;

tensDigit = tmpVal % 10; // Ex: tmpVal = 927 / 10 is 92. Then 92 % 10 is 2.


tmpVal = tmpVal / 10;

hundredsDigit = tmpVal % 10; // Ex: tmpVal = 92 / 10 = 9. Then 9 % 10 is 9.

Example 2.11.3: Get prefix of a phone number.

Given a 10-digit phone number stored as an integer, % and / can be used to get any
part, such as the prefix. For phoneNum = 1365551212 (whose prefix is 555):

tmpVal = phoneNum / 10000; // / 10000 shifts right by 4, so 136555.


prefixNum = tmpVal % 1000; // % 1000 gets the right 3 digits, so 555.

Dividing by a power of 10 shifts a value right. 321 / 10 is 32. 321 / 100 is 3.

% by a power of 10 gets the rightmost digits. 321 % 10 is 1. 321 % 100 is 21.

###################################################################################
##########################################################

2.12 Type conversions

Type conversions
A type conversion is a conversion of one data type to another, such as an int to a
double. The compiler automatically performs several common conversions between int
and double types, such automatic conversions are known as implicit conversion.

* For an arithmetic operator like + or *, if either operand is a double, the other


is automatically converted to double, and then a floating-point operation is
performed.

* For assignments, the right side type is converted to the left side type.

int-to-double conversion is straightforward: 25 becomes 25.0.

double-to-int conversion just drops the fraction: 4.9 becomes 4.

Assigning doubles with integer literals

Because of implicit conversion, statements like double someDoubleVar = 0; or


someDoubleVar = 5; are allowed, but discouraged. Using 0.0 or 5.0 is preferable.

Type casting

A programmer sometimes needs to explicitly convert an item's type. Ex: If a program


needs a floating-point result from dividing two integers, then at least one of the
integers needs to be converted to double so floating-point division is performed.
Otherwise, integer division is performed, evaluating to only the quotient and
ignoring the remainder. A type cast explicitly converts a value of one type to
another type.

The static_cast operator (static_cast<type>(expression)) converts the expression's


value to the indicated type. Ex: If myIntVar is 7, then
static_cast<double>(myIntVar) converts int 7 to double 7.0.

###################################################################################
##########################################################

Binary : Use a binary calculator if this ever comes up, which I doubt that it
really will...

###################################################################################
##########################################################

2.14 Characters
Basics

A variable of char type, as in char myChar;, can store a single character like the
letter m. A character literal is surrounded with single quotes, as in myChar =
'm';.

Table 2.14.2: Common escape sequences.

Escape sequence Char


\n newline
\t tab
\' single quote
\" double quote
\\ backslash

###################################################################################
##########################################################

2.15 Strings

Strings and string literals

A string is a sequence of characters. A string literal surrounds a character


sequence with double quotes, as in "Hello", "52 Main St.", or "42", vs. an integer
literal like 42 or character literal like 'a'. Various characters may be in a
string, such as letters, numbers, spaces, or symbols like $ or %, as in "$100 for
Julia!!". Earlier sections showed string literals being output, as in: cout <<
"Hello";.

String variables and assignments

Some variables should hold a string. A string data type isn't built into C++ like
char, int, or double, but is available in the standard library and can be used
after adding: #include <string>. A programmer can then declare a string variable
as: string firstName;.

^ I missed this the first go through, don't forget this! Would have been
frustrating to run into later.

A programmer can assign a string just as for other types. Ex: str1 = "Hello", or
str1 = str2. The string type automatically reallocates memory for str1 if the
right-side string is larger or smaller, and then copies the characters into str1.

A programmer can initialize a string variable during declaration: string firstMonth


= "January";. Otherwise, a string variable is automatically initialized to an empty
string "".

#include <iostream>
#include <string>
using namespace std;

int main() {
string sentenceSubject;
string sentenceVerb;
string sentenceObject = "an apple";

sentenceSubject = "boy";
sentenceVerb = "ate";

cout << "A ";


cout << sentenceSubject << " ";
cout << sentenceVerb << " ";
cout << sentenceObject << "." << endl;

return 0;
}

Getting a string without whitespaces from input

A whitespace character is a character used to represent horizontal and vertical


spaces in text, and includes spaces, tabs, and newline characters. Ex: "Oh my
goodness!" has two whitespace characters, one between h and m, the other between y
and g.

Below shows the basic approach to get a string from input into variable userString.
The approach automatically skips initial whitespace, then gets characters until the
next whitespace is seen.

cin >> userString;

Getting a string with whitespace from input

Sometimes a programmer wishes to get whitespace characters into a string, such as


getting a user's input of the name "Franklin D. Roosevelt" into a string variable
presidentName.

For such cases, the language supports getting an entire line into a string. The
function getline(cin, stringVar) gets all remaining text on the current input line,
up to the next newline character (which is removed from input but not put in
stringVar).

#include <iostream>
#include <string>
using namespace std;

int main() {
string firstName;
string lastName;

cout << "Enter first name:" << endl;


getline(cin, firstName); // Gets entire line up to ENTER

cout << "Enter last name:" << endl;


getline(cin, lastName); // Gets entire line up to ENTER

cout << endl;


cout << "Welcome " << firstName << " " << lastName << "!" << endl;
cout << "May I call you " << firstName << "?" << endl;

return 0;
}

Mixing cin and getline


Mixing cin >> and getline() can be tricky, because cin >> leaves the newline in the
input, while getline() does not skip leading whitespace.

###################################################################################
##########################################################

2.17 Numeric data types

int and double are the most common numeric data types. However, several other
numeric types exist. The following table summarizes available integer numeric data
types.

The size of integer numeric data types can vary between compilers, for reasons
beyond our scope. The following table lists the sizes for numeric integer data
types used in this material along with the minimum size for those data types
defined by the language standard.

Table 2.17.1: Integer numeric data types.

Declaration Size Supported number range


Standard-defined minimum size

char myVar; 8 bits -128 to 127


8 bits
short myVar; 16 bits -32,768 to 32,767
16 bits
long myVar; 32 bits -2,147,483,648 to 2,147,483,647
32 bits
long long myVar; 64 bits -9,223,372,036,854,775,808 to
9,223,372,036,854,775,807 64 bits
int myVar; 32 bits -2,147,483,648 to 2,147,483,647
16 bits

###################################################################################
##########################################################

2.18 Unsigned

Sometimes a programmer knows that a variable's numbers will always be positive (0


or greater), such as when the variable stores a person's age or weight. The
programmer can prepend the word "unsigned" to inform the compiler that the integers
will always be positive. Because the integer's sign need not be stored, the integer
range reaches slightly higher numbers, as follows:

Table 2.18.1: Unsigned integer data types.

Declaration Size Supported number range


Standard-defined minimum size

unsigned char myVar; 8 bits 0 to 255


8 bits
unsigned short myVar; 16 bits 0 to 65,535
16 bits
unsigned long myVar; 32 bits 0 to 4,294,967,295
32 bits
unsigned long long myVar; 64 bits 0 to
18,446,744,073,709,551,615 64 bits
unsigned int myVar; 32 bits 0 to 4,294,967,295
16 bits

Figure 2.18.1: Unsigned variables example: Memory size


converter.

#include <iostream>
using namespace std;

int main() {
unsigned long memSizeGiB;
unsigned long long memSizeBytes;
unsigned long long memSizeBits;

cout << "Enter memory size in GiBs: ";


cin >> memSizeGiB;

// 1 GiB = 1024 MiB, 1 MiB = 1024 KiB, 1 KiB = 1024 bytes


memSizeBytes = memSizeGiB * (1024 * 1024 * 1024);
// 1 byte = 8 bits
memSizeBits = memSizeBytes * 8;

cout << "Memory size in bytes: " << memSizeBytes << endl;
cout << "Memory size in bits: " << memSizeBits << endl;

return 0;
}

###################################################################################
##########################################################

2.19 Random numbers

Generating a random number

Some programs need to use a random number. Ex: A game program may need to roll
dice, or a website program may generate a random initial password.

The rand() function, in the C standard library, returns a random integer each time
the function is called, in the range 0 to RAND_MAX.

Figure 2.19.1: Outputting three random integers.

#include <iostream>
#include <cstdlib>
using namespace std;

int main() {
cout << rand() << endl;
cout << rand() << endl;
cout << rand() << endl;

cout << "(RAND_MAX: " << RAND_MAX << ")" << endl;

return 0;
}

OUTPUT:

16807
282475249
1622650073
(RAND_MAX: 2147483647)

Modulo to restrict range

Usually, a programmer wants a random integer restricted to a specific number of


possible values. The modulo operator % can be used. Ex: integer % 10 has 10
possible remainders: 0, 1, 2, ..., 8, 9.

Each call to rand() returns a random integer between 0 and a large number RAND_MAX.
A programmer usually wants a smaller number of possible values, for which % can be
used. % (modulo) means remainder. rand() % 3 has possible remainders of 0, 1, and
2.

Thus, rand() % 3 yields 3 possible values: 0, 1, and 2. Generally, rand() % N


yields N possible values, from 0 to N-1.

Specific ranges

The technique above generates random integers with N possible values ranging from 0
to N-1, like 6 values from 0 to 5. Commonly, a programmer wants a specific range
that starts with some value x that isn't 0, like 10 to 15, or -20 to 20. The
programmer should first determine the number of values in the range, generate a
random integer with that number of possible values, and then add x to adjust the
range to start with x.

Figure 2.19.2: Randomly moving a student from one seat to


another.

#include <iostream>
#include <cstdlib>
using namespace std;

// Switch a student
// from a random seat on the left (cols 1 to 15)
// to a random seat on the right (cols 16 to 30)
// Seat rows are 1 to 20

int main() {
int rowNumL;
int colNumL;
int rowNumR;
int colNumR;

rowNumL = (rand() % 20) + 1; // 1 to 20


colNumL = (rand() % 15) + 1; // 1 to 15

rowNumR = (rand() % 20) + 1; // 1 to 20


colNumR = (rand() % 15) + 16; // 16 to 30

cout << "Move from ";


cout << "row " << rowNumL << " col " << colNumL;
cout << " to " ;
cout << "row " << rowNumR << " col " << colNumR;
cout << endl;

return 0;
}

Pseudo-random (Seeds)

The integers generated by rand() are known as pseudo-random. "Pseudo" means "not
actually, but having the appearance of". The integers are pseudo-random because
each time a program runs, calls to rand() yield the same sequence of values.
Earlier in this section, a program called rand() three times and output 16807,
282475249, 1622650073. Every time the program is run, those same three integers
will be printed. Such reproducibility is important for testing some programs.
(Players of classic arcade games like Pac-man may notice that the seemingly-random
actions of objects actually follow the same pattern every time the game is played,
allowing players to master the game by repeating the same winning actions).

Internally, the rand() function has an equation to compute the next "random"
integer from the previous one, (invisibly) keeping track of the previous one. For
the first call to rand(), no previous random integer exists, so the function uses a
built-in integer known as the seed. By default, the seed is 1. A programmer can
change the seed using the function srand(), as in srand(2) or srand(99).

If the seed is different for each program run, the program will get a unique
sequence. One way to get a different seed for each program run is to use the
current time as the seed. The function time() returns the number of seconds since
Jan 1, 1970.

Note that the seeding should only be done once in a program, before the first call
to rand().

Which generates a random integer in the range 18 ...


30?

(rand() % (30 - 18 + 1)) + 18

^ yeah kind of weird syntax but basically using the


top # in range
- the bottom number + 1 to generate the length of
nums for indexing
the +1 justifies it to be e.g. 1-10, not 0-9, the +
sets the bottom
of the range...I swear there were more examples of
this but
apparently not....

###################################################################################
##########################################################

2.21 Auto (since C++11)

Versions of C++ since C++11 support auto specifiers. In a variable declaration,


using auto as the type specifier causes the compiler to automatically deduce the
type from the initializer. Ex: auto i = 5; causes i to be of type int, and auto j =
5.0; causes j to be of type double.

###################################################################################
##########################################################

3.2 Detecting equal values with branches

Detecting if two items are equal using an if


statement

A program commonly needs to determine if two items are equal. Ex: If a hotel gives
a discount for guests on their 50th wedding anniversary, a program to calculate the
discount can check if a variable numYears is equal to the value 50. A programmer
can use an if statement to check if two values are equal.

An if statement executes a group of statements if an expression is true. Braces


surround the if branch's statements. Braces { }, sometimes redundantly called curly
braces, represent a grouping, such as a grouping of statements. Note: { } are
braces, [ ] are brackets.

The example below uses ==. The equality operator (==) evaluates to true if the left
and right sides are equal. Ex: If numYears is 50, then numYears == 50 evaluates to
true. Note the equality operator is ==, not =.

Good practice is to indent a branch's statements, using a consistent number of


spaces. This material indents 3 spaces.

#include <iostream>
using namespace std;

int main() {
int hotelRate;
int numYears;

hotelRate = 150;

cout << "Enter number of years married: ";


cin >> numYears;

if (numYears == 50) {
cout << "Congratulations on 50 years "
<< "of marriage!" << endl;

hotelRate = hotelRate / 2;
}

cout << "Your hotel rate: ";


cout << hotelRate << endl;

return 0;
}

Equality and inequality operators

Whereas the equality operator checks whether two values are equal, the inequality
operator (!=) evaluates to true if the left and right sides are not equal, or
different.

An expression involving the equality or inequality operators evaluates to a Boolean


value. A Boolean is a type that has just two values: true or false.

###################################################################################
##########################################################

If-else statement

An if-else statement executes one group of statements when an expression is true,


and another group of statements when the expression is false. In the example below,
the if-else statement outputs if a number entered by the user is even or odd. The
if statement executes if divRemainder is equal to 0, and the else statement
executes if divRemainder is not equal to 0.

#include <iostream>
using namespace std;

int main() {
int userNum;
int divRemainder;

cout << "Enter a number: ";


cin >> userNum;

divRemainder = userNum % 2;

if (divRemainder == 0) {
cout << userNum << " is even." << endl;
}
else {
cout << userNum << " is odd." << endl;
}
return 0;
}

Multi-branch if-else statements

Commonly, a program may need to detect several specific values of a variable. An


If-else statement can be extended to have three (or more) branches. Each branch's
expression is checked in sequence. As soon as one branch's expression is found to
be true, that branch's statements execute (and no subsequent branch is considered).
If no expression is true, the else branch executes. The example below detects
values of 1, 10, 25, or 50 for variable numYears.

Figure 3.2.1: Multi-branch if-else statement. Only 1 branch


will execute.

if (expression1) {
// Statements that execute when expression1 is true
// (first branch)
}
else if (expression2) {
// Statements that execute when expression1 is false and expression2 is true
// (second branch)
}
else {
// Statements that execute when expression1 is false and expression2 is false
// (third branch)
}

###################################################################################
##########################################################

Table 3.5.1: Logical operators.

Logical operator Description

a AND b Logical AND: true when both of its


operands are true.
a OR b Logical OR: true when at least one
of its two operands are true.
NOT a Logical NOT: true when its one operand is
false, and vice-versa.

Logical operators

Special symbols are used to represent the AND, OR, and NOT logical operators.
Logical operators are commonly used in expressions of if-else statements.

Table 3.5.2: Logical operators.

Logical operator Description

a && b Logical AND (&&): true when both of


its operands are true
a || b Logical OR (||): true when at least
one of its two operands are true
!a Logical NOT (!): true when its one operand is false, and vice-
versa.

###################################################################################
##########################################################

3.10 Order of evaluation


Precedence rules

The order in which operators are evaluated in an expression are known as precedence
rules. Arithmetic, logical, and relational operators are evaluated in the order
shown below.

Table 3.10.1: Precedence rules for arithmetic, logical, and


relational operators.

Operator/Convention Description
Explanation

( ) Items within parentheses are evaluated first In (a * (b +


c)) - d, the + is evaluated first, then *,
then -.

! ! (logical NOT) is next ! x || y is


evaluated as (!x) || y

* / % + - Arithmetic operators (using their precedence z - 45 * y <


53 evaluates * first, then -, then <.
rules; see earlier section)

< <= > >= Relational operators x < 2 || x


>= 10 is evaluated as (x < 2) || (x >= 10) because
< and >= have precedence over ||.

== != Equality and inequality operators x == 0 && x


>= 10 is evaluated as (x == 0) && (x >= 10)
because < and >= have precedence over &&.
== and != have the same
precedence and are evaluated
left to right.

&& Logical AND x == 5 || y == 10 && z !


= 10 is evaluated as (x == 5) || ((y
== 10) && (z != 10)) because && has precedence over ||.

|| Logical OR || has the lowest


precedence of the listed arithmetic,
logical, and relational operators.

###################################################################################
##########################################################
3.11 Switch statements

Switch statement

A switch statement can more clearly represent multi-branch behavior involving a


variable being compared to constant values. The program executes the first case
whose constant expression matches the value of the switch expression, executes that
case's statements, and then jumps to the end. If no case matches, then the default
case statements are executed.

switch (userVal) {
case 1:
numItems = 5;
break;

case 3:
numItems = 12;
break;

case 4:
numItems = 99;
break;

default:
numItems = 55;
break;
}

Omitting the break statement

Omitting the break statement for a case will cause the statements within the next
case to be executed. Such "falling through" to the next case can be useful when
multiple cases, such as cases 0, 1, and 2, should execute the same statements.

The following extends the previous program for dog ages less than 1 year old. If
the dog's age is 0, the program asks for the dog's age in months. Within the
switch (dogAgeMonths) statement, "falling through" is used to execute the same
display statement for several values of dogAgeMonths. For example, if dogAgeMonths
is 0, 1 or 2, the same statement executes.

A common error occurs when the programmer forgets to include a break statement at
the end of a case's statements.

Construct 3.11.1: Switch statement general


form.

switch (expression) {
case constantExpr1:
// Statements
break;

case constantExpr2:
// Statements
break;
...

default: // If no other case matches


// Statements
break;
}

3.11.3 Another example of a switch statement


with fallthrough behavior

switch (userChar) {
case 'A':
encodedVal = 1;
break;

case 'B':
encodedVal = 2;
break;

case 'C':

case 'D':
encodedVal = 4;
break;

case 'E':
encodedVal = 5;

case 'F':
encodedVal = 6;
break;

default:
encodedVal = -1;
break;
}

###################################################################################
##########################################################
3.12 Boolean data type

Boolean data type

Boolean refers to a quantity that has only two possible values, true or false. C++
has the built-in data type bool for representing Boolean quantities.

A Boolean variable may be set using true or false keywords. Ex: isMale = true;
assigns isMale with the Boolean value true. A Boolean variable may also be set to
the result of a logical expression. Ex: isOverweight = (userBmi >= 25); assigns
isOverweight with the result of the expression userBmi >= 25.

Figure 3.12.1: Variables of bool data type: Restaurant wait


time calculator.
#include <iostream>
using namespace std;

int main() {
int waitTime;
int partySize;
char day;
bool isLargeParty;
bool isWeekend;

// Get day of reservation


cout << "Day of reservation (T/W/R/F/S/U): ";
cin >> day;
if (day == 'F' || day == 'S' || day == 'U') {
isWeekend = true;
}
else {
isWeekend = false;
}

// Get party size


cout << "Enter party size: ";
cin >> partySize;
isLargeParty = (partySize > 6);

// Determine wait time based on day of week and party size


if (isWeekend && !isLargeParty) {
waitTime = 30;
}
else if (!isWeekend && !isLargeParty) {
waitTime = 10;
}
else if (isWeekend && isLargeParty) {
waitTime = 45;
}
else {
waitTime = 15;
}

cout << "Restaurant wait time is " << waitTime


<< " minutes." << endl;

return 0;
}

Figure 3.12.2: Using Boolean variables to simplify


expressions.

isHot = (currentTemp > desiredTemp);


isReallyHot = (currentTemp > (desiredTemp + 5.0));
isHumid = (currentHumidity > 0.50);

if (isReallyHot) {
// Use A/C and evaporative cooler
acOn = true;
evapCoolerOn = true;
}
else if (isHot && isHumid) {
// Use A/C
acOn = true;
evapCoolerOn = false;
}
else if (isHot && !isHumid) {
// Use evaporative cooler
acOn = false;
evapCoolerOn = true;
}
else {
acOn = false;
evapCoolerOn = false;
}

###################################################################################
##########################################################

3.14 Indexing through Strings / String access operations

Accessing string characters

at(): The notation someString.at(x) accesses the character at index x of a string.

Figure 3.14.1: String character access: Word scramble.

#include <iostream>
#include <string>
using namespace std;

int main() {
string userWord;

cout << "Enter a 5-letter word: ";


cin >> userWord;

cout << "Scrambled: ";


cout << userWord.at(3);
cout << userWord.at(1);
cout << userWord.at(4);
cout << userWord.at(0);
cout << userWord.at(2);
cout << endl;

return 0;
}

Changing a character in a string

A character in a string can be assigned. If userString is "abcde", then


userString.at(3) = 'X' yields "abcXe".
Figure 3.14.2: Example: Changing a character.

#include <iostream>
#include <string>
using namespace std;

int main() {
string userWord ="Caterpillar";
int replaceIndex;

cout << "Enter an index (0-10): ";


cin >> replaceIndex;

userWord.at(replaceIndex) = '*';

cout << "Updated string: ";


cout << userWord << endl;

return 0;
}

sample in/out:
Enter an index (0-10): 0
Updated string: *aterpillar

...

Enter an index (0-10): 3


Updated string: Cat*rpillar

...

Enter an index (0-10): 10


Updated string: Caterpilla*

Working with the end of a string

Determining the last character in a string is often useful. If a string's length is


known, the last character is at index length - 1. Ex: "Hey" has length 3, with y at
index 2. The function s1.size() returns s1's length. Ex: If s1 is "Hey", s1.size()
returns 3.

A common task is to append (add to the end) a string to an existing string. The
function s1.append(s2) appends string s2 to string s1. Ex: If s1 is "Hey",
s1.append("!!!") makes s1 "Hey!!!".

The example program below might be part of a "caption contest" for a website where
a user enters a string below an image. The program automatically adds a period if
the user did not include any punctuation at the caption's end.

Figure 3.14.3: Example: Adding a period to a caption if no


punctuation.
#include <iostream>
#include <string>
using namespace std;

int main() {
string userCaption;
char lastChar;
int lastIndex;

cout << "Enter a caption: ";


getline(cin, userCaption);

lastIndex = userCaption.size() - 1;
lastChar = userCaption.at(lastIndex);

if ( (lastChar != '.') && (lastChar != '!') && (lastChar != '?') ) {


// User's caption lacked ending punctuation, so add a period
userCaption.append(".");
}

cout << "New: ";


cout << userCaption << endl;

return 0;
}

sample in/out:
Enter a caption: Hello world
New: Hello world.

...

Enter a caption: Anyone home?


New: Anyone home?

...

Enter a caption: TGIF!


New: TGIF!

...

Enter a caption: Another day.


New: Another day.

...

Enter a caption: Life is sweet


New: Life is sweet.

The .at(index) function generates an exception if the index is out of range for the
string's size. An exception is a detected runtime error that commonly prints an
error message and terminates the program.

C++ also supports C-style access of a string using brackets [] rather than .at(),
as in: someString[0]. However, such C-style access does not provide such error
checking. Good practice is to use .at() rather than brackets for accessing a
string's characters, due to .at()'s error checking.

###################################################################################
##########################################################

3.15 Character operations

Including the cctype library via #include <cctype> provides access to several
functions for working with characters. ctype stands for character type. The first c
indicates the library is originally from the C language.

Table 3.15.1: Character functions return values.

isalpha(c) true if alphabetic: isalpha('x') // true


a-z or A-Z isalpha('6') // false
isalpha('!') // false

toupper(c) Uppercase version letter = toupper('a') // A


letter = toupper('A') // A
letter = toupper('3') // 3

isdigit(c) true if digit: 0-9. isdigit('x') // false


isdigit('6') // true

tolower(c) Lowercase version letter = tolower('A') // a


letter = tolower('a') // a
letter = tolower('3') // 3

isspace(c) true if whitespace. isspace(' ') // true


isspace('\n') // true
isspace('x') // false

Figure 3.15.1: State abbreviation capitalization.


#include <iostream>
#include <cctype>
using namespace std;

int main() {
char let0;
char let1;

cout << "Enter a two-letter state abbreviation: ";


cin >> let0;
cin >> let1;

if ( ! (isalpha(let0) && isalpha(let1)) ) {


cout << "Error: Both are not letters." << endl;
}
else {
let0 = toupper(let0);
let1 = toupper(let1);
cout << "Capitalized: " << let0 << let1 << endl;
}
return 0;
}

sample in/out:

Enter a two-letter state abbreviation: az


Capitalized: AZ
...
Enter a two-letter state abbreviation: AZ
Capitalized: AZ
...
Enter a two-letter state abbreviation: Mn
Capitalized: MN
...
Enter a two-letter state abbreviation: 5x
Error: Both are not letters.
...
Enter a two-letter state abbreviation: A@
Error: Both are not letters.

#include <iostream>
#include <string>
#include <cctype>
using namespace std;

int main() {
string userPassword;

getline(cin, userPassword);

/* Your code goes here */


// Iterate through each character in the string
for (int i = 0; i < userPassword.length(); ++i) {
// Check if the character is alphabetic
if (isalpha(userPassword[i])) {
// Replace it with '*'
userPassword[i] = '*';
}
}
cout << userPassword << endl;

return 0;
}

#include <iostream>
#include <string>
#include <cctype>
using namespace std;

int main() {
string userPassword;

getline(cin, userPassword);

/* Your code goes here */


// Iterate through each character in the string
if (isalpha(userPassword[0])) {
userPassword[0] = '*';
}
if (isalpha(userPassword[1])) {
userPassword[1] = '*';
}
cout << userPassword << endl;

return 0;
}

###################################################################################
##########################################################

Read in a 3-character string from input into variable passCode. Declare a boolean
variable isValid and set isValid to true if passCode does not contain any
alphabetic characters. Otherwise, set isValid to false.

Ex: If the input is $%^, then the output is:

Passcode accepted

Note: Use getline(cin, passCode) to read the entire line from input into passCode.

#include <iostream>
#include <string>
#include <cctype>
using namespace std;

int main() {
string passCode;

/* Your code goes here */


getline(cin, passCode); // Read the entire line into passCode

bool isValid = true; // Assume passCode is valid unless proven otherwise

// Check each character in passCode


for (char c : passCode) {
if (!isalpha(c)) {
continue; // Continue if the character is not alphabetic
} else {
isValid = false; // Set isValid to false if any character is alphabetic
break; // Exit the loop as we found an alphabetic character
}
}
if (isValid) {
cout << "Passcode accepted" << endl;
}
else {
cout << "Passcode not accepted" << endl;
}

return 0;
}

Read in a 2-character string from input into variable userPassword. Declare a


boolean variable containsLowercase and set containsLowercase to true if
userPassword contains a lowercase letter. Otherwise, set containsLowercase to
false.

Ex: If the input is qD, then containsLowercase is assigned with true, so the output
is:

Password is valid

Ex: If the input is !2, then containsLowercase is assigned with false, so the
output is:

Password is not valid

Note: Use getline(cin, userPassword) to read the entire line from input into
userPassword.

#include <iostream>
#include <string>
#include <cctype>
using namespace std;

int main() {
string userPassword;

/* Your code goes here */


getline(cin, userPassword);

bool containsLowercase;

for (char i : userPassword) {


if (islower(i)) {
containsLowercase = true;
break;
}
}

if (containsLowercase) {
cout << "Password is valid" << endl;
}
else {
cout << "Password is not valid" << endl;
}
return 0;
}

THESE ARE TRICKY AF FOR SOME REASON I FIND THE SYNTAX MIND BOGGLING... DEFINATELY
PRACTICE THESE...

###################################################################################
##########################################################

Figure 3.16.1: Example: Get username from email


address.

#include <iostream>
#include <string>
using namespace std;

int main() {
string emailText;
int atSymbolIndex;
string emailUsername;

cout << "Enter email address: ";


cin >> emailText;

atSymbolIndex = emailText.find('@');
if (atSymbolIndex == string::npos) {
cout << "Address is missing @" << endl;
}
else {
emailUsername = emailText.substr(0, atSymbolIndex);
cout << "Username: " << emailUsername << endl;
}

return 0;
}

###################################################################################
##########################################################

Finding in a string / Getting a substring

The string library provides numerous useful functions, including functions for
finding a character or string within a string, or getting a substring of a string.

Table 3.16.1: find() and substr() functions, invoked as


myString.find().

find() find(item) returns index of first item occurrence, else


// userText is "Help me!"
returns string::npos (a constant defined in the string library).
userText.find('p') // Returns 3
Item may be char, string variable, string literal (or char array)
userText.find('e') // Returns 1 (first find(item, indx)
starts at index indx. occurrence of e only)

userText.find('z') // Returns string::npos

userText.find("me") // Returns 5

userText.find('e', 2) // Returns 6 (starts at


index 2)

substr() substr(index, length) returns substring starting at index


// userText is "http://google.com"
and having length characters.
userText.substr(0, 7)
// Returns "http://"

userText.substr(13, 4)
// Returns
".com"

userText.substr(userText.size() - 4, 4)
// Last 4:
".com"

Combining / Replacing

The string library has more functions for modifying strings.

Table 3.16.2: String modify functions, invoked as myString.push_back(c). Each


increases/decreases string's length appropriately.

push_back() push_back(c) appends character c to the end of a string.


// userText is "Hello"

userText.push_back('?'); // Now "Hello?"

userText.size(); // Returns 6

insert() insert(indx, subStr) Inserts string subStr starting at index


indx. // userText is "Goodbye"

userText.insert(0, "Well "); // Now


"Well
Goodbye"

// userText
is "Goodbye"

userText.insert(4, "---");
// Now
"Good---bye"

replace() replace(indx, num, subStr) replaces characters at indices


// userText is "You have many gifts"
indx to indx+num-1 with a copy of subStr.
userText.replace(9, 4, "a plethora of");
// Now "You
have a plethora of gifts"

str1 + str2 Returns a new string that is a copy of str1 with str2 appended.
// userText is "A B"
myString =
userText + " C D";
If one of str1, str2 is a string, the other may be a
// myString is "A B C D"
character (or character array).
myString = myString + '!';
// myString
now "A B C D!"
myString =
myString + userText;
// myString
now "A B C D!A B"

Figure 3.16.2: String modify example: Greeting.

#include <iostream>
#include <string>
using namespace std;

int main() {
string userName;
string greetingText;
int itemIndex;

itemIndex = 0;

cout << "Enter name: ";


getline(cin, userName);

// Combine strings using +


greetingText = "Hello " + userName;

// Append a period (could have used +)


greetingText.push_back('.'); // '' not ""
cout << greetingText << endl;

// Insert Mr/Ms before user's name


greetingText.insert(6, "Mr/Ms ");
cout << greetingText << endl;

// Replace occurrence of "Darn" by "@$#"


if (greetingText.find("Darn") != string::npos) { // Found
itemIndex = greetingText.find("Darn");
greetingText.replace(itemIndex, 4, "@#$");
}
cout << greetingText << endl;
return 0;
}

Enter name: Julia


Hello Julia.
Hello Mr/Ms Julia.
Hello Mr/Ms Julia.

...

Enter name: Darn Rabbit


Hello Darn Rabbit.
Hello Mr/Ms Darn Rabbit.
Hello Mr/Ms @#$ Rabbit.

str1 is "Main" and str2 is " Street" (note the leading space).

1) Use + to combine str1 and str2, so newStr should be "Main Street".

newStr = str1 + str2;

2) Use push_back to append period to str2, so str2 should be " Street."

str2.push_back('.');

3) Replace "ai" with "our" in str1, so str1 should be "Mourn". The


first two arguments are just numbers.

str1.replace(1, 2, "our");

###################################################################################
##########################################################

3.17 Conditional expressions

If-else statements with the form shown below are so common that the language
supports the shorthand notation shown.

Form 1: Shorthand:

if (condition) { myVar = (condition) ? expr1 : expr2;


myVar = expr1;
}
else {
myVar = expr2;
}

A conditional expression has the form condition ? exprWhenTrue : exprWhenFalse.

All three operands are expressions. If the condition evaluates to true, then
exprWhenTrue is evaluated. If the condition evaluates to false, then exprWhenFalse
is evaluated. The conditional expression evaluates to whichever of those two
expressions was evaluated. For example, if x is 2, then the conditional expression
(x == 2) ? 5 : 9 * x evaluates to 5.

A conditional expression has three operands and thus the "?" and ":" together are
sometimes referred to as a ternary operator.

Good practice is to restrict usage of conditional expressions to an assignment


statement, as in: y = (x == 2) ? 5 : 9 * x;. Common practice is to put parentheses
around the first expression of the conditional expression, to enhance readability.

###################################################################################
##########################################################

3.18 Floating-point comparison

Floating-point numbers should not be compared using ==. Ex: Avoid float1 == float2.
Reason: Some floating-point numbers cannot be exactly represented in the limited
available memory bits like 64 bits. Floating-point numbers expected to be equal may
be close but not exactly equal.

Floating-point numbers should be compared for "close enough" rather than exact
equality. Ex: If (x - y) < 0.0001, x and y are deemed equal. Because the difference
may be negative, the absolute value is used: fabs(x - y) < 0.0001. fabs() is a
function in the math library. The difference threshold indicating that floating-
point numbers are equal is often called the epsilon. Epsilon's value depends on the
program's expected values, but 0.0001 is common.

The std::abs() function is overloaded to support floating-point and integer types.


However, good practice is to use the fabs() function to make the operation clear.

numMeters = 0.7;
numMeters = numMeters - 0.4;
numMeters = numMeters - 0.3;

// numMeters expected to be 0,
// but is actually -0.0000000000000000555112
if (numMeters == 0.0) {
// Equals 0.
}
else {
// Does not equal 0.
}
Bug
if (fabs(numMeters - 0.0) < 0.001) {
// Equals 0.
}
else {
// Does not equal 0.
}

#include <iostream>
#include <cmath>
using namespace std;

int main() {
double bodyTemp;

cout << "Enter body temperature in Fahrenheit: ";


cin >> bodyTemp;

if (fabs(bodyTemp - 98.6) < 0.0001) {


cout << "Temperature is exactly normal." << endl;
}
else if (bodyTemp > 98.6) {
cout << "Temperature is above normal." << endl;
}
else {
cout << "Temperature is below normal." << endl;
}

return 0;
}

###################################################################################
##########################################################

3.19 Short circuit evaluation

A logical operator evaluates operands from left to right. Short circuit evaluation
skips evaluating later operands if the result of the logical operator can already
be determined. The logical AND operator short circuits to false if the first
operand evaluates to false, and skips evaluating the second operand. The logical OR
operator short circuits to true if the first operand is true, and skips evaluating
the second operand.

// Read minutes and seconds


if ((minutes < 1) && (seconds < 10)) {
// Print "Few seconds remaining!"
}
else {
// Print "Take your time."
}
...

Table 3.19.1: Short circuit evaluation.

Operator Example Short circuit


evaluation
operand1 && operand2 true && operand2 If the first operand
evaluates to true, operand2 is evaluated.
false && operand2 If the first operand evaluates to
false, the result of the AND operation is
always false, so operand2 is not evaluated.

operand1 || operand2 true || operand2 If the first operand


evaluates to true, the result of the OR operation is
always true, so operand2 is not evaluated.

false || operand2 If the first operand evaluates to


false, operand2 is evaluated.

###################################################################################
##########################################################
3.22 Loops (general)

While loop: Basics

A while loop is a program construct that repeatedly executes a list of sub-


statements (known as the loop body) while the loop's expression evaluates to true.
Each execution of the loop body is called an iteration. Once entering the loop
body, execution continues to the body's end, even if the expression would become
false midway through.

Construct 3.23.1: While loop.

while (expression) { // Loop expression


// Loop body: Executes if expression evaluated to true
// After body, execution jumps back to the "while"
}
// Statements that execute after the expression evaluates to false

9 - 7 = 2
2:7
7-2 = 5
2:5
5-2 = 3
2:3

3.25 For loops

Basics

A loop commonly must iterate a specific number of times, such as 10 times. Though
achievable with a while loop, that situation is so common that a special kind of
loop exists. A for loop is a loop with three parts at the top: a loop variable
initialization, a loop expression, and a loop variable update. A for loop describes
iterating a specific number of times more naturally than a while loop.

Construct 3.25.1: For loop.


for (initialExpression; conditionExpression; updateExpression) {
// Loop body
}
// Statements after the loop

The statement i = i + 1 is so common that the language supports the shorthand ++i,
with ++ known as the increment operator. (Likewise, -- is the decrement operator,
--i means i = i - 1). As such, a standard way to loop N times is shown below.

int i;
...
for (i = 0; i < N; ++i) {
...
}

Note: Actually two increment operators exist: ++i (pre-increment) and i++ (post-
increment). ++i increments before evaluating to a value, while i++ increments
after. Ex: If i is 5, outputting ++i outputs 6, while outputting i++ outputs 5 (and
then i becomes 6). This material primarily uses ++i for simplicity and safety,
although many programmers use i++, especially in for loops.

3.27 Loops and strings

Iterating through a string with a for loop


A programmer commonly iterates through a string, examining each character. The
following example counts the number of letters in a string, not counting digits,
symbols, etc.

Figure 3.27.1: Iterating through a string: Counting


letters.

#include <iostream>
#include <string>
#include <cctype>
using namespace std;

int main() {
string inputWord;
int numLetters;
unsigned int i;

cout << "Enter a word: ";


cin >> inputWord;

numLetters = 0;
for (i = 0; i < inputWord.size(); ++i) {
if (isalpha(inputWord.at(i))) {
numLetters += 1;
}
}

cout << "Number of letters: " << numLetters << endl;

return 0;
}

Figure 3.27.2: Iterating until done: Replacing all


occurrences of a word.
#include <iostream>
#include <string>
using namespace std;
int main() {
string userText;
int usaIndex;

cout << "Enter text: ";


getline(cin, userText);

// At least one occurrence exists


while (userText.find("U.S.A.") != string::npos) {
// Get index of first instance
usaIndex = userText.find("U.S.A.");

// U.S.A. is 6 long
userText.replace(usaIndex, 6, "USA");
}

cout << "New text: " << userText<< endl;

return 0;
}

###################################################################################
##########################################################
I AM STILL JANKY AT ITERATING THROUGH STRINGS FOR SOME REASON WITH
REPLACE...CHALLENGES....

#include <iostream>
#include <string>
using namespace std;

int main() {
string passPhrase;
unsigned int i;

getline(cin, passPhrase);

for (i = 0; i < passPhrase.length(); ++i) {


if (!isdigit(passPhrase[i])) {
passPhrase[i] = '1';
}
}

cout << "New password: " << passPhrase << endl;

return 0;
}

"qwerty" is a string commonly found in weak passwords. Use a while loop to count
the number of occurrences of "qwerty" in secretStr, and replace each occurrence of
"qwerty" in secretStr with an empty string("").
string.find(item) returns the index of the first occurrence of item in string. If
no occurrence is found, then the function returns string::npos.
str.replace(indx, n, "") replaces the n characters starting at index indx of str
with an empty string.

#include <iostream>
#include <string>
using namespace std;

int main() {
string secretStr;
int count;
int indx;

cin >> secretStr;

count = 0;
indx = 0;

while (secretStr.find("qwerty") != string::npos) {


indx = secretStr.find("qwerty");

if (secretStr.find("qwerty") != string::npos) {
count += 1;
}

// qwerty is 6 char long


secretStr.replace(indx, 6, "");
}

cout << "Number of violations: " << count << endl;


cout << "Remaining string: " << secretStr << endl;

return 0;
}

###################################################################################
##########################################################

3.28 Nested loops


A nested loop is a loop that appears in the body of another loop. The nested loops
are commonly referred to as the inner loop and outer loop.

Nested loops have various uses. One use is to generate all combinations of some
items. For example, the following program generates all two-letter .com Internet
domain names.

#include <iostream>
using namespace std;

/* Output all two-letter .com Internet domain names */


int main() {
char letter1;
char letter2;

cout << "Two-letter domain names:" << endl;

letter1 = 'a';
while (letter1 <= 'z') {
letter2 = 'a';
while (letter2 <= 'z') {
cout << letter1 << letter2 << ".com" << endl;
++letter2;
}
++letter1;
}

return 0;
}

#include <iostream>
using namespace std;

int main() {
int userNum;
int i;
int j;

cin >> userNum;

// Outer loop to iterate from 0 to userNum


for (int i = 0; i <= userNum; ++i) {
// Inner loop to print leading spaces
for (int j = 0; j < i; ++j) {
cout << " ";
}
// Print the number after leading spaces
cout << i << endl;
}

return 0;
}

Given numRows and numColumns, print a list of all seats in a theater. Rows are
numbered, columns lettered, as in 1A or 3E. Print a space after each seat,
including after the last. Ex: numRows = 2 and numColumns = 3 prints:
1A 1B 1C 2A 2B 2C
#include <iostream>
using namespace std;

int main() {
int numRows;
int numColumns;
int currentRow;
int currentColumn;
char currentColumnLetter;

cin >> numRows;


cin >> numColumns;

for (int i=1; i < numRows + 1; ++i) {


for (int j = 0; j < numColumns; ++j) {
cout << i << static_cast<char>('A' + j) << " ";
}
}

cout << endl;

return 0;
}

###################################################################################
##########################################################
3.32 Enumerations

This section has been set as optional by your instructor.


Some variables only need to store a small set of named values. For example, a
variable representing a traffic light need only store values named GREEN, YELLOW,
or RED. An enumeration type (enum) declares a name for a new type and possible
values for that type.

Construct 3.32.1: Enumeration type.


enum identifier {enumerator1, enumerator2, ...};

###################################################################################
##########################################################

4.2 Vectors

Vector declaration and accessing elements

A programmer commonly needs to maintain a list of items, just as people often


maintain lists of items like a grocery list or a course roster. A vector is an
ordered list of items of a given data type. Each item in a vector is called an
element. A programmer must include the statement #include <vector> at the top of
the file when planning to use vectors.

The statement above declares a vector with the specified number of elements, each
element of the specified data type. The type of each vector element is specified
within the angle brackets (<>). The number of vector elements is specified within
parentheses following the vector name. Ex: vector<int> gameScores(4); declares a
vector gameScores with 4 integer elements.

Terminology note: { } are braces. < > are angle brackets, or chevrons. In a vector
access, the number in .at() parentheses is called the index of the corresponding
element. The first vector element is at index 0.

If you have studied arrays, then know that a vector was added to C++ as a safer and
more powerful form of arrays, discussed elsewhere.

#include <iostream>
#include <vector>
using namespace std;

int main() {
vector<int> itemCounts(3);

itemCounts.at(0) = 122;
itemCounts.at(1) = 119;
itemCounts.at(2) = 117;

cout << itemCounts.at(1);

return 0;
}

Using an expression for a vector index

A powerful aspect of vectors is that the index is an expression. Ex: userNums.at(i)


uses the value held in the int variable i as the index. As such, a vector is useful
to easily lookup the Nth item in a list.

A vector's index must be an unsigned integer type. The vector index cannot be a
floating-point type, even if the value is 0.0, 1.0, etc.

The program below allows a user to print the age of the Nth oldest known person to
have ever lived. The program quickly accesses the Nth oldest person's age using
oldestPeople.at(nthPerson - 1). Note that the index is nthPerson - 1 rather than
just nthPerson because a vector's indices start at 0, so the 1st age is at index 0,
the 2nd at index 1, etc.

Figure 4.2.1: Vector's ith element can be directly accessed using .at(i
- 1): Oldest people program.

#include <iostream>
#include <vector>
using namespace std;

int main() {
vector<int> oldestPeople(5);
int nthPerson; // User input, Nth oldest person

oldestPeople.at(0) = 122; // Died 1997 in France


oldestPeople.at(1) = 119; // Died 1999 in U.S.
oldestPeople.at(2) = 117; // Died 1993 in U.S.
oldestPeople.at(3) = 117; // Died 1998 in Canada
oldestPeople.at(4) = 116; // Died 2006 in Ecuador

cout << "Enter N (1..5): ";


cin >> nthPerson;

if ((nthPerson >= 1) && (nthPerson <= 5)) {


cout << "The #" << nthPerson << " oldest person lived ";
cout << oldestPeople.at(nthPerson - 1) << " years." << endl;
}

return 0;
}

Enter N (1..5): 1
The #1 oldest person lived 122 years.

...

Enter N (1..5): 4
The #4 oldest person lived 117 years.

...

Enter N (1..5): 9

...

Enter N (1..5): 0

...

Enter N (1..5): 5
The #5 oldest person lived 116 years.

###################################################################################
##########################################################
4.2.4: Vector declaration and accesses.

1) Declare a vector named myVals that stores 10 items of type int.

A: vector<int> myVals(10);

2) Assign x with the value stored at index 8 of vector myVals.

A: x = myVals.at(8);

3) Given myVals has 10 elements, assign the last element in myVals with the value
555.

A: myVals.at(9) = 555;
4) Assign myVals element at the index held in currIndex with the value 777.

A: myVals.at(currIndex) = 777;

5) Assign tempVal with the myVals element at the index one after the value held in
variable i.

A: tempVal = myVals.at(i + 1);

Loops and vectors

A key advantage of vectors becomes evident when used in conjunction with loops. The
program below uses a loop to allow a user to enter 8 integer values, storing those
values in a vector, and then printing those 8 values.

A vector's size() function returns the number of vector elements. Ex: In the
program below, userVals.size() is 8 because the vector was declared with 8
elements.

Figure 4.2.2: Vectors combined with loops are powerful together:


User-entered numbers.

#include <iostream>
#include <vector>
using namespace std;

int main() {
const int NUM_VALS = 8; // Number of elements in vector
vector<int> userVals(NUM_VALS); // User values
unsigned int i; // Loop index

cout << "Enter " << NUM_VALS << " integer values..." << endl;
for (i = 0; i < userVals.size(); ++i) {
cout << "Value: ";
cin >> userVals.at(i);
}

cout << "You entered: ";


for (i = 0; i < userVals.size(); ++i) {
cout << userVals.at(i) << " ";
}
cout << endl;

return 0;
}

Vector initialization
A vector's elements are automatically initialized to 0s during the vector
declaration.

All of a vector's elements may be initialized to another single value. Ex:


vector<int> myVector(3, -1); creates a vector named myVector with three elements,
each with value -1.

A programmer may initialize each vector element with different values by specifying
the initial values in braces {} separated by commas. Ex: vector<int> carSales = {5,
7, 11}; creates a vector of three integer elements initialized with values 5, 7,
and 11. Such vector declaration and initialization does not require specifying the
vector size, because the vector's size is automatically set to the number of
elements within the braces. For a larger vector, initialization may be done by
first declaring the vector, and then using a loop to assign vector elements.

Iterating through vectors using loops

Iterating through vectors using loops is commonplace and is an important


programming skill to master. Because vector indices are numbered 0 to N - 1 rather
than 1 to N, programmers commonly use this for loop structure:

Figure 4.4.1: Common for loop structure for iterating


through a vector.

// Iterating through myVector


for (i = 0; i < myVector.size(); ++i) {
// Loop body accessing myVector.at(i)
}

Feedback?
Note that index variable i is initialized to 0, and the loop expression is i <
myVector.size() rather than i <= myVector.size(). If myVector.size() were 5, the
loop's iterations would set i to 0, 1, 2, 3, and 4, for a total of 5 iterations.
The benefit of the loop structure is that each vector element is accessed as
myVector.at(i) rather than the more complex myVector.at(i - 1).

Determining a quantity about a vector's items

Iterating through a vector for various purposes is an important programming skill


to master. Programs commonly iterate through vectors to determine some quantity
about the vector's items. The example below computes the sum of a vector's element
values.

Figure 4.4.2: Iterating through a vector example: Program that


finds the sum of a vector's elements.
#include <iostream>
#include <vector>
using namespace std;

int main() {
const int NUM_ELEMENTS = 8; // Number of elements in vector
vector<int> userVals(NUM_ELEMENTS); // User values
unsigned int i; // Loop index
int sumVal; // For computing sum

cout << "Enter " << NUM_ELEMENTS << " integer values..." << endl;
for (i = 0; i < userVals.size(); ++i) {
cout << "Value: ";
cin >> userVals.at(i);
cout << endl;
}

// Determine sum
sumVal = 0;
for (i = 0; i < userVals.size(); ++i) {
sumVal = sumVal + userVals.at(i);
}
cout << "Sum: " << sumVal << endl;

return 0;
}

Finding the maximum value in a vector

The program below determines the maximum value in a user-entered list. If the user
enters numbers 7, -9, 55, 44, 20, -400, 0, 2, then the program will output "max:
55". The program uses the variable maxVal to store the largest value seen thus far
as the program iterates through the vector. During each iteration, if the vector's
current element value is larger than the max seen thus far, the program assigns
maxVal with the current vector element.

Before entering the loop, maxVal must be initialized to some value because maxVal
will be compared with each vector element's value. A logical error would be to
initialize maxVal to 0, because 0 is not in fact the largest value seen so far, and
would result in incorrect output (of 0) if the user entered all negative numbers.
Instead, the program peeks at a vector element (in this case the first element,
though any element could be used) and initializes maxVal with that element's value.

###################################################################################
##########################################################

Figure 4.4.3: Iterating through a vector example: Program that


finds the max item.

#include <iostream>
#include <vector>
using namespace std;
int main() {
const int NUM_VALS = 8; // Number of elements in vector
vector<int> userVals(NUM_VALS); // User values
unsigned int i; // Loop index
int maxVal; // Computed max

cout << "Enter " << NUM_VALS << " integer values..." << endl;
for (i = 0; i < userVals.size(); ++i) {
cout << "Value: ";
cin >> userVals.at(i);
}

// Determine largest (max) number


maxVal = userVals.at(0); // Largest so far
for (i = 0; i < userVals.size(); ++i) {
if (userVals.at(i) > maxVal) {
maxVal = userVals.at(i);
}
}
cout << "Max: " << maxVal << endl;

return 0;
}

###################################################################################
##########################################################
4.5 Vector resize

Commonly, the size of a list of items is not known during a program's compile time.
Thus, a vector's size need not be specified in the vector's declaration. Instead, a
vector's size can be set or changed while a program executes using resize(N). Ex:
highScore.resize(10) resizes the highScores vector to have 10 elements.

resize() can be called multiple times. If the new size is larger, resize() adds
elements at the end. If smaller, resize() deletes elements from the end. If
userScores has size 3 (elements 0, 1, 2), userScores.resize(2); would delete
element 2, leaving elements 0 and 1. A subsequent access to userScores.at(2) would
result in an error.

###################################################################################
##########################################################

4.6 Swapping two variables (General)

Sometimes a program must swap values among two variables. Swapping two variables x
and y means to assign y's value to x, and x's value to y. If x is 33 and y is 55,
then after swapping x is 55 and y is 33.

A common method for swapping uses a temporary variable. A temporary variable is a


variable used briefly to store a value. To understand the intuition of such
temporary storage, consider a person holding a book in one hand and a phone in the
other, wishing to swap the items. The person can temporarily place the phone on a
table, move the book to the other hand, then pick up the phone.
4.7 Debugging example: Reversing a vector

A common vector modification is to reverse a vector's elements. One way to


accomplish this goal is to perform a series of swaps. For example, starting with a
vector of numbers 10 20 30 40 50 60 70 80, we could first swap the first item with
the last item, yielding 80 20 30 40 50 60 70 10. We could next swap the second item
with the second-to-last item, yielding 80 70 30 40 50 60 20 10. The next swap would
yield 80 70 60 40 50 30 20 10, and the last would yield 80 70 60 50 40 30 20 10.

Figure 4.7.4: Vector reversal program with correct output.

#include <iostream>
#include <vector>
using namespace std;

int main() {
const int NUM_ELEMENTS = 8; // Number of elements
vector<int> revVctr(NUM_ELEMENTS); // User values
unsigned int i; // Loop index
int tmpValue; // Placeholder

cout << "Enter " << NUM_ELEMENTS << " integer values..." << endl;
for (i = 0; i < revVctr.size(); ++i) {
cout << "Value: ";
cin >> revVctr.at(i);
}

// Reverse
for (i = 0; i < (revVctr.size() / 2); ++i) {
tmpValue = revVctr.at(i); // These 3 statements swap
revVctr.at(i) = revVctr.at(revVctr.size() - 1 - i);
revVctr.at(revVctr.size() - 1 - i) = tmpValue;
}

// Print values
cout << endl << "New values: ";
for (i = 0; i < revVctr.size(); ++i) {
cout << " " << revVctr.at(i);
}
cout << endl;

return 0;
}

Enter 8 integer values...


Value: 10
Value: 20
Value: 30
Value: 40
Value: 50
Value: 60
Value: 70
Value: 80

New values: 80 70 60 50 40 30 20 10

We should ensure the program works if the number of elements is odd rather than
even. Suppose the vector has 5 elements (0-4) with values 10 20 30 40 50.
revVctr.size() / 2 would be 5 / 2 = 2, meaning the loop expression would be i < 2.
The iteration when i is 0 would swap elements 0 and 4 (5-1-0), yielding 50 20 30 40
10. The iteration for i=1 would swap elements 1 and 3, yielding 50 40 30 20 10. The
loop would then not execute again because i is 2. So the results are correct for an
odd number of elements, because the middle element will just not move.

The mistakes made above are each very common when dealing with loops and vectors,
especially for beginning programmers. An incorrect (in this case out-of-range)
index, an incorrect swap, and an incorrect loop expression. The lesson is that
loops and vectors require attention to detail, greatly aided by manually executing
the loop to determine what is happening on each iteration. Ideally, a programmer
will take more care when writing the original program, but the above mistakes are
quite common.

###################################################################################
##########################################################
4.8 Arrays vs. vectors

C++ supports two kinds of ordered list types.

Arrays: declared as int myList[10], accessed as myList[i].


Vectors: declared as vector<int> myList(10), accessed as myList.at(i).
Arrays have a simpler syntax than vectors, but vectors are safer to use. Thus,
using vectors rather than arrays is good practice.

Vectors are safer because the access v.at(i) is checked during execution to ensure
the index is within the vector's valid range. An array access a[i] involves no such
check. Such checking is important; trying to access an array with an out-of-range
index is a very common error, and one of the hardest errors to debug.

int userWeights[3];
int userAge;

userAge = 44;

userWeights[0] = 122;
userWeights[1] = 119;
userWeights[2] = 117;
userWeights[3] = 199; // (Problematic)

// Print userAge

1. Variable userAge is allocated a location in memory immediately after the array


userWeights. userAge is assigned with 44.
2. Each element of array userWeights is assigned a value.
3. 3 is out of userWeights's index range, and results in overwriting userAge's
value.

As shown above, assigning with an out-of-range index can mysteriously change some
other variable's value. Debugging such an error can be a nightmare.

Vectors have more advantages, like resizing during runtime, easy insertion of items
at the front or rear, determining vector size, etc., discussed later. Arrays have
minor benefits that don't really outweigh drawbacks. Like choosing to not wear
seatbelts, choosing to not use vectors may be quite risky.

C++ allows vectors to be accessed using brackets [], but brackets involve no range
checking, so a good practice is to use .at() to access vector elements.

###################################################################################
##########################################################
4.9 Two-dimensional arrays

An array can be declared with two dimensions. int myArray[R][C] represents a table
of int variables with R rows and C columns, so R*C elements total. For example, int
myArray[2][3] creates a table with 2 rows and 3 columns, for 6 int variables total.
Example accesses are myArray[0][0] = 33; or num = myArray[1][2].

// Define array with size [2][3]

// Write to some elements


myArray[0][0] = 55;
myArray[1][1] = 77;
myArray[1][2] = 99;

1. Conceptually, a two-dimensional array is a table with rows and columns.


2. A two-dimensional array is implemented in a one-dimensional memory by placing
each row following the previous row.

Conceptually, a two-dimensional array is a table with rows and columns. The


compiler maps two-dimensional array elements to one-dimensional memory, each row
following the previous row, known as row-major order.

###################################################################################
##########################################################
Figure 4.9.1: Using a two-dimensional array: A driving distance
between cities example.

#include <iostream>
using namespace std;

/* Direct driving distances between cities, in miles */


/* 0: Boston 1: Chicago 2: Los Angeles */

int main() {
int cityA; // Starting city
int cityB; // Destination city
int drivingDistances[3][3]; // Driving distances

// Initialize distances array


drivingDistances[0][0] = 0;
drivingDistances[0][1] = 960; // Boston-Chicago
drivingDistances[0][2] = 2960; // Boston-Los Angeles
drivingDistances[1][0] = 960; // Chicago-Boston
drivingDistances[1][1] = 0;
drivingDistances[1][2] = 2011; // Chicago-Los Angeles
drivingDistances[2][0] = 2960; // Los Angeles-Boston
drivingDistances[2][1] = 2011; // Los Angeles-Chicago
drivingDistances[2][2] = 0;

cout << "0: Boston 1: Chicago 2: Los Angeles" << endl;

cout << "Enter city pair (Ex: 1 2) -- ";


cin >> cityA;
cin >> cityB;

if ((cityA >= 0) && (cityA <= 2) && (cityB >= 0) && (cityB <= 2)) {
cout << "Distance: " << drivingDistances[cityA][cityB];
cout << " miles." << endl;
}

return 0;
}

A programmer can initialize a two-dimensional array's elements during declaration


using nested braces, as below. Multiple lines make the rows and columns more
visible.

###################################################################################
##########################################################
Construct 4.9.1: Initializing a two-dimensional array
during declaration.

// Initializing a 2D array
int numVals[2][3] = { {22, 44, 66}, {97, 98, 99} };

// Use multiple lines to make rows more visible


int numVals[2][3] = {
{22, 44, 66}, // Row 0
{97, 98, 99} // Row 1
};

Arrays of three or more dimensions can also be declared, as in int myArray[2][3]


[5], which declares a total of 2*3*5 or 30 elements. Note the rapid growth in size
-- an array declared as int myArray[100][100][5][3] would have 100*100*5*3 or
150,000 elements. A programmer should make sure not to unnecessarily occupy
available memory with a large array.

4.10 C++ example: Annual salary tax rate calculation with vectors
zyDE 4.10.1: Various tax rates.
Vectors are useful to process tabular information. Income taxes are based on annual
salary, usually with a tiered approach. Below is an example of a simple tax table:

Annual Salary Tax Rate


0 to 20000 10%
Above 20000 to 50000 20%
Above 50000 to 100000 30%
Above 100000 40%

The below program uses a vector salaryBase to hold the cutoffs for each salary
level and a parallel vector taxBase that has the corresponding tax rate.

Run the program and enter annual salaries of 40000 and 60000, then enter 0.
Modify the program to use two parallel vectors named annualSalaries and taxesToPay,
each with 10 elements. Vectors annualSalaries holds up to 10 annual salaries
entered; vector taxesToPay holds up to 10 corresponding amounts of taxes to pay for
those annual salaries. Print the total annual salaries and taxes to pay after all
input has been processed.
Run the program again with the same annual salary numbers as above.
The following program calculates the tax rate and tax to pay based on annual
income.

###################################################################################
##########################################################
zyDE 4.10.2: Various tax rates (solution).

#include <iostream>
#include <vector>
using namespace std;

int main() {
const int MAX_ELEMENTS = 10;
int annualSalary;
double taxRate;
int taxToPay;
int totalSalaries;
int totalTaxes;
int numSalaries;
bool keepLooking;
unsigned int i;
int j;

vector<int> salaryBase(5);
vector<double> taxBase(5);
vector<int> annualSalaries(MAX_ELEMENTS);
vector<int> taxesToPay(MAX_ELEMENTS);

salaryBase.at(0) = 0;
salaryBase.at(1) = 20000;
salaryBase.at(2) = 50000;
salaryBase.at(3) = 100000;
salaryBase.at(4) = 99999999;

taxBase.at(0) = 0.0;
taxBase.at(1) = 0.10;
taxBase.at(2) = 0.20;
taxBase.at(3) = 0.30;
taxBase.at(4) = 0.40;

numSalaries = 0;

cout << "\nEnter annual salary (0 to exit): " << endl;


cin >> annualSalary;

while ((annualSalary > 0) && (numSalaries < MAX_ELEMENTS)) {


i = 0;
taxRate = 0;
keepLooking = true;

// Search for appropriate table row for given annualSalary


while ((i < salaryBase.size()) && keepLooking) {
if (annualSalary <= salaryBase.at(i)) {
taxRate = taxBase.at(i);
keepLooking = false;
}
else {
++i;
}
} // End inner while loop (search for appropriate table row)

taxToPay = static_cast<int>(annualSalary * taxRate); // Truncate tax to an


integer amount
annualSalaries.at(numSalaries) = annualSalary;
taxesToPay.at(numSalaries) = taxToPay;

cout << "Annual salary: " << annualSalaries[numSalaries] <<


"\tTax rate: " << taxRate <<
"\tTax to pay: " << taxesToPay[numSalaries] << endl;
++numSalaries;

// Get the next annual salary


cout << "\nEnter annual salary (0 to exit): " << endl;
cin >> annualSalary;
} // End outer while loop (valid annualSalary entered)

// Sum the annual salaries and taxes to pay and print the totals
totalSalaries = 0;
totalTaxes = 0;

for (j = 0; j < numSalaries; ++j) {


totalSalaries += annualSalaries[j];
totalTaxes += taxesToPay[j];
}
cout << "\nTotal salaries: " << totalSalaries <<
"\tTotal taxes: " << totalTaxes << endl;

return 0;
}

###################################################################################
##########################################################
4.11.1: LAB: Sort a vector
4.11 LAB: Sort a vector

Define a function named SortVector that takes a vector of integers as a parameter.


Function SortVector() modifies the vector parameter by sorting the elements in
descending order (highest to lowest). Then write a main program that reads a list
of integers from input, stores the integers in a vector, calls SortVector(), and
outputs the sorted vector. The first input integer indicates how many numbers are
in the list.

Ex: If the input is:

5 10 4 39 12 2
the output is:

39,12,10,4,2,
For coding simplicity, follow every output value by a comma, including the last
one.

Your program must define and call the following function:


void SortVector(vector<int>& myVec)

Hint: Sorting a vector can be done in many ways. You are welcome to look up and use
any existing algorithm. Some believe the simplest to code is bubble sort:
https://en.wikipedia.org/wiki/Bubble_sort. But you are welcome to try others:
https://en.wikipedia.org/wiki/Sorting_algorithm.

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

/* Define your function here */


void SortVector(vector<int>& myVec) {
// uses std::sort functions, and greater<int>() comparator
sort(myVec.begin(), myVec.end(), greater<int>());
}

int main() {
/* Type your code here */
// number we take from user to determine size of array
int n;
// read the val from the user and pass it to variable n
cin >> n;
// create an integer array of the size n taken from the user
vector<int> myVec(n);

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


cin >> myVec[i];
}

// call the sortVector function


SortVector(myVec);

// output the sorted vector with commas

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


cout << myVec[i];
if (i < n - 1) {
cout << ",";
}
else {
cout << ",";
}
}
cout << endl;
return 0;
}

^ Aight so I cheated and used AI to help because wtf I don't even think we have
learned how to define functions unless I somehow stumbled through that? What an
insane complexity creep in one problem worth a fraction of points... I hate this
class sometimes.

Lol we had not, in fact....

###################################################################################
##########################################################
5.1 User-defined function basics

Functions (general)

A program may perform the same operation repeatedly, causing a large and confusing
program due to redundancy. Program redundancy can be reduced by creating a grouping
of predefined statements for repeatedly used operations, known as a function. Even
without redundancy, functions can prevent a main program from becoming large and
confusing.

Pizza Funk

#include <iostream>
using namespace std;

double CalcPizzaArea() {
double pizzaDiameter;
double pizzaRadius;
double pizzaArea;
double piVal = 3.14159265;

pizzaDiameter = 12.0;
pizzaRadius = pizzaDiameter / 2.0;
pizzaArea = piVal * pizzaRadius * pizzaRadius;
return pizzaArea;
}
int main() {
cout << "12 inch pizza is " << CalcPizzaArea();
cout << " inches squared." << endl;
return 0;
}

Returning a value from a function


A function may return one value using a return statement. Below, the
ComputeSquare() function is defined to have a return type of int; thus, the
function's return statement must have an expression that evaluates to an int.

Squares in a Funk

#include <iostream>
using namespace std;

int ComputeSquare(int numToSquare) {


return numToSquare * numToSquare;
}

int main() {
int numSquared;

numSquared = ComputeSquare(7);
cout << "7 squared is " << numSquared << endl;

return 0;
}

Other return types are allowed, such as char, double, etc. A function can only
return one item, not two or more. A return type of void indicates that a function
does not return any value.

Questions:

The following is a valid function definition?:


char GetItem() { ... }

A: True!

2) The following is a valid function definition for a function that returns two
items:
int, int GetItems() { ... }

A: False: A function can only return one item, not two or more.

3) The following is a valid function definition:


void PrintItem() { ... }

True: A void return type means the function returns no value. Ex: A function that
outputs data may have no need to return a value. The function typically has no
return statement (but may have: return; with no expression).
###################################################################################
##########################################################

Parameters

A programmer can influence a function's behavior via an input.

A parameter is a function input specified in a function definition. Ex: A pizza


area function might have diameter as an input.
An argument is a value provided to a function's parameter during a function call.
Ex: A pizza area function might be called as CalcPizzaArea(12.0) or as
CalcPizzaArea(16.0).

A parameter is like a variable declaration. Upon a call, the parameter's memory


location is allocated, and the parameter is assigned with the argument's value.
Upon returning to the original call location, the parameter is deleted from memory.

An argument may be an expression, like 12.0, x, or x * 1.5.

5.1.8: Function with parameters example: Calculating pizza


area for different diameters.

#include <iostream>
using namespace std;

double CalcPizzaArea(double pizzaDiameter) {


double pizzaRadius;
double pizzaArea;
double piVal = 3.14159265;

pizzaRadius = pizzaDiameter / 2.0;


pizzaArea = piVal * pizzaRadius * pizzaRadius;
return pizzaArea;
}

int main() {
cout << "12.0 inch pizza is "<< CalcPizzaArea(12.0)
<< " square inches." << endl;
cout << "16.0 inch pizza is "<< CalcPizzaArea(16.0)
<< " square inches." << endl;
return 0;
}

Questions:

5.1.9: Parameters. --- IMPORTANT IMPLICIT DECLARATIONS DESCRIBED HERE....

1) Complete the function beginning to have a parameter named numServings of type


int.
A: int CalcCalories(int numServings) {

2) Write a statement that calls a function named CalcCalories, passing the value 3
as an argument.
A: CalcCalories(3);

3) Is the following a valid definition beginning? Type yes or no.


int myFct(int userNum + 5) {...}

A: NO: A parameter, like a variable declaration, cannot be an expression.

4) Assume a function int GetBirthdayAge(int userAge) simply returns the value of


userAge + 1. What will the following output?

cout << GetBirthdayAge(42);


cout << GetBirthdayAge(20);

A: 4321

Multiple or no parameters

A function definition may have multiple parameters, seperated by commas. Parameters


are assigned with argument values by position. First parameter with first argument,
second with second, etc.

A function definition with no parameters must still have the parentheses, as in:
int DoSomething() {...}. The vall must include parenthesis, with no argument, as
in: DoSomething().

###################################################################################
##########################################################
Figure 5.1.1: Function with multiple parameters.

#include <iostream>
using namespace std;

double CalcPizzaVolume(double pizzaDiameter, double pizzaHeight) {


double pizzaRadius;
double pizzaArea;
double pizzaVolume;
double piVal = 3.14159265;

pizzaRadius = pizzaDiameter / 2.0;


pizzaArea = piVal * pizzaRadius * pizzaRadius;
pizzaVolume = pizzaArea * pizzaHeight;
return pizzaVolume;
}

int main() {
cout << "12.0 x 0.3 inch pizza is " << CalcPizzaVolume(12.0, 0.3);
cout << " inches cubed." << endl;
cout << "12.0 x 0.8 inch pizza is " << CalcPizzaVolume(12.0, 0.8);
cout << " inches cubed." << endl;
cout << "16.0 x 0.8 inch pizza is " << CalcPizzaVolume(16.0, 0.8);
cout << " inches cubed." << endl;

return 0;
}
###################################################################################
##########################################################

Calling functions from functions

A function's statements may call other functions. In the example below, the
PizzaCalories() function calls the CalcCircleArea() function. (Note that main()
itself is the first function called when a program executes, and calls other
functions.)

Figure 5.1.2: Functions calling functions.


#include <iostream>
using namespace std;

double CalcCircleArea(double circleDiameter) {


double circleRadius;
double circleArea;
double piVal = 3.14159265;

circleRadius = circleDiameter / 2.0;


circleArea = piVal * circleRadius * circleRadius;

return circleArea;
}

double PizzaCalories(double pizzaDiameter) {


double totalCalories;
double caloriesPerSquareInch = 16.7; // Regular crust pepperoni pizza

totalCalories = CalcCircleArea(pizzaDiameter) * caloriesPerSquareInch;

return totalCalories;
}

int main() {
cout << "12 inch pizza has " << PizzaCalories(12.0) << " calories." << endl;
cout << "14 inch pizza has " << PizzaCalories(14.0) << " calories." << endl;

return 0;
}

Complete the function definition to return the hours given minutes. Output for
sample program when the user inputs 210.0:
3.5

#include <iostream>
using namespace std;

double GetMinutesAsHours(double origMinutes) {

/* Your solution goes here */


double hours = origMinutes / 60;
return hours;
}

int main() {
double minutes;

cin >> minutes;

// Will be run with 210.0, 3600.0, and 0.0.


cout << GetMinutesAsHours(minutes) << endl;

return 0;
}

###################################################################################
##########################################################

5.10 Pass by reference

Pass by reference

New programmers sometimes assign a value to a parameter, believing the assignment


updates the corresponding argument variable. An example situation is when a
function should return two values, whereas a function's return construct can only
return one value. Assigning a normal parameter fails to update the argument's
variable, because normal parameters are pass by value, meaning the argument's value
is copied into a local variable for the parameter.

C++ supports another kind of parameter that enables updating of an argument


variable. A pass by reference parameter does not create a local copy of the
argument, but rather the parameter refers directly to the argument variable's
memory location. Appending & to a parameter's data type makes the parameter pass by
reference type.

Pass by reference parameters should be used sparingly. For the case of two return
values, commonly a programmer should instead create two functions. For example,
defining two separate functions int StepsToFeet(int baseSteps) and int
StepsToCalories(int baseSteps) is better than a single function void
StepsToFeetAndCalories(int baseSteps, int& baseFeet, int& totCalories) . The
separate functions support modular development, and enables use of the functions in
an expression as in if (StepsToFeet(mySteps) < 100).

Using multiple pass by reference parameters makes sense when the output values are
intertwined, such as computing monetary change, whose function might be void
ComputeChange(int totCents, int& numQuarters, int& numDimes, int& numNickels, int&
numPennies), or converting from polar to Cartesian coordinates, whose function
might be void PolarToCartesian(int radialPol, int anglePol, int& xCar, int& yCar).

zyDE 5.10.1: Calculating monetary change.

Complete the monetary change program. Use the fewest coins (i.e., using maximum
larger coins first).

#include <iostream>
using namespace std;

// FIXME: Add parameters for dimes, nickels, and pennies.


void ComputeChange(int totCents, int& numQuarters, int& numDimes, int& numNickels,
int& numPennies) {

numQuarters = totCents / 25;


numDimes = (totCents - numQuarters * 25) / 10;
numNickels = (totCents - (numQuarters * 25 + numDimes * 10)) / 5;
numPennies = (totCents - (numQuarters * 25 + numDimes * 10 + numNickels * 5));
}

int main() {
int userCents;
int numQuarters;
int numDimes;
int numNickels;
int numPennies;
// FIXME add variables for dimes, nickels, pennies

cout << "Enter total cents: " << endl;


cin >> userCents;

ComputeChange(userCents, numQuarters, numDimes, numNickels, numPennies);

cout << "Quarters: " << numQuarters << endl;


cout << "Dimes: " << numDimes << endl;
cout << "Nickels: " << numNickels << endl;
cout << "Pennies: " << numPennies << endl;

return 0;
}

Reference variables

A programmer can also declare a reference variable. A reference is a variable type


that refers to another variable. Ex: int& maxValRef declares a reference to a
variable of type int. The programmer must initialize each reference with an
existing variable, which can be done by initializing the reference variable when
the reference is declared. Ex: int& maxValRef = usrInput3;

In the example below, usrValRef is a reference that refers to usrValInt. The user-
entered number is assigned to the variable usrValInt. Because usrValRef refers to
usrValInt, printing usrValInt or usrValRef will print the number.

Figure 5.10.2: Reference variable example.

#include <iostream>
using namespace std;

int main() {
int usrValInt;
int& usrValRef = usrValInt; // Refers to usrValInt

cout << "Enter an integer: ";


cin >> usrValInt;
cout << "We wrote your integer to usrValInt." << endl;
cout << "usrValInt is: " << usrValInt << "." << endl;
cout << "usrValRef refers to usrValInt, and is: " << usrValRef << "." << endl;

usrValInt = 99;
cout << endl << "We assigned usrValInt with 99." << endl;
cout << "usrValInt is now: " << usrValInt << "." << endl;
cout << "usrValRef is now: " << usrValRef << "." << endl;
cout << "Note that usrValRef refers to usrValInt, so it changed too." << endl;
return 0;
}

###################################################################################
##########################################################

CHALLENGE ACTIVITY
5.10.1: Function pass by reference: Transforming
coordinates.

Define a function CoordTransform() that transforms the function's first two input
parameters xVal and yVal into two output parameters xValNew and yValNew. The
function returns void. The transformation is new = (old + 1) * 2. Ex: If xVal = 3
and yVal = 4, then xValNew is 8 and yValNew is 10.

#include <iostream>
using namespace std;

int usrValInt;
int& usrValRef = usrValInt;
/* Your solution goes here */
void CoordTransform(int xVal, int yVal, int& xValNew, int& yValNew) {
xValNew = (xVal + 1) * 2;
yValNew = (yVal + 1) * 2;
}
int main() {
int xValNew;
int yValNew;
int xValUser;
int yValUser;

cin >> xValUser;


cin >> yValUser;

CoordTransform(xValUser, yValUser, xValNew, yValNew);


cout << "(" << xValUser << ", " << yValUser << ") becomes (" << xValNew << ", "
<< yValNew << ")" << endl;

return 0;
}

###################################################################################
##########################################################

Define a function ConvertVolume() that takes one integer parameter as


totalTablespoons, and two integer parameters passed by reference as cups and
tablespoons. The function converts totalTablespoons to cups and tablespoons. The
function does not return any value.

Ex: If the input is 90, then the output is:

5 cups and 10 tablespoons

Note: totalTablespoons / 16 computes the number of cups, and totalTablespoons % 16


computes the remaining tablespoons.

#include <iostream>
using namespace std;

/* Your code goes here */


void ConvertVolume(int totalTablespoons, int& cups, int& tablespoons) {
cups = totalTablespoons / 16;
tablespoons = totalTablespoons % 16;
}

int main() {
int usrCups;
int usrTablespoons;
int totalTablespoons;

cin >> totalTablespoons;

ConvertVolume(totalTablespoons, usrCups, usrTablespoons);

cout << usrCups << " cups and " << usrTablespoons << " tablespoons" << endl;

return 0;
}

###################################################################################
##########################################################

Define a function GetWeight() that takes one integer parameter passed by reference
as totalOunces and two integer parameters as pounds and ounces. If both pounds and
ounces are non-negative, the function computes totalOunces and returns true.
Otherwise, the function returns false without updating totalOunces.

Ex: If the input is 15 -1, then the output is:

Invalid. Total ounces: 0

Notes:

#include <iostream>
using namespace std;

/* Your code goes here */


int GetWeight(int& totalOunces, int pounds, int ounces) {
if (pounds >= 0 && ounces >= 0) {
totalOunces = (pounds * 16) + ounces;
return true;
}
else {
return false;
}
}

int main() {
int totalOunces;
int pounds;
int ounces;
bool valid;

totalOunces = 0;
cin >> pounds;
cin >> ounces;

valid = GetWeight(totalOunces, pounds, ounces);

if (valid) {
cout << "Total ounces: " << totalOunces << endl;
}
else {
cout << "Invalid. Total ounces: " << totalOunces << endl;
}

return 0;
}

###################################################################################
##########################################################

5.11 Functions with string/vector parameters

Functions commonly modify a string or vector. The following function modifies a


string by replacing spaces with hyphens.

#include <iostream>
#include <string>
using namespace std;

// Function replaces spaces with hyphens


void StrSpaceToHyphen(string& modStr) {
unsigned int i; // Loop index

for (i = 0; i < modStr.size(); ++i) {


if (modStr.at(i) == ' ') {
modStr.at(i) = '-';
}
}
}

int main() {
string userStr; // Input string from user

// Prompt user for input


cout << "Enter string with spaces: " << endl;
getline(cin, userStr);

// Call function to modify user defined string


StrSpaceToHyphen(userStr);

// Output modified string


cout << "String with hyphens: ";
cout << userStr << endl;

return 0;
}

Enter string with spaces:


Hello there everyone.
String with hyphens: Hello-there-everyone.

...

Enter string with spaces:


Good bye now !!!
String with hyphens: Good-bye--now---!!!

Sometimes a programmer defines a vector or string parameter as pass by reference


even though the function does not modify the parameter, to prevent the performance
and memory overhead of copying the argument that would otherwise occur.

The keyword const can be prepended to a function's vector or string parameter to


prevent the function from modifying the parameter. Programmers commonly make a
large vector or string input parameter pass by reference, to gain efficiency, while
also making the parameter const, to prevent assignment.

The following illustrates. The first function modifies the vector so it defines a
normal pass by reference. The second function does not modify the vector but for
efficiency uses constant pass by reference.

Figure 5.11.2: Normal and constant pass by reference vector parameters


in a vector reversal program.

#include <iostream>
#include <vector>
using namespace std;

void ReverseVals(vector<int>& vctrVals) {


unsigned int i; // Loop index
int tmpVal; // Temp variable for swapping

for (i = 0; i < (vctrVals.size() / 2); ++i) {


tmpVal = vctrVals.at(i); // These statements swap
vctrVals.at(i) = vctrVals.at(vctrVals.size() - 1 - i);
vctrVals.at(vctrVals.size() - 1 - i) = tmpVal;
}
}

void PrintVals(const vector<int>& vctrVals) {


unsigned int i; // Loop index

// Print updated vector


cout << endl << "New values: ";
for (i = 0; i < vctrVals.size(); ++i) {
cout << " " << vctrVals.at(i);
}
cout << endl;
}

int main() {
const int NUM_VALUES = 8; // Vector size
vector<int> userValues(NUM_VALUES); // User values
int i; // Loop index

// Prompt user to populate vector


cout << "Enter " << NUM_VALUES << " values..." << endl;
for (i = 0; i < NUM_VALUES; ++i) {
cout << "Value: ";
cin >> userValues.at(i);
}

// Call function to reverse vector values


ReverseVals(userValues);

// Print reversed values


PrintVals(userValues);

return 0;
}

Enter 8 values...
Value: 10
Value: 20
Value: 30
Value: 40
Value: 50
Value: 60
Value: 70
Value: 80

New values: 80 70 60 50 40 30 20 10

A reader might wonder why all input parameters are not defined as constant pass by
reference parameters: Why make local copies at all? The reason is efficiency. For
parameters involving just a few memory locations, making a local copy enables the
compiler to generate more efficient code, in part because the compiler can place
those copies inside a tiny-but-fast memory inside the processor called a register
file—further details are beyond our scope.

In summary:
Define a function's output or input/output parameters as pass by reference.
But create output parameters sparingly, striving to use return values instead.
Define input parameters as pass by value.
Except for large items (perhaps 10 or more elements); use constant pass by
reference for those.

This part is very confusing....

PARTICIPATION ACTIVITY
5.11.1: Constants and pass by reference.
How should a function's vector parameter ages be defined for the following
situations?

1) ages will always be small (fewer than 10 elements) and the function will not
modify the vector.

A: Constant but not pass by reference

Constant prevents the function from modifying ages. Since ages is small, pass by
reference is not used; instead, a copy of ages is made.

2) ages will always be small, and the function will modify the vector.

A: Pass by reference but not constant

Pass by reference makes ages modifiable, but constant prevents ages from being
modified.

3) ages may be very large, and the function will modify the vector.

A: Pass by reference but not constant

Pass by reference makes ages modifiable, but constant prevents ages from being
modified.

4) ages may be very large, and the function will not modify the vector.

A: Constant and pass by reference

Constant prevents the function from modifying ages. Since ages is large, pass by
reference is used to pass the original vector, instead of creating a copy.
PARTICIPATION ACTIVITY

5.11.2: Vector parameters.

Define a function's vector parameter ages for the following situations. Assume ages
is a vector of integers. Example: ages will always be small (fewer than 10
elements) and the function will not modify the vector: const vector<int> ages.

1) ages will always be small, and the function will modify the vector.

A: void MyFct (vector<int>& ages) {

Because the vector will be modified, the parameter must be pass by reference, and
of course cannot be constant. The size is not relevant; to be modified, the
parameter must be pass by reference.

2) ages may be very large, and the function will modify the vector

A: void MyFct (vector<int>& ages) {

Pass by reference but not constant. Because the function modifies the vector, the
size is irrelevant.

3) ages may be very large, and the function will not modify the vector.

A: void MyFct (const vector<int>& ages) {

Pass by reference (achieved using &) and constant (achieved using const).

Complete the function to replace any period by an exclamation point. Ex: "Hello.
I'm Miley. Nice to meet you." becomes:
"Hello! I'm Miley! Nice to meet you!"

#include <iostream>
#include <string>
using namespace std;

void MakeSentenceExcited(string& sentenceText) {

// Function replaces spaces with hyphens


unsigned int i; // Loop index

for (i = 0; i < sentenceText.size(); ++i) {


if (sentenceText.at(i) == '.') {
sentenceText.at(i) = '!';
}
}

int main() {
string testStr;

getline(cin, testStr);
MakeSentenceExcited(testStr);
cout << testStr;

return 0;
}

5.11.3: Modify a vector parameter.


Write a function SwapVectorEnds() that swaps the first and last elements of its
vector parameter. Ex: sortVector = {10, 20, 30, 40} becomes {40, 20, 30, 10}.

#include <iostream>
#include <vector>
using namespace std;

/* Your solution goes here */


void SwapVectorEnds(vector<int>& vectorVals) {
unsigned int i;
int tmpVal;
// to make complete vector swap change i < 1 to i < (vectorVals.size() / 2)
for (i= 0; i < 1; ++i) {
tmpVal = vectorVals.at(i);
vectorVals.at(i) = vectorVals.at(vectorVals.size() - 1 - i);
vectorVals.at(vectorVals.size() - 1 - i) = tmpVal;
}
}

int main() {
vector<int> sortVector(4);
unsigned int i;
int userNum;

for (i = 0; i < sortVector.size(); ++i) {


cin >> userNum;
sortVector.at(i) = userNum;
}

SwapVectorEnds(sortVector);

for (i = 0; i < sortVector.size(); ++i) {


cout << sortVector.at(i) << " ";
}
cout << endl;

return 0;
}

Complete the function GetLastIndex() that has one string parameter and one
character parameter. The function returns the index of the last character in the
string that is not equal to the character parameter. If no such character is found,
the function returns -1.
Ex: If the input is tnmmb m, then the output is:

#include <iostream>
using namespace std;

int GetLastIndex(string inputString, char x) {

/* Your code goes here */

for (int i = inputString.size() - 1; i >= 0; --i) {


if (inputString.at(i) != x) {
return i;
break;
}
else if (inputString.at(0) == x) {
return -1;

}
else {
return 0;
}
}
}

int main() {
string inString;
char x;
int result;

cin >> inString;


cin >> x;

result = GetLastIndex(inString, x);

cout << result << endl;

return 0;
}

You might also like