Download as pptx, pdf, or txt
Download as pptx, pdf, or txt
You are on page 1of 56

CS 201

Introduction to Computing

Fall 2021-2022
Week-5

● Loops - repetition
o Counting loops
o Sentinel loops
o For Loops and While Loops
o Strings with loops

Textbook Sections 5.1 and 5.2

2
From Selection to Repetition
● The if statement and if/else statement allow a block of
statements to be executed selectively: based on a condition

cout << "Please enter a non-negative number" << endl;


cin >> inputnumber;
if (inputnumber < 0){
cout << inputnumber << " is negative. Wrong Input" << endl;
}

● This piece of code does not ask another input if number < 0
● While statement repeatedly executes a block of statements
while the condition is true
cout << " Please enter a non-negative number" << endl;
cin >> inputnumber;
while (inputnumber < 0){
cout << inputnumber << " is negative! Try again"<<endl;
cin >> inputnumber;
}
Semantics of while loop
if (test){ while (test){

statement list; statement list;


} }

true true
test test

false Statement list false Statement list

Next statement Next statement


Sum Example: why we need loops?

● We want to find the sum of 10 positive values


● We can write:

int num1, num2, num3, num4, num5;


int num6, num7, num8, num9, num10;
int sum;
cin >> num1 >> num2 >> num3 >> num4 >> num5;
>> num6 >> num7 >> num8 >> num9 >> num10;
sum = num1 + num2 + num3 + num4 + num5;
sum += num6 + num7 + num8 + num9 + num10;
Sum Example (not in book)
● What if we want to compute the sum of
● 100 values
● an undetermined number of values

● What we need is a program to be able to read as many values


as we want and then compute the sum
● This is possible with loops

● Good solution is to use loops


● Code is developed on board: see sum10nums.cpp
● This type of loops are called counting loops
● number of iterations is known
while loop syntax

<initialization>
while (<test>)
{
<statement1>;
...
<statementN>;
<update>
}
Another simple example

● Calculate the sum of the integer numbers between 1 and 10

int sum = 0; // this program piece


int i = 1; // calculates the sum
of
while (i <= 10) // integers between and
{ // including 1 and 10
sum = sum + i;
i = i + 1;
}
Walkthrough of the example

i 1 2
int sum = 0; sum 0 1
int i = 1;
i<=10
while (i <= 10)
{
true false
sum = sum + i;
i = i + 1;
sum=sum+i;
} i=i+1;
cout << sum;

cout<<sum;
Walkthrough of the example

i 2 3
int sum = 0; sum 1 3
int i = 1;
i<=10
while (i <= 10)
{
true false
sum = sum + i;
i = i + 1;
sum=sum+i;
} i=i+1;
cout << sum;

cout<<sum;
Walkthrough of the example

i 3 4
int sum = 0; sum 3 6
int i = 1;
i<=10
while (i <= 10)
{
true false
sum = sum + i;
i = i + 1;
sum=sum+i;
} i=i+1;
cout << sum;

cout<<sum;
Walkthrough of the example

i 10 11
int sum = 0; sum 45 55
int i = 1;
i<=10
while (i <= 10)
{
true false
sum = sum + i;
i = i + 1;
sum=sum+i;
} i=i+1;
cout << sum;

cout<<sum;
while loop sum example

● Sum of numbers from 1..10

int sum = 0;
initialization
int i = 1;
while (i <= 10) test

{
sum = sum + i; body statements

i = i + 1; update
}
cout << sum;
Another easy example (not in book)

● Read a sequence of integer numbers from keyboard and


find their sum
● input should finish when user enters –1
● -1 is the sentinel value in this example
● not to be added to the sum

● Code is developed on board (see sumnums.cpp)

● This type of loop is called conditional loop


● number of iterations is not known
● depends on input
Anatomy of a loop
● Initialize variables used in loop body and loop test (before the loop)
● No general rule; the way of initialization and the initial values are to be
determined according to the application
● The loop test is evaluated before each loop iteration
● NOT evaluated after each statement in the loop body
● Current value of variables are used for the loop test before each iteration
● The loop body must update some variables used in the loop test so that the loop
eventually terminates
● If loop test is always true, loop is infinite
● Infinite loops must be avoided

