240 likes | 255 Views
CS 240: Data Structures. Monday, June 1 st Intro to C++, Classes, etc. Compilation. Remember our Hello.cpp file? Let’s relate it to Figure P.1 (page 4). #include<iostream> using namespace std; int main() { cout << “Hello!” <<endl; return 0; }. Hello.o. Hello.exe. Machine Code:
E N D
CS 240: Data Structures Monday, June 1st Intro to C++, Classes, etc
Compilation • Remember our Hello.cpp file? • Let’s relate it to Figure P.1 (page 4)
#include<iostream> using namespace std; int main() { cout << “Hello!” <<endl; return 0; } Hello.o Hello.exe Machine Code: add r1, r2, r3 mov r3, r4, r1 … We don’t have any in this file But, an example would be: #include”myfile.h”
Compilation • To compile code: • g++ -c file.cpp • To link code: • g++ file1.o file2.o ….. –o file.exe • We will cover makefiles in a later class.
For our code we will start using multiple files to organize our code. This example will have some basic math functions. Remember, filenames are case sensitive on linux. This may be a problem if you move files from one machine to another. mathexample.cpp #include<iostream> #include”mathstuff.h” using namespace std; int main() { int first_num,second_num; cout << “Enter first number: “ <<endl; cin >> first_num; cout << “Enter second number: “ <<endl; cin >> second_num; cout << mysum(first_num,second_num) <<endl; cout << mydiff(first_num,second_num) << endl; cout << myproduct(first_num,second_num) <<endl; return 0; } Coding
mathstuff.h #ifndef MATHSTUFF_H #define MATHSTUFF_H //Basic math functions //Sum, difference and product of two numbers int mysum(int first,int second); int mydiff(int first,int second); int myproduct(int first,int second); #endif mathstuff.cpp int mysum(int first, int second) { return (first+second); } int mydiff(int first, int second) { return (first-second); } int myproduct(int first, int second) { return (first*second); }
To compile • g++ -c mathstuff.cpp • g++ -c mathexample.cpp • g++ mathstuff.o mathexample.o –o math.exe • To run: • ./math.exe
Why so many files? • Other than for organization…. • Multiple files makes it easier to use your code with a tester. • Remember, you can only have 1 main() in your code. • To test code, you want to be able to directly access the relevant code.
A sample tester: #include<iostream> #include"mathstuff.h" using namespace std; int main() { for(int i=0;i<1000;i++) { int firstval=i; int secondval=i*i; if((firstval+secondval)!=(mysum(firstval,secondval))) { cout << "Failed addition case: " << firstval << ", " << secondval <<endl; return 1; } if((firstval-secondval)!=(mydiff(firstval,secondval))) { cout << "Failed subtraction case: " << firstval << ", " << secondval <<endl; return 1; } if((firstval*secondval)!=(myproduct(firstval,secondval))) { cout << "Failed multiplication case: " << firstval << ", " << secondval <<endl; 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; return 0; }
This tester has its own main(), never needs to look at your main() and tests the functions directly. • The more we decompose effectively (effectively is a bit hard to qualify) the easier it is to test our code.
Testing • Output testing is an easy way (but may not be viable on some setups) to see what your program is doing as it is running.
Testing with assert • Assertion testing is commonly used to test for sanity. • If we had a variable called mysize: • mysize (because of its name) represents the size of something. • Therefore:
if(mysize<0) { cout << “Sanity failed, mysize is negative!” <<endl; return 1; //Alternatively, we could have defined an error value } • Therefore, whenever you change mysize you should make sure it didn’t become negative. If it became negative, something is wrong! • Ideally, we want to ensure (rather than check) that the value will always be correct.
#include<iostream> #include<cassert> using namespace std; int main() { int mysize = 5; Adjustsize(mysize,4); Adjustsize(mysize,-8); Adjustsize(mysize,-4); } Adjustsize modifies mysize. In this example, not much happens. In a more complex example we could be removing items from a list or container, etc.
#include<iostream> #include<cassert> using namespace std; int main() { int mysize = 5; Adjustsize(mysize,4); Adjustsize(mysize,-8); Adjustsize(mysize,-4); } mysize = 5 Add 4 items mysize = 9 Remove 8 items mysize = 1 Remove 4 items mysize = ? 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<cassert> using namespace std; int main() { int mysize = 5; Adjustsize(mysize,4); Adjustsize(mysize,-8); Adjustsize(mysize,-4); } We don’t know if Adjustsize works correctly so we add asserts to verify. #include<iostream> #include<cassert> using namespace std; int main() { int mysize = 5; Adjustsize(mysize,4); assert(mysize>=0); Adjustsize(mysize,-8); assert(mysize>=0); Adjustsize(mysize,-4); assert(mysize>=0); }
That may be a bit excessive. • Since we are worried about mysize becoming negative. We really only need those asserts after a remove. • However: • mysize could become negative due to overflow • mysize might become larger than we can handle • This should be handled separately.
Data • What is it? • Data has a value and a location. • Within our code, data also has a name (it won’t always, and the names aren’t preserved in the executable). • Manipulation of the location of data provides us many advantages but can be elusive – this is one of the most important concepts of this course!
We will take in non-int user input using the string class and c_strings. The string class makes the input handling very trivial compared to handling it with c_strings. #include<iostream> #include<string> using namespace std; int main() { string userinput; cout << “Input stuff and then press enter!” <<endl; cin >> userinput; cout << “You entered: “ << userinput <<endl; return 0; } User input
Now that we have the string how do we use it? The methods are similar to that of Java and C. Once we have the variable “userinput” we can access it as follows: “userinput[n]” is the nth character of the string. “userinput.length()” is the size of the input “userinput.c_str()” is a cstring of the input – you will need this to use strings with various functions. Some basic string methods
#include<iostream> #include<string> using namespace std; int main() { string input; cout << "Enter some text (one word): " <<endl; cin >> input; cout << "You entered: " << input <<endl; cout << "There are " << input.length() << " letters" << endl; for(int i=0;i<input.length();i++) { cout << "Character number: " << i+1 << " is " << input[i] << " and " << input.at(i) << endl; } char * mycstring; mycstring = new char[input.length()]; for(int i=0;i<input.length();i++) { mycstring[i] = input[i]; } mycstring[input.length()] = '\0'; cout << mycstring << endl; delete mycstring; return 0; }
Now, lets do this with a c_string (and use malloc/free instead of new/delete).
Programming Structure • To solve a programming problem: • Define the problem • Break it up into manageable parts • Split up the problem into smaller tasks • If a task can be immediately realized, it is small enough • Code the parts • Integrate parts together
Converting ideas to code: • Sometimes, the ideas are easy. • Getting the code down – or approaching the problem – becomes the challenge. • Most code revolves around the following statements: