cs 240: data structures thursday, may 31 st intro to c++, assignments, etc

25
CS 240: Data CS 240: Data Structures Structures Thursday, May 31 Thursday, May 31 st st Intro to C++, Intro to C++, Assignments, etc Assignments, etc

Post on 22-Dec-2015

215 views

Category:

Documents


0 download

TRANSCRIPT

CS 240: Data StructuresCS 240: Data Structures

Thursday, May 31Thursday, May 31stst

Intro to C++, Assignments, etcIntro to C++, Assignments, etc

From the HomeworkFrom the Homework

1) Look at example p.3 on Page 12. What is wrong 1) Look at example p.3 on Page 12. What is wrong with this example?with this example?

Short-circuit evaluation prevents a divide-by-Short-circuit evaluation prevents a divide-by-zero from occurring.zero from occurring.

What I was looking for was the lack of What I was looking for was the lack of parentheses.parentheses. (num != 0 && sum / num) may work in C++, but order (num != 0 && sum / num) may work in C++, but order

of operations may vary in other languages.of operations may vary in other languages. ((num != 0) && (sum / num)) is a better answer as it is ((num != 0) && (sum / num)) is a better answer as it is

portable across languages.portable across languages.

2) Read "Selection and Repetition Control" on Page 12. Short-2) Read "Selection and Repetition Control" on Page 12. Short-circuit evaluation has the benefit of saving computation time; circuit evaluation has the benefit of saving computation time; however, it can cause problems to not be found. How can however, it can cause problems to not be found. How can short-circuit evaluation make testing our code harder?short-circuit evaluation make testing our code harder?

Short-circuit evaluation allows us to skip the evaluation Short-circuit evaluation allows us to skip the evaluation of some parts of a test.of some parts of a test.

From example p.3:From example p.3: ((num != 0) && (sum / num))((num != 0) && (sum / num))

When num is 0, we don’t evaluate sum / 0.When num is 0, we don’t evaluate sum / 0. If a problem exists with the value in sum (but num is 0, If a problem exists with the value in sum (but num is 0,

we won’t notice it).we won’t notice it).

3) Look at Example P.5 on page 15. If the computer 3) Look at Example P.5 on page 15. If the computer gets to the 3gets to the 3rdrd "else" statement, what are the possible "else" statement, what are the possible values for operator?values for operator?

We don’t actually know that operator is a “char”, We don’t actually know that operator is a “char”, but we’ll assume it is.but we’ll assume it is.

operator can be anything other than +, - or *operator can be anything other than +, - or * When using nested ifs, it is important to know When using nested ifs, it is important to know

what how the if statements interact. We will go what how the if statements interact. We will go over this in more detail as part of coding style.over this in more detail as part of coding style.

4) Why are objects destroyed when they leave scope?4) Why are objects destroyed when they leave scope?

Once something is out of scope, we can no Once something is out of scope, we can no longer use it (technically, not true – an example longer use it (technically, not true – an example is deleting files).is deleting files).

If we don’t destroy the object then we can’t If we don’t destroy the object then we can’t reclaim the resources it uses.reclaim the resources it uses.

In C++, dynamic objects are not destroyed when In C++, dynamic objects are not destroyed when we leave scope. This requires the programmer we leave scope. This requires the programmer to handle it.to handle it.

5) What is wrong with Example P.10 on page 33? 5) What is wrong with Example P.10 on page 33? Hint: It means the programmer was lazy.Hint: It means the programmer was lazy.

Declaring the array:Declaring the array: string names[] = {…..}string names[] = {…..}

string names[] allows you to not declare how string names[] allows you to not declare how large the array is. But, it means that you don’t large the array is. But, it means that you don’t know how big the array is unless you count it.know how big the array is unless you count it.

Instead, use:Instead, use: string names[4] = {…}string names[4] = {…}

CompilationCompilation

Remember our Hello.cpp file?Remember our Hello.cpp file?Let’s relate it to Figure P.1 (page 4)Let’s relate it to Figure P.1 (page 4)

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

int main()int main(){{

cout << “Hello!” <<endl;cout << “Hello!” <<endl;return 0;return 0;

}}

Hello.o Hello.exe

We don’t have any in this fileBut, an example would be:#include”myfile.h”

Machine Code:add r1, r2, r3mov r3, r4, r1…

CompilationCompilation

To compile code:To compile code:g++ -c file.cppg++ -c file.cpp

To link code:To link code:g++ file1.o file2.o ….. –o file.exeg++ file1.o file2.o ….. –o file.exe

We will cover makefiles in a later class.We will cover makefiles in a later class.

CodingCoding

For our code we will For our code we will start using multiple start using multiple files to organize our files to organize our code.code.

This example will have This example will have some basic math some basic math functions.functions.

Remember, filenames Remember, filenames are case sensitive on are case sensitive on linux. This may be a linux. This may be a problem if you move problem if you move files from one machine files from one machine to another.to another.

mathexample.cppmathexample.cpp

#include<iostream>#include<iostream>#include”mathstuff.h”#include”mathstuff.h”

using namespace std;using namespace std;