● Basic rule of designing a loop:


● Initialization, loop test and update parts should be designed carefully in order
to iterate the loop as many times as needed, but not one less or one more.
● Unfortunately there is no straightforward rule of designing a bug-free loop
● you should be able to develop those parts by understanding and analyzing
the underlying problem that needs a loop
for loop syntax

for (<initialization>; <test>; <update>)


{
<statement1>;
...
 <statementN>;
}

● Initialization, test and update parts are combined


● Good for counting on an index kind of loops
for loop syntax compared with while

<initialization> for(<initialization>;<test>;<update>)
while(<test>) {
{ <statement1>;
<statement1>; ...
 <statementN>;
...
}
<statementN>;
<update>
}
for loop example

•Rewrite the same loop: sum of numbers from 1..10

int sum = 0; int sum = 0;


int i = 1;
while (i <= 10) for (int i=1; i <= 10; i=i+1)
{ {
sum = sum + i; sum = sum + i;
i = i + 1; }
}
The for loop
● initialization statement
● executed once before the loop
● test expression
● boolean expression
● checked each time before entering the loop body
● if true execute loop body, if false terminate loop
● update statement
● executed after the last statement of the loop body
● several statements in initialization and update are separated by comma
for (len = s.length(), k=0; k < len; k+=1)
● initialization and/or test and/or update parts could be missing
● but semicolons are there
int k = 0;
for (; k < len; k+=1)
The for loop
● For loops are good for counting loops (although they can be used for conditional loops)
● Number of iterations known before loop begins
● Example: sum of 10 input numbers
● Example: print a string vertically

void Vertical(string s)
// post: chars of s printed vertically // for loop alternative 1
int len; int k; int len; int k;
len = s.length(); len = s.length();
k = 0; for(k=0; k < len; k+= 1){
while (k < len){ cout << s.substr(k,1) << endl;
cout << s.substr(k,1) << endl; }
k += 1;
}
// for loop alternative 2
// for loop alternative 3 int len; int k;
int len; int k; for(len = s.length(), k=0; k < len; k+= 1){
len = s.length(); cout << s.substr(k,1) << endl;
k = 0; }
for(; k < len; k+= 1){
cout << s.substr(k,1) << endl;
}
Example: Print a string backwards
(revstring.cpp)
● Determine the index of the last character of the string,
and then access each character backwards
● How many times should the loop iterate ?
string s; int k;
cout << "enter string: ";
cin >> s;
cout << s << " reversed is ";
k = s.length() - 1; // index of last character in s
while (k >= 0){
cout << s.substr(k,1);
k -= 1;
}
cout << endl;
● What could we use instead of s.substr(k,1) ? s.at(k)
Reverse String as a function
● First step, what is the prototype?

string revstring(string s)
// pre: s = c0c1c2…cn-1
// post: return cn-1…c2c1c0

● Second step, how do we build a new string?


● Start with an empty string, ""
● Add one character at each iteration using concatenation, +

rev = rev + s.substr(k,1);

● Use revstring to determine if a string is a palindrome


See palindrome.cpp for full program
string revstring(string s){
// post: returns reverse of s, that is "stab" for "bats“
int k = s.length() – 1;
string rev = ""; // start with empty string

while (k >= 0){


rev = rev + s.substr(k,1);
k -= 1;
}
return rev;
}

bool IsPalindrome(string word){


// post: returns true if and only word is a palindrome
return (word == revstring(word));
}
Bad loops

1. for (int i = 10; i < 5; i++) {


cout << "How many times do I print?";
}

2. for (int i = 10; i >= 1; i++) {


cout << "How many times do I print?";
}

3. int i = 1;
while (i < 20) {
cout << "How many times do I print?";
}
Bad loops
● Never executes
● Never stops (infinite loops)
● Example: consider the following modified code from sum10nums
● What’s the problem in the loop below? What is missing?

sum = 0;
count = 1;
while (count <= 10){
cin >> num;
sum += num;
}

