View
218
Download
2
Embed Size (px)
Citation preview
CS 240: Data StructuresCS 240: Data Structures
Tuesday, June 19Tuesday, June 19thth
ADT Requirements (Card), I/OADT Requirements (Card), I/O
TerminologyTerminology
Here is some stuff to memorize:Here is some stuff to memorize: ““Container Class”Container Class”
mycontainer is a type of “Container Class”mycontainer is a type of “Container Class” ““Sequential Container”Sequential Container”
An array is a sequential container so is An array is a sequential container so is mycontainer.mycontainer.
““Coercion” and “Casting”Coercion” and “Casting”
Some MaterialSome Material
This is a list of some material which I can cover This is a list of some material which I can cover if you want but already expect you all to know as if you want but already expect you all to know as part of the background courses.part of the background courses.
Binary representationBinary representation Also, real values (you do not need to translate, just Also, real values (you do not need to translate, just
understand that the binary is an abstraction)understand that the binary is an abstraction)
LogicLogic And, or, xor, nor, etcAnd, or, xor, nor, etc I may draw gates, but I’ll give you a keyI may draw gates, but I’ll give you a key
ADTsADTs
An ADT is a collection of data that An ADT is a collection of data that represents some sort of abstraction.represents some sort of abstraction.
A person is represented by:A person is represented by:Name, age, height, etcName, age, height, etc
A book “can” be represented by:A book “can” be represented by:Title, ISBN, author, yearTitle, ISBN, author, year
ADTsADTs
However, an ADT isn’t too useful if it just However, an ADT isn’t too useful if it just stores data and nothing else.stores data and nothing else.
All this would do is allow you to organize All this would do is allow you to organize data better:data better:
Book ADTBook ADT
#ifndef BOOK_H#ifndef BOOK_H#define BOOK_H#define BOOK_H
class Bookclass Book{{
public:public:string title;string title;string ISBN;string ISBN;string author;string author;int year;int year;
};};
#endif#endif
This just stores data.This just stores data. A “storage only” ADT can A “storage only” ADT can
have public have public variables/members.variables/members.
A “storage only” ADT has A “storage only” ADT has no associated functions; no associated functions; therefore, it has no cpp therefore, it has no cpp file.file.
(Optional): In C, this (Optional): In C, this instead be a “struct”instead be a “struct”
Book ADTBook ADT
#ifndef BOOK_H#ifndef BOOK_H
#define BOOK_H#define BOOK_H
class Bookclass Book
{{
public:public:
string title;string title;
string ISBN;string ISBN;
string author;string author;
int year;int year;
};};
#endif#endif
#include<iostream>#include<iostream>#include”Book.h”#include”Book.h”
using namespace std;using namespace std;
int main()int main(){{
Book mylibrary[10];Book mylibrary[10];string intitle,inISBN,inauthor;string intitle,inISBN,inauthor;int inyear;int inyear;for(int i=0;i<10;i++)for(int i=0;i<10;i++){{
cin >> intitle >> inISBN;cin >> intitle >> inISBN;cin >> inauthor >> inyear;cin >> inauthor >> inyear;mylibrary[i].title=intitle;mylibrary[i].title=intitle;mylibrary[i].ISBN=inISBN;mylibrary[i].ISBN=inISBN;mylibrary[i].author=inauthor;mylibrary[i].author=inauthor;mylibrary[i].year=inyear;mylibrary[i].year=inyear;
}}cout << mylibrary[0].title <<endl;cout << mylibrary[0].title <<endl;cout << mylibrary[0].ISBN <<endl;cout << mylibrary[0].ISBN <<endl;
}}
Book ADTBook ADT
Manipulating this book can become Manipulating this book can become annoying.annoying.
Therefore, we turn it into a Data Structure Therefore, we turn it into a Data Structure by associating functions with it.by associating functions with it.
Book ADTBook ADT
How can we simplify How can we simplify the input loop?the input loop?
It would be annoying It would be annoying if every time we if every time we wanted to use the wanted to use the Book class we would Book class we would have to copy that have to copy that entire set of entire set of assignment assignment instructions.instructions.
There are two There are two approaches to this:approaches to this:
1) Create an input 1) Create an input function (low-level)function (low-level)
2) Overload input to 2) Overload input to allow direct access allow direct access (high-level)(high-level)
#ifndef BOOK_H#ifndef BOOK_H
#define BOOK_H#define BOOK_H
#include<iostream>#include<iostream>
using namespace std;using namespace std;
class Bookclass Book
{{
public:public:
void input(istream & in);void input(istream & in);
void display(ostream & out);void display(ostream & out);
privateprivate::
string title;string title;
string ISBN;string ISBN;
string author;string author;
int year;int year;
};};
istream & operator >>(istream & in, Book istream & operator >>(istream & in, Book & target);& target);
ostream & operator <<(ostream & out, ostream & operator <<(ostream & out, Book & target);Book & target);
#endif#endif
void Book::input(istream & in)void Book::input(istream & in)
{{
in >> title;in >> title;
in >> ISBN;in >> ISBN;
in >> author;in >> author;
in >> year;in >> year;
}}
void Book::display(ostream & out)void Book::display(ostream & out)
{{
out << title << “ “ << ISBN << “ “;out << title << “ “ << ISBN << “ “;
out << author << “ “ << year <<endl;out << author << “ “ << year <<endl;
}}
istream?istream stands for “input stream”
We can tell the function what input stream to use:cin, or some other stream.
The syntax of operator >> requires memorization.
#ifndef BOOK_H#ifndef BOOK_H
#define BOOK_H#define BOOK_H
#include<iostream>#include<iostream>
using namespace std;using namespace std;
class Bookclass Book
{{
public:public:
void input(istream & in);void input(istream & in);
void display(ostream & out);void display(ostream & out);
privateprivate::
string title;string title;
string ISBN;string ISBN;
string author;string author;
int year;int year;
};};
istream & operator >>(istream & in, Book istream & operator >>(istream & in, Book & target);& target);
ostream & operator <<(ostream & out, ostream & operator <<(ostream & out, Book & target);Book & target);
#endif#endif
istream & operator >>(istream &in, Book & target)istream & operator >>(istream &in, Book & target){{
target.input(in);target.input(in);return in;return in;
}}
ostream & operator <<(ostream & out, Book & ostream & operator <<(ostream & out, Book & target)target)
{{target.display(out);target.display(out);return out;return out;
}}
Really, we should also be able to return a string but Really, we should also be able to return a string but we won’t worry about that for this example.we won’t worry about that for this example.
Now we can update our code:Now we can update our code: Instead of:Instead of:#include<iostream>#include<iostream>#include”Book.h”#include”Book.h”
using namespace std;using namespace std;
int main()int main(){{
Book mylibrary[10];Book mylibrary[10];string intitle,inISBN,inauthor;string intitle,inISBN,inauthor;int inyear;int inyear;for(int i=0;i<10;i++)for(int i=0;i<10;i++){{
cin >> intitle >> inISBN;cin >> intitle >> inISBN;cin >> inauthor >> inyear;cin >> inauthor >> inyear;mylibrary[i].title=intitle;mylibrary[i].title=intitle;mylibrary[i].ISBN=inISBN;mylibrary[i].ISBN=inISBN;mylibrary[i].author=inauthor;mylibrary[i].author=inauthor;mylibrary[i].year=inyear;mylibrary[i].year=inyear;
}}cout << mylibrary[0].title <<endl;cout << mylibrary[0].title <<endl;cout << mylibrary[0].ISBN <<endl;cout << mylibrary[0].ISBN <<endl;
}}
Now:Now:#include<iostream>#include<iostream>#include”Book.h”#include”Book.h”
using namespace std;using namespace std;
int main()int main(){{
Book mylibrary[10];Book mylibrary[10];string intitle,inISBN,inauthor;string intitle,inISBN,inauthor;int inyear;int inyear;for(int i=0;i<10;i++)for(int i=0;i<10;i++){{
cin >> mylibrary[i];cin >> mylibrary[i];}}for(int i=0;i<10;i++)for(int i=0;i<10;i++){{
cout << mylibrary[i];cout << mylibrary[i];}}return 0;return 0;
}}
Or:Or:#include<iostream>#include<iostream>#include”Book.h”#include”Book.h”
using namespace std;using namespace std;
int main()int main(){{
Book mylibrary[10];Book mylibrary[10];string intitle,inISBN,inauthor;string intitle,inISBN,inauthor;int inyear;int inyear;for(int i=0;i<10;i++)for(int i=0;i<10;i++){{
mylibrary[i].input(cin);mylibrary[i].input(cin);}}for(int i=0;i<10;i++)for(int i=0;i<10;i++){{
mylibrary[i].display(cout);mylibrary[i].display(cout);}}return 0;return 0;
}}
RationaleRationale
Why do we do the second method?Why do we do the second method?Well, it allows us to see more readily what Well, it allows us to see more readily what
is going on.is going on.We call the input method with cin. We call the input method with cin. We call the display method with cout.We call the display method with cout.Alternatively, we can give these functions Alternatively, we can give these functions
other streams.other streams.
I/O StreamsI/O Streams
The streams we have been exposed to so The streams we have been exposed to so far:far:
cin and coutcin and coutHowever, there are other streams we can However, there are other streams we can
use:use: ifstream and ofstreamifstream and ofstream
These are for file input and file outputThese are for file input and file output
File I/O ExampleFile I/O Example
ifstream myfile;ifstream myfile;
string toopen = “filename.txt”;string toopen = “filename.txt”;
myfile.open(toopen.c_str(),ios::in);myfile.open(toopen.c_str(),ios::in);
string input;string input;
myfile >> input;myfile >> input;
myfile.close();myfile.close();
File I/O ExampleFile I/O Example
ofstream myfile;ofstream myfile;
string toopen = “filename.txt”;string toopen = “filename.txt”;
myfile.open(toopen.c_str(),ios::out);myfile.open(toopen.c_str(),ios::out);
string output = “I’m writing data”;string output = “I’m writing data”;
myfile << output;myfile << output;
myfile.close();myfile.close();
Card ADTCard ADT Let us come up with a specification for a playing Let us come up with a specification for a playing
card. Then we can code it:card. Then we can code it: We need to come up with the important We need to come up with the important
abstractions that relate to a playing card.abstractions that relate to a playing card. We also need to take into consideration how the We also need to take into consideration how the
Card is managed in memory.Card is managed in memory. We will also examine the three required methods We will also examine the three required methods
of most ADTsof most ADTs Copy constructor, assignment operator and destructorCopy constructor, assignment operator and destructor
Also, what would a container class of Card Also, what would a container class of Card require?require?
What is a primitive?What is a primitive?
A primitive is a built-in data type.A primitive is a built-in data type.Generally, it has complete functionality.Generally, it has complete functionality.They have a value and are located in They have a value and are located in
memory.memory.During compilation, they have a name.During compilation, they have a name.
Only a memory address is used while running.Only a memory address is used while running.
Primitive Type: int
Value (32 bits): ?
Address: ?
Primitive Type: char
Value (8 bits): ?
Address: ?
Data ManipulationData Manipulation
Therefore, we use the address of the data to Therefore, we use the address of the data to locate the value we want.locate the value we want.
How about an array of ints?How about an array of ints? Ok, so if we know where the array starts we can Ok, so if we know where the array starts we can
find successive data.find successive data.
Address:Address: i i i+4i+4 i+8i+8 i+12i+12 i+16i+16 i+20i+20 i+24i+24
Value:Value: 1010 2020 3030 1010 5050 1010 00
Data ManipulationData Manipulation An array is a form of a data abstraction.An array is a form of a data abstraction.
class arrayclass array{{
T value;T value;memory_address next_data;memory_address next_data;memory_address own_location;memory_address own_location;
};};
Where next_data is always equal to the size of T.Where next_data is always equal to the size of T.This is done automatically when we use array implementation (this This is done automatically when we use array implementation (this
abstraction only works in theory since the next_location would be abstraction only works in theory since the next_location would be offset by the other class members).offset by the other class members).
If you created an array of this time (and set next_data to size of array If you created an array of this time (and set next_data to size of array instead of T), it would mirror the real implementation.instead of T), it would mirror the real implementation.
Data ManipulationData Manipulation
These abstractions allow us to group data These abstractions allow us to group data together so that we access data we can together so that we access data we can get more than 1 piece of information.get more than 1 piece of information.
Primitive Type: int
Value (32 bits): ?
Address: ?
Address: ?
ADT: array (int)
96 bits(32 bits) -> int(32 bits) -> 12
(32 bits) -> *this
array testdata[3];array testdata[3];
ADT: array (int)
96 bits(32 bits) -> int (5)
(32 bits) -> 12(32 bits) -> *this (X)
Address: X
ADT: array (int)
96 bits(32 bits) -> int (10)
(32 bits) -> 12(32 bits) -> *this (X+12)
Address: X + 12
ADT: array (int)
96 bits(32 bits) -> int (15)
(32 bits) -> 12(32 bits) -> *this (X+24)
Address: X + 24
This actually requires array to have a constructor to set:next_data = sizeof(array);own_location = *this;
Therefore:&testdata[0] = &testdata[0].own_location;&testdata[1] = &testdata[1].own_location;
and &testdata[1] = &testdata[0].own_location + testdata[0].next_data;This is a representation of how it is actually done in memory.
Data ManipulationData Manipulation
You wouldn’t implement an array like we You wouldn’t implement an array like we did in the last slide. However, we using it did in the last slide. However, we using it slightly differently we can achieve a slightly differently we can achieve a differently goal.differently goal.
array testdata[3];array testdata[3];
ADT: array (int)
96 bits(32 bits) -> int (5)
(32 bits) -> 24(32 bits) -> *this (X)
Address: X
ADT: array (int)
96 bits(32 bits) -> int (10)
(32 bits) -> 12(32 bits) -> *this (X+12)
Address: X + 12
ADT: array (int)
96 bits(32 bits) -> int (15)
(32 bits) -> -12(32 bits) -> *this (X+24)
Address: X + 24
If we use [ ], we will get all the data in the same order as before:5 10 15
However, if we use next_data:5 15 10
We now have a new representation – an array-based linked list
We don’t need an array…We don’t need an array…
ADT: array (int)
96 bits(32 bits) -> int (5)
(32 bits) -> Z-X(32 bits) -> *this (X)
Address: X
ADT: array (int)
96 bits(32 bits) -> int (10)
(32 bits) -> -Y(32 bits) -> *this (Y)
Address: Y
ADT: array (int)
96 bits(32 bits) -> int (15)
(32 bits) -> Y-Z(32 bits) -> *this (Z)
Address: Z
In our assignments we won’t use “our_location”We always know where the first item is and can find the remaining items by using next_item.
Without our_locationWithout our_location
ADT: array (int)
96 bits(32 bits) -> int (5)
(32 bits) -> Z
Address: X
ADT: array (int)
96 bits(32 bits) -> int (10)
(32 bits) -> 0
Address: Y
ADT: array (int)
96 bits(32 bits) -> int (15)
(32 bits) -> Y
Address: Z
If our first item is at address X then, (5)we find the second item by using next_item (15)and the third item by using next_item of the second (10)and since third_item.next_item == 0, we are done.