int main()int main(){{

int first_num,second_num;int first_num,second_num;cout << “Enter first number: “ <<endl;cout << “Enter first number: “ <<endl;cin >> first_num;cin >> first_num;cout << “Enter second number: “ <<endl;cout << “Enter second number: “ <<endl;cin >> second_num;cin >> second_num;cout << mysum(first_num,second_num) <<endl;cout << mysum(first_num,second_num) <<endl;cout << mydiff(first_num,second_num) << endl;cout << mydiff(first_num,second_num) << endl;cout << myproduct(first_num,second_num) <<endl;cout << myproduct(first_num,second_num) <<endl;return 0;return 0;

}}

mathstuff.hmathstuff.h

#ifndef MATHSTUFF_H#ifndef MATHSTUFF_H

#define MATHSTUFF_H#define MATHSTUFF_H

//Basic math functions//Basic math functions

//Sum, difference and product of two numbers//Sum, difference and product of two numbers

int mysum(int first,int second);int mysum(int first,int second);

int mydiff(int first,int second);int mydiff(int first,int second);

int myproduct(int first,int second);int myproduct(int first,int second);

#endif#endif

mathstuff.cppmathstuff.cpp

int mysum(int first, int second)int mysum(int first, int second){{

return (first+second);return (first+second);}}

int mydiff(int first, int second)int mydiff(int first, int second){{

return (first-second);return (first-second);}}

int myproduct(int first, int second)int myproduct(int first, int second){{

return (first*second);return (first*second);}}

To compileTo compile

g++ -c mathstuff.cppg++ -c mathstuff.cpp g++ -c mathexample.cppg++ -c mathexample.cpp g++ mathstuff.o mathexample.o –o math.exeg++ mathstuff.o mathexample.o –o math.exeTo run:To run: ./math.exe./math.exe

Why so many files?Why so many files?

Other than for organization….Other than for organization….

Multiple files makes it easier to use your Multiple files makes it easier to use your code with a tester.code with a tester.

Remember, you can only have 1 main() in Remember, you can only have 1 main() in your code.your code.To test code, you want to be able to directly To test code, you want to be able to directly

access the relevant code.access the relevant code.

A sample tester:A sample tester:#include<iostream>#include<iostream>#include"mathstuff.h"#include"mathstuff.h"using namespace std;using namespace std;

int main()int main(){{ for(int i=0;i<1000;i++)for(int i=0;i<1000;i++) {{ int firstval=i;int firstval=i; int secondval=i*i;int secondval=i*i; if((firstval+secondval)!=(mysum(firstval,secondval)))if((firstval+secondval)!=(mysum(firstval,secondval))) {{ cout << "Failed addition case: " << firstval << ", " << secondval <<endl;cout << "Failed addition case: " << firstval << ", " << secondval <<endl; return 1;return 1; }} if((firstval-secondval)!=(mydiff(firstval,secondval)))if((firstval-secondval)!=(mydiff(firstval,secondval))) {{ cout << "Failed subtraction case: " << firstval << ", " << secondval <<endl;cout << "Failed subtraction case: " << firstval << ", " << secondval <<endl; return 1;return 1; }} if((firstval*secondval)!=(myproduct(firstval,secondval)))if((firstval*secondval)!=(myproduct(firstval,secondval))) {{ cout << "Failed multiplication case: " << firstval << ", " << secondval <<endl;cout << "Failed multiplication case: " << firstval << ", " << secondval <<endl; return 1;return 1; }} }} cout << "Tests of mysum(i,i^2), mydiff(i,i^2) and myproduct(i,i^2) for i = [0,1000) is completed successfully." << endl;cout << "Tests of mysum(i,i^2), mydiff(i,i^2) and myproduct(i,i^2) for i = [0,1000) is completed successfully." << endl; return 0;return 0;}}

The tester has its own main(), never needs The tester has its own main(), never needs to look at your main() and tests the to look at your main() and tests the functions directly.functions directly.

The more we decompose effectively The more we decompose effectively (effectively is a bit hard to qualify) the (effectively is a bit hard to qualify) the easier it is to test our code.easier it is to test our code.

Testing with assertTesting with assert

Assertion testing is commonly used to test Assertion testing is commonly used to test for sanity.for sanity.

If we had a variable called mysize:If we had a variable called mysize:mysize (because of its name) represents the mysize (because of its name) represents the

size of something.size of something.Therefore:Therefore:

if(mysize<0)if(mysize<0)

{{

cout << “Sanity failed, mysize is negative!” <<endl;cout << “Sanity failed, mysize is negative!” <<endl;

return 1;return 1;

}}

Therefore, whenever you change mysize you should Therefore, whenever you change mysize you should make sure it didn’t become negative. If it became make sure it didn’t become negative. If it became negative, something is wrong!negative, something is wrong!

#include<iostream>#include<iostream>

#include<cassert>#include<cassert>

using namespace std;using namespace std;

int main()int main()

{{

int mysize = 5;int mysize = 5;

Adjustsize(mysize,4);Adjustsize(mysize,4);

Adjustsize(mysize,-8);Adjustsize(mysize,-8);

Adjustsize(mysize,-4);Adjustsize(mysize,-4);

}}