● count never reaches 10,


because count is not updated in the loop
Infinite loops

● Infinite loop is something that must be avoided

● happens when the loop condition is always true


● same loop body iterates forever
● sometimes you see an output, sometimes you don't
● press Ctrl-C to stop (⌘. on Xcode)
● could be because of a wrong or missing update statement
● could be because of a wrong condition
● could be another reason
Infinite loops
● What is the problem with the code below?
● cannot say infinite loop, depends on input number
● for example, if num is an odd number, then the loop is infinite
cin >> num;
int start = 0;
while (start != num){
start += 2;
cout << start << endl;
}

● How to fix?
● You can check whether num is even before starting the loop.
if (num % 2 == 0)
while (start != num){
start += 2;
cout << start << endl;
}
Other Common Problems

● Easy to iterate one more or one less times

● Test each loop with the inputs that cause:


● zero iterations of the loop body
● one iteration of the loop body
● maximum number of iterations
● one less than the maximum number of iterations

● Use the debugger and watch the variables


Developing Loops

● Some loops are easy to develop, others are not

● Sometimes the proper loop test and body are hard to design

● Practice helps, but remember:


● Good design comes from experience, experience comes
from bad design
Number Crunching

● Number crunching is a CS term that means a computing


operation that requires several (and sometimes complex)
arithmetic operations
● It was the job of early computers
● Numerical Analysis
● classical sub-discipline of computer science
● Today
● implicitly or explicitly, all operations are numeric
● Now we will see some mathematical applications
● factorial calculation
● prime number testing
Factorial
● n! = 1x2x…xn is "n factorial"; used in math, statistics

long factorial(long n)
// pre: 0 <= n
// post: returns n! (1 x 2 x … x n)

● Similar to sum, but this time we will calculate a product within


the loop; and at the end we will return the final product
● The loop will iterate n times, multiplying by 1, 2, …, n
● Suppose we use a variable called product to hold the result,
then product is n! when the loop terminates; then we will
return it at the end
Factorial
int Factorial(int num){
// precondition: num >= 0
// postcondition returns num! (1 x 2 x … x num)
int product = 1;
int count = 0;
while (count < num){
count += 1;
product *= count;
}
return product;
}

● Issues
● What happens if we initialize count to 1?

● Let’s see fact.cpp


Factorial (Cont’d) – Using BigInt class
● What is the problem of the previous program?
● integer overflow
● 12! is 479,001,600 so what happens with 13! ?
● The type BigInt, accessible via #include "bigint.h" can be used
like an int, but gets as big as you want it to be
● Really arbitrarily large?
● No, limited to computer memory
● Disadvantages of using BigInt compared to int?
● processing speed is lower
● uses up more memory
● Use BigInt if you really need it
● Do not forget to add bigint.cpp to your project,
● BigInt is a Tapestry class
● Download wincode.zip file from http://cs.duke.edu/csed/tapestry

See bigfact.cpp
Determining if a number is prime
● Prime number is a natural number having only two divisors: 1 & itself
● Some Cryptographic algorithms depend on prime numbers
● Determining if a number is prime must be "easy"
● Actually factoring a number must be "hard"
● "hard" in the sense that it must be computationally infeasible to
factorize in a reasonable amount of time
● RSA Cryptosystem
● Rivest, Shamir, Adleman
● based on the factorization problem of large numbers
● has been utilized by several security products and services
● PGP (Pretty Good Privacy) – email security
● WWW security using SSL protocol
● Sophisticated mathematics used for fast prime-testing, we'll do basic
prime testing
● Since our algorithm is based on factorization, it will be really slow for
large numbers
Determining Primeness (continued)
● 1 is NOT prime, 2 is prime, 3 is prime, 17 is prime, … 137, 193?
● We don't need to check even numbers other than 2 (2 is special case)
● To check 193, divide it by 3, 5, 7, 9, 11, 13
● Note that 14x14 = 196, so 13 largest potential factor?
● We will use modulus operator to check divisibility

● We'll check odd numbers as potential divisors


