430 likes | 696 Views
First Midterm Exam. November 22 , 200 8 , Saturday 1 0 :40 – 1 2 :20 max 100 minutes One A4 size cheat-note allowed Closed book, closed notes, no calculators and no laptops Until the end of loops A detailed email will be sent later
E N D
First Midterm Exam • November 22, 2008, Saturday • 10:40 – 12:20 • max 100 minutes • One A4 size cheat-note allowed • Closed book, closed notes, no calculators and no laptops • Until the end of loops • A detailed email will be sent later • Next week, a Sample Question Set will be posted on the website of the course • Solutions will be posted later
Homework 3 • Homework 3 is due November 5, 2008, 19:00 • Robot application. • Be careful where and how you create the robots • Robot must be created only once within the main • Examine example robot programs covered in recitations • Scope rules say that each identifier can be used only in the compound block in which it is declared • If you receive an “undeclared identifier” error for a robot even you declare it, check where you declare and use it! • Use of functions • You have to split the task into several functions • Do not forget to use & for robot parameters
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 number if the number is negative. ------------------------------------------------------------------------------------------------------ • The 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; }
true true test test false false Statement list Next statement Statement list Next statement Semantics of while loop if (test) while (test) { { statement list; statement list; } }
Another simple example • Calculate the sum of the integer numbers between 1 and 10 int sum = 0; // this program piece int num = 1; // calculates the sum of while (num <= 10) // integers between and { // including 1 and 10 sum = sum + num; num += 1; }
Easy Example (not in book) • Input 10 integer numbers and find their sum • What about having cin >> num; sum = sum + num; 10 times? • not a good solution • 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
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 sum = 0; count = 1; while (count <= 10) { cin >> num; sum += num; count += 1; } initialization Loop test expression Loop body Update statement
Anatomy of a loop • Initialize variables used in loop body and loop test (before 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 • neither one less nor 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
The for loop • Initialization, test and update parts are combined for (initialization; looptest expression; update) { statement list; //loop body } • 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 in every iteration
for loop example sum = 0; count = 1; while (count <= 10) { sum = sum + count; count = count + 1; } sum = 0; for (count =1; count <= 10; count = count+1) { sum = sum + count; }
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); }
Infinite loops • Infinite loop is something that must be avoided • happens when the loop condition is always true • same loop body iterates indefinitely • sometimes you see an output, sometimes you don’t • press Ctrl-C to stop • maybe the effect of a wrong or missing update statement • maybe due to a wrong condition; may be due to another reason • Example: consider the following modified code from sum10nums • What’s the problem in the loop below? What is missing? • count never reaches 10, because count is not updated in the loop sum = 0; count = 1; while (count <= 10) { cin >> num; sum += num; }
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; }
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 • There are other loop statements in addition to while, • for loop • do-while loop • similar idea • some minor differences • will see later
Number Crunching • Number crunching is a CS term that means a computing operation that requires several (and sometimes complex) arithmetic operations • was the job of early computers • Numeric Analysis • classical subdiscipline 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. 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 productis n! when the loop terminates. So we will return it at the end.
Factorial long Factorial(int num) // precondition: num >= 0 // postcondition returns num! (1 x 2 x … x num) { long product = 1; int count = 0; while (count < num) { count += 1; product *= count; } return product; } • Issues • Why did we use long? What happens if we use int instead? • 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 • even long is not sufficient (actually there is not difference between long and int for 32-bit computers like ours) • 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, but computers most likely run out of time before running out of 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
Factorial using BigInt class • See bigfact.cpp
Determining if a number is prime • Prime numberis a natural number which has only two divisors: 1 and 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) – e-mail security • WWW security using SSL protocol • Sophisticated mathematics used for fast prime-testing, we’ll do basic prime testing that’s reasonably fast for small numbers, but not good enough for RSA (why not?) • because our algorithm is based on factorization, so it is really slow for large numbers
Determining Primeness (continued) • 1 is NOT prime, 2 is prime, 3 is prime, 5 is prime, 17 is prime, … 137, 193? • We do not need to check even numbers other than 2 (2 is a special case) • To check 193, divide it by 3, 5, 7, 9, 11, 13 • Note that 14x14 = 196, so 13 largest potential factor? • we 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 there 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 int limit = int(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 • We will see typecast in more detail later
What is next with loops • Loops are useful instruments in program development • Loops are statements, can be combined with other loops, with if statements, in functions, etc. • Other kinds of looping statements can make programming simpler • for loops • good for counting loops • do – while loops • good if the loop body must be executed at least once • nested loops • loops inside other loops
The for loop • Initialization, test and update parts are combined for (initialization; test expression; update) { statement list; //loop body } • 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 in every iteration • several statements in initialization and update are separated by comma • initialization and/or test and/or update parts could be missing • but semicolons are there
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 int len; int k; len = s.length(); k = 0; while (k < len) { cout << s.substr(k,1) << endl; k += 1; } // for loop alternative 1 // for loop alternative 2 int len; int k; len = s.length(); int len; int k; for(k=0; k < len; k+= 1) for(len = s.length(), k=0; k < len; k+= 1) { cout << s.substr(k,1) << endl; { cout << s.substr(k,1) << endl; } } // for loop alternative 3 int len; int k; len = s.length(); k = 0; for(; k < len; k+= 1) { cout << s.substr(k,1) << endl; }
Example • Rewrite the while loop of main of primes.cpp using for k = low; while (k <= high) { if (IsPrime(k)) { cout << k << endl; numPrimes += 1; } k += 1; } for (k = low; k <= high; k += 1) { if (IsPrime(k)) { cout << k << endl; numPrimes += 1; } }
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 • preincrement • 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 postdecrement (and predecrement) num = num - 1; num -= 1; num--;
The do-while loop • Similar to while loop, but the test is after the execution of the loop body • The while loop may never execute, do-while loop executes at least once do { loop body; } while (test ); //executes loop while the test is true • 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 << "enternumber in range [0..100] "; cin >> num; } while (num < 0 || num > 100 );
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 • I don’t like this kind of loops (I’d prefer code duplication). • I do NOT recommend to use break to break the 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 • The 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; Noproblem, but code duplicates • Think of other solutions! (see page 175 of Tapestry)
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 one line of stars { cout << "*"; } cout << endl; // end of line marker 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 6 , the output should look like * ** *** **** ***** ****** for (i=1; i<= side; i++) { for (j=1; j<=i; j++) // inner loop prints one line of stars { cout << "*"; } cout << endl; // end of line marker is put to the end of each line } • See drawfigures.cpp for the complete function and its use in main
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 marker 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 • Sometimes very useful • provide self documentation and 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
Example using robot class (see rectangularscan.cpp) • Write a program in which the robot starts at 0,0 and searches a rectangular space that covers n*n cells • n is input (in the example below, n is 8) • during this journey the robot should pick or put things on the cells so that all visited cells occupy one thing