Adjustsize modifies Adjustsize modifies mysize.mysize.

In this example, not In this example, not much happens. In a much happens. In a more complex more complex example we could be example we could be removing items from removing items from a list or container, etc.a list or container, etc.

#include<iostream>#include<iostream>

#include<cassert>#include<cassert>

using namespace std;using namespace std;

int main()int main()

{{

int mysize = 5;int mysize = 5;

Adjustsize(mysize,4);Adjustsize(mysize,4);

Adjustsize(mysize,-8);Adjustsize(mysize,-8);

Adjustsize(mysize,-4);Adjustsize(mysize,-4);

}}

mysize = 5

Add 4 itemsmysize = 9

Remove 8 itemsmysize = 1

Remove 4 itemsmysize = ?

If mysize is –3, we have a problem. A valid Adjustsize would either: 1) remove no items (not enough items, abort)

2) remove 1 item (removed all remaining)

#include<iostream>#include<iostream>

#include<cassert>#include<cassert>

using namespace std;using namespace std;

int main()int main()

{{

int mysize = 5;int mysize = 5;

Adjustsize(mysize,4);Adjustsize(mysize,4);

Adjustsize(mysize,-8);Adjustsize(mysize,-8);

Adjustsize(mysize,-4);Adjustsize(mysize,-4);

}}

We don’t know if Adjustsize works correctly so we add asserts to verify.

#include<iostream>#include<iostream>

#include<cassert>#include<cassert>

using namespace std;using namespace std;

int main()int main()

{{

int mysize = 5;int mysize = 5;

Adjustsize(mysize,4);Adjustsize(mysize,4);

assert(mysize>=0);assert(mysize>=0);

Adjustsize(mysize,-8);Adjustsize(mysize,-8);

assert(mysize>=0);assert(mysize>=0);

Adjustsize(mysize,-4);Adjustsize(mysize,-4);

assert(mysize>=0);assert(mysize>=0);

}}

That may be a bit excessive.That may be a bit excessive.Since we are worried about mysize Since we are worried about mysize

becoming negative. We really only need becoming negative. We really only need those asserts after a remove.those asserts after a remove.However:However:

mysize could become negative due to overflowmysize could become negative due to overflowmysize might become larger than we can handlemysize might become larger than we can handle

This should be handled separately.This should be handled separately.

User inputUser input

The only input we’ve The only input we’ve shown so far is taking shown so far is taking in ints.in ints.

We will take in non-int We will take in non-int user input using the user input using the string class.string class.

Later, once we’ve Later, once we’ve covered streams we covered streams we will explain c_strings.will explain c_strings.

#include<iostream>#include<iostream>#include<string>#include<string>

using namespace std;using namespace std;

int main()int main(){{

string userinput;string userinput;cout << “Input stuff and then press enter!” cout << “Input stuff and then press enter!” <<endl;<<endl;cin >> userinput;cin >> userinput;cout << “You entered: “ << userinput <<endl;cout << “You entered: “ << userinput <<endl;return 0;return 0;

}}

Some basic string methodsSome basic string methods

Now that we have the Now that we have the string how do we use string how do we use it?it?

The methods are The methods are similar to that of Java similar to that of Java and C.and C.

Once we have the Once we have the variable “userinput” variable “userinput” we can access it as we can access it as follows:follows:

““userinput[n]” is the nth userinput[n]” is the nth character of the string.character of the string.

““userinput.length()” is the userinput.length()” is the size of the inputsize of the input

““userinput.c_str()” is a userinput.c_str()” is a cstring of the input – you cstring of the input – you will need this to use strings will need this to use strings with various functions.with various functions.

We will go over other We will go over other functions later. I just want functions later. I just want you to have the basic you to have the basic understanding of a string understanding of a string at this point.at this point.

#include<iostream>#include<iostream>#include<string>#include<string>

using namespace std;using namespace std;

int main()int main(){{ string input;string input; cout << "Enter some text (one word): " <<endl;cout << "Enter some text (one word): " <<endl; cin >> input;cin >> input; cout << "You entered: " << input <<endl;cout << "You entered: " << input <<endl; cout << "There are " << input.length() << " letters" << endl;cout << "There are " << input.length() << " letters" << endl; for(int i=0;i<input.length();i++)for(int i=0;i<input.length();i++) {{ cout << "Character number: " << i+1 << " is " << input[i] << " and " << input.at(i) << endl;cout << "Character number: " << i+1 << " is " << input[i] << " and " << input.at(i) << endl; }}

char * mycstring;char * mycstring; mycstring = new char[input.length()];mycstring = new char[input.length()]; for(int i=0;i<input.length();i++)for(int i=0;i<input.length();i++) {{ mycstring[i] = input[i];mycstring[i] = input[i]; }} mycstring[input.length()] = '\0';mycstring[input.length()] = '\0'; cout << mycstring << endl;cout << mycstring << endl; delete mycstring;delete mycstring; return 0;return 0;}}

Logical operations:Logical operations:Short circuit evaluationShort circuit evaluationbitand (&) - and (&&)bitand (&) - and (&&)bitor (|) – or(||)bitor (|) – or(||)