● Watch out for 2, it is a special case
● How far should we go to check potential divisors?
● Up to and including sqrt(number) + 1
● If there was a bigger factor, a smaller factor would exist; and this
smaller one must have been checked before; so we do not need to
go beyond this limit
● +1 is to make sure that there will be no problems with precision
● See primes.cpp for code
Primeness Check – Details
● Special even number check is added before the loop to
eliminate even numbers to be checked in the loop
● In order to make the code more efficient, the limit is
selected as the sqrt(n) + 1

● To assign a double value to an int, a typecast is used, to


tell the compiler that the loss of precision is intentional
● Make typecasts explicit to tell the compiler you know
what you are doing
● Compiler warnings are avoided
int limit = int(sqrt(n) + 1);

● We will see typecast in more detail later


Downward-counting loop

● Calculate n to the power of m: nm=nxnx…xn


● Example: 25=2x2x2x2x2=32

int power = 1;
int n, m;
cin >> n >> m;
for (int i = m; i >= 1; i--){
power = power * n;
}
Nested loops
● Sometimes one loop occurs in another
● Generating 2-dimensional tabular data
● multiplication table
● Sorting vectors (which will be studied much later)
● Display some geometric figures using character *
(or any other character)
● display rectangles, triangles

● Although other loops can be nested as well, most of the


time, for loops are used in nested manner
Nested loops - Example
● Write a function to display a rectangle of stars
(height and width are parameters)
● e.g. if height is 4 and width is 7, the output should look like
*******
*******
*******
*******
for (i=1; i<= height; i++){
for (j=1; j<=width; j++) // inner loop prints 1 line of stars
cout << "*";
cout << endl; // end of line is put to the end of each line
}

● See drawfigures.cpp for the complete function and its use in main
Nested loops - Example
● Write a function to display a perpendicular isosceles triangle of stars
(perpendicular side length is parameter)
● e.g. if side length is 5, the output should look like
*
**
***
****
*****

for (i=1; i <= side; i++){


for (j=1; j<=i; j++) // inner loop prints 1 line of stars
cout << "*";
cout << endl; // end of line is put to the end of each line
}

● See drawfigures.cpp for the complete function and its use in main
Same loop: downward-counting

for (i=1; i <= side; i++){ for (i=1; i <= side; i++){
for (j=1; j<=i; j++){ for (j=i; j>=1; j--){
cout << "*"; cout << "*";
} }
cout << endl; cout << endl;
} }
Drawfigures – Other Considerations
● What about having a function to display a line of stars
(number of stars is a parameter)
● useful for both rectangle and triangle
void PrintLine (int numstars){
// pre: numstars > 0
// post: displays numstars stars in one line
int i;
for (i=1; i<= numstars; i++)
cout << "*";
cout << endl; // end of line is put to the end of the line
}

● in rectangle function, inner loop is replaced by a function call


for (i=1; i<=height ; i++)
PrintLine(width);

● use of PrintLine in triangle function is similar


Example – Multiplication Table
● On ith line print, i*1, i*2, i*3, ... , i*i
● Total number of lines is an input; display lines starting with 1
● See multiply.cpp #include <iostream>
#include <iomanip> // for setw
using namespace std;

int main(){
int i,k,numlines;
const int WIDTH = 4;
cin >> numlines;

for (i=1; i <= numlines; i++){


for (k=1; k <= i; k++){
cout << setw(WIDTH) << i*k;
}
cout << endl;
}
return 0;
}
Constants (re-visit)
● Sometimes very useful
● provides self documentation
● re-use the same value across the program
● avoid accidental value changes

● Like variables, but their value is assigned at declaration and


