320 likes | 335 Views
CS 240: Data Structures. Monday, June 9 th Programming Semantics, Software Life Cycle, Memory Allocation. double *shorty; double jimmy; jimmy = 10; shorty = &jimmy; cout << shorty << endl;. What does this code output? What does: “cout << *shorty <<endl;” output?. Pointers and reference.
E N D
CS 240: Data Structures Monday, June 9th Programming Semantics, Software Life Cycle, Memory Allocation
double *shorty; double jimmy; jimmy = 10; shorty = &jimmy; cout << shorty << endl; What does this code output? What does: “cout << *shorty <<endl;” output? Pointers and reference
double *shorty; double jimmy; jimmy = 10; shorty = &jimmy; cout << shorty << endl; cout << *shorty << endl; Pointers and reference Name: shorty Value: Uninitialized Location: Topmost! Name: shorty Value: The Bottom Location: Topmost! Output: The Bottom Output: 10 Name: jimmy Value: 10 Location: The Bottom Name: jimmy Value: Uninitialized Location: The bottom
More on pointers • Pointers allow us to give data to functions • They also allow us to obtain additional memory resources while a program is running.
Queries • We’ve covered various things at this point. • What topics are giving you trouble? • What topics did you think we would have covered by now have not been covered?
Decomposition • When you create a decomposition (and particularly when you create a specification) it should be readable to the point that if someone else was looking at it they could code it.
blackjack.cpp Contains our main() Contains: #include”card.h” #include”deck.h” #include”player.h” #include”game.h” The following files organize our code: Card -> card.h and card.cpp Deck -> deck.h and deck.cpp Player -> player.h and player.cpp Game -> game.h and game.cpp File Layout Example
Value model: A copy of the data is given. This is like burning a copy of a CD to give to a friend because they don’t have clean hands. This is the model that Java uses. int myfunction(int first, int last, double appliedvalue, float secondvalue); Passing data:
Passing data: • Reference model: • This model allows us to share/give data to a function.
#include<iostream> #include”swap.h” using namespace std; int main() { int number = 5; int secondnum = 10; swap_t swapper; swapper.swap(number,secondnum); cout << number << endl; cout << secondnum << endl; return 0; } Output: 10 5 Reference passing
swap.h #ifndef SWAP_H #define SWAP_H //Swaps the values pointed to by the parameters. //input: two int references //output: none //side effects: the values pointed to by the two parameters are swapped. class swap_t { public: void swap(int &a, int &b); }; #endif swap.cpp #ifndef SWAP_CPP #define SWAP_CPP #include”swap.h” void swap_t::swap(int &a, int &b) { int temp = a; a = b; b = temp; } #endif Reference passing
Using arrays • Arrays are a representation of multiple data of the same type: • Either: int numbers[1000]; or • int number1,number2,number3….. • An array is not just a cleaner scheme but much more modifiable. • Also, easier to access (try setting each of the numbers to 15).
Arrays • An array is implicitly a pointer (a static pointer). • Because it is static, we do not use it as we do with pointers. • Generally, we use dynamic arrays which are created differently.
Dynamic Arrays #include<iostream> using namespace std; int main() { int *numbers; int userinput; cin >> userinput; numbers = new int[userinput]; cout << “Array created of size: “ << userinput <<endl; delete [] numbers; //[] is [ ] without the space }
Dynamic Arrays • If the array the user asked for isn’t large enough? • Lets say the user inputs: 10 • And we change the code to take in int inputs until the user inputs -1.
Dynamic Arrays #include<iostream> using namespace std; int main() { int *numbers; int userinput; cin >> userinput; numbers = new int[userinput]; cout << “Array created of size: “ << userinput <<endl; int location = 0; userinput = 0; while(userinput != -1) { cin >> userinput; numbers[location] = userinput; location++; } delete [] numbers; }
Dynamic Arrays • When the user inputs the 11th value, it uses memory that isn’t ours. • It may not cause an error right away. • In fact, on larger programs, we might just overwrite our own data for awhile. • Dynamic arrays allows us to resize the array if we need to.
#include<iostream> using namespace std; int main() { int *numbers; int userinput; cin >> userinput; numbers = new int[userinput]; cout << “Array created of size: “ << userinput <<endl; int location = 0; int maxsize = userinput; userinput = 0; while(userinput != -1) { cin >> userinput; numbers[location] = userinput; location++; if(location>=maxsize) { ….. } } delete [] numbers; } int *temp = new int[maxsize*2]; for(int i=0;i<maxsize;i++) { temp[i]=numbers[i]; } maxsize *= 2; delete [] numbers; numbers = temp;
Abstract Data Types • An abstract data type (ADT) is a collection of data. • It provides a representation for some more abstract object. class computer { string name,processor_type,brand,video_card; int processor_speed,ram_speed,ram_amount; …. };
ADTs • This allows you to use the ADT instead of defining each field in your code
ADTs #include<iostream> #include”computer.h” using namespace std; int main() { computer mycomputer; mycomputer.ram_amount = 1024; computer *mycomputer_ptr = new computer; mycomputer_ptr->ram_amount = 1024; cout << mycomputer << endl; //This doesn’t work! return 0; }
ADTs • You could print out each field/value/variable within computer. • However, that would be excessive. • Also, what if you want to change what you decided to print? You’d have to change it in every location. • computer can be given functions/methods that generate a printable output.
ADTs - Output • Option 1: • Create a function that uses cout directly: • This is not preferred, it limits what can be done with the output. • Option 2: • Overload “<<“, that way we can use cout on computer. • This is easier to use, but still limits what can be done with the output. • Option 3: • Create a function that returns a string of what we want to output. • We will use options 2 and 3 in this class
computer.h #ifndef COMPUTER_H #define COMPUTER_H class computer { string name,processor_type,brand,video_card; int processor_speed,ram_speed,ram_amount; public: string getoutput(); }; #endif
computer.cpp #include”computer.h” string computer::getoutput() { string retval = “”; retval = “Computer: “ + name; return retval; }
Other ADT benefits • An ADT allows us to group data together. This way everything we want to manipulate is close together. • The variables/fields declared in the class prototype are “global” to all the class functions/methods.
ADT constraints • Generally, you don’t give a user access to your variables/fields. • They could mess things up, so, mutators and accessors are created. • Mutators mutate/change data. • Accessors access data. • ADTs may require constructors and destructors
int main() { computer mycomputer; mycomputer.set_ram_amount(1024); computer *mycomputer_ptr = new computer; mycomputer_ptr->set_ram_amount(1024); cout << mycomputer.getoutput() << endl; cout << mycomputer.get_ram_amount() <<endl; return 0; }
Constructors/Destructors • Constructors: • Allow you to provide initial values • These are needed for dynamic memory within an ADT • Destructors: • If you have any dynamic memory in the ADT, this is where you deallocate it.
computer.h #ifndef COMPUTER_H #define COMPUTER_H class computer { string name,processor_type,brand,video_card; int processor_speed,ram_speed,ram_amount; int *somedynamicmemory; public: string getoutput(); //provides output computer(); //constructor ~computer(); //destructor }; #endif
computer.cpp Alternative constructor (using initializer lists) computer::computer() : brand(“No name brand, inc.”), processor_speed(0) { somedynamicmemory = new int[100]; } #include”computer.h” string computer::getoutput() { string retval = “”; retval = “Computer: “ + name; return retval; } computer::computer() { somedynamicmemory = new int[100]; brand = “No name brand, inc.”; processor_speed = 0; } computer::~computer() { delete [] somedynamicmemory; }
Class Project • For project 1 we will implement a program to track cars on a race track.