can never change afterwards
● declared by using const before the type name (any type is OK)
const double PI = 3.14159;
const string thisclass = "CS201"
const int WIDTH = 4;
● later you can use their value
cout << (PI * 4 * 4);
● but cannot change their value
PI = 3.14; causes a syntax error
Formatting Output
● We use stream manipulator setw to specify the total number
of spaces that the next output will use
● setw(field length)
● written in cout and affects only the next output value
not the whole cout line
● output is displayed using field length spaces in right
justified manner (any empty space is on the left)
● defined in header file <iomanip>, so you have to have
#include <iomanip>
● Example
cout << setw(9) << "cs201";
● output shown is four blanks and cs201
Shorthand for increment/decrement
● Lots of code requires incrementing a variable by one
● Three methods, using = and +, using +=, and using ++
● effectively they are same
num = num + 1;
num += 1;
num++; // post increment
● It is also possible to write ++num;
● pre-increment
● These differ on when the increment is performed, but this
difference doesn't matter when used as an abbreviation for
the statement n += 1; in a single statement
● Similarly there are post-decrement (and pre-decrement)
num = num - 1; num -= 1; num--;
for loop syntax compared with while
(re-visit)

<initialization> for (<initialization>;

while (<test>) <test>;

{ <update> )

<statement1>; {

... <statement1>;
...
<statementN>;
 <statementN>;
<update>
}
}
Example
● Rewrite the while loop of main of primes.cpp using for loop

k = low;
while (k <= high) for (k = low; k <= high; k += 1)
{ {
if (IsPrime(k)) if (IsPrime(k))
{ {
cout << k << endl; cout << k << endl;
numPrimes += 1; numPrimes += 1;
} }
k += 1; }
}
The do-while loop
● Similar to while loop, but test is after the execution of the loop body
● while loop may never execute, do-while loop executes at least once
<initialization>
do{
<statement1>;
   ...
  <statementN>; Don't
<update> forget
} while (<condition>);

● Example: Prompt for a number between 0 and 100, loop until such a
number is entered (user should enter at least one number)

do{
cout << "enter number in range [0..100] ";
cin >> num;
} while (num < 0 || num > 100 );
while loop versus do-while loop
Priming
● Priming: reading an initial value before the loop
● do not get confused with prime numbers; this is something else
● Problem: enter numbers, add them up, stop when -1 entered

int sum = 0;
int num;
cin >> num; // prime the loop
while (num != -1){
sum += num;
cin >> num;
}
cout << "total = " << sum << end;

● Code duplication exists here: input (and perhaps prompt) code


is repeated before the loop and in the loop
Pseudo infinite solution using break
● To avoid repeating code, include it in the body of the loop only,
use a test to break out of the loop
● break statement exits (inner-most) loop
● Try not to use break in this course
● Save it for later when you develop really complicated loops

int sum = 0;
int num;
while (true){ // seemingly infinite loop
cin >> num;
if (num == -1)
break; // get out of loop
sum += num;
}
cout << "total = " << sum << end;
Fence Post Problem
● Problem that occurs when one or more operations of the loop
body are executed one less then the others
● Example: Display integers between 1 and 10 separated by comma
1,2,3,4,5,6,7,8,9,10
● no comma after 10; no comma before 1

for (n=1; n <= 10; n++){


cout << n << ",";
} // Problem: comma after 10

for (n=1; n < 10; n++){


cout << n << ",";
}
cout << n; // No problem, but code duplicates
● Think of other solutions! (see page 175 of Tapestry)
One Possible Exam Question
Write a function that takes an integer as its only parameter,
say num, and returns the number of unique digits in this integer
parameter. This function should also display those of the digits
that occur exactly once.

For example, if the input is 10003, then the function should


return 2 and the output would be "1 3", since 1 and 3 are the
unique digits.

As another example, if the input is 12345, then the function


should return 5 and the output would be "1 2 3 4 5", since
1,2,3,4 and 5 are the unique digits it contains.

uniqueDigits.cpp
Another Possible Exam Question
Write a C++ program that takes string inputs as words until
the user enters the word "end", case-insensitively, and
concatenates them to makeup a sentence (except for "end").
Your program should then display the most frequent character
appearing in the constructed sentence.

Here is a sample run for the program:


Please enter a word: hi
Please enter a word: there
Please enter a word: welcome
Please enter a word: to
Please enter a word: SU
Please enter a word: END
Sentence is: hi there welcome to su
Most frequent character is: e mostFreqChar.cpp

You might also like