WEBVTT 00:00:00.000 --> 00:00:11.000 00:00:11.000 --> 00:00:14.000 This presentation is delivered by the Stanford Center for Professional Development. 00:00:14.000 --> 00:00:24.000 00:00:24.000 --> 00:00:26.000 Any administration questions on your mind? 00:00:26.000 --> 00:00:28.000 How many people have actually successfully installed a compiler? 00:00:28.000 --> 00:00:31.000 Have stuff working - okay, so that's like a 00:00:31.000 --> 00:00:34.000 third of you, good to know. 00:00:34.000 --> 00:00:36.000 Remaining two thirds, you 00:00:36.000 --> 00:00:40.000 want to get on it. Okay, 00:00:40.000 --> 00:00:45.000 so we started to talk about this on Monday, and I'm gonna 00:00:45.000 --> 00:00:48.000 try to finish off the things that I had started to get you thinking about; 00:00:48.000 --> 00:00:52.000 about how input/output works in C++. We've seen the simple 00:00:52.000 --> 00:00:53.000 forms of 00:00:53.000 --> 00:00:57.000 using stream insertion, the less than less than operator to push things on to cout, 00:00:57.000 --> 00:00:59.000 the Console Output Stream. 00:00:59.000 --> 00:01:02.000 A C-Out is capable of writing all the 00:01:02.000 --> 00:01:06.000 basic types that are built into C++, ants and doubles and cars and strings, 00:01:06.000 --> 00:01:06.000 right, 00:01:06.000 --> 00:01:09.000 by virtue of just sort of putting the string on the left and the thing you want on 00:01:09.000 --> 00:01:10.000 the right, it will kind of 00:01:10.000 --> 00:01:14.000 take that thing and push it out onto stream. You can chain those 00:01:14.000 --> 00:01:17.000 together with lots and lots of those < < to get a whole bunch 00:01:17.000 --> 00:01:20.000 of things, and then the endl is the - what's called stream 00:01:20.000 --> 00:01:24.000 manipulator that produces a new line, starts the next line of text, a line 00:01:24.000 --> 00:01:25.000 beneath that. 00:01:25.000 --> 00:01:30.000 The analog to that on the reading side is the stream 00:01:30.000 --> 00:01:33.000 extraction operator, which is the > >. And then when applied 00:01:33.000 --> 00:01:36.000 to an input stream it attempts to sort of take where the cursor position is in 00:01:36.000 --> 00:01:42.000 the input stream and read the next characters using the expected format 00:01:42.000 --> 00:01:46.000 given by the type of the thing you're trying to extract. So in this case 00:01:46.000 --> 00:01:50.000 what I'm saying, CN > > extract an integer here, X being an integer. 00:01:50.000 --> 00:01:53.000 What it's gonna look for in the input stream is it's going to skip 00:01:53.000 --> 00:01:55.000 over white space. So by default 00:01:55.000 --> 00:01:58.000 the stream extraction always skips over any leading white space. That means tabs, 00:01:58.000 --> 00:01:59.000 new lines, 00:01:59.000 --> 00:02:02.000 and ordinary space characters. So 00:02:02.000 --> 00:02:05.000 scans up to that, gets to the first non-space character 00:02:05.000 --> 00:02:09.000 and then starts assuming that what should be there is a number, and so 00:02:09.000 --> 00:02:12.000 number being, a sequence of digit characters. And in this case, because it's 00:02:12.000 --> 00:02:16.000 integer, it shouldn't have a dot or any of the exponentiations sort of things that 00:02:16.000 --> 00:02:17.000 a real number 00:02:17.000 --> 00:02:20.000 would. If it runs into something that's not integer, it 00:02:20.000 --> 00:02:24.000 runs into a character, it runs into a punctuation, it runs into a 00:02:24.000 --> 00:02:26.000 39.5, 00:02:26.000 --> 00:02:29.000 what happens is that the screen goes into a fail state 00:02:29.000 --> 00:02:33.000 where it says, I - you told me to expect an integer. What I read next wasn't an 00:02:33.000 --> 00:02:33.000 integer. 00:02:33.000 --> 00:02:36.000 I don't know how to make heads or tails of this. So it basically just 00:02:36.000 --> 00:02:38.000 throws up its hand. 00:02:38.000 --> 00:02:39.000 And so it - 00:02:39.000 --> 00:02:43.000 at that point the stream is - it requires you to kind of intervene, 00:02:43.000 --> 00:02:45.000 check the fail state, see that something's wrong, 00:02:45.000 --> 00:02:47.000 clear that fail state, 00:02:47.000 --> 00:02:50.000 decide what to do about it, kind of restart, and kind of pick up where you left off. It 00:02:50.000 --> 00:02:52.000 makes for kind of messy handling 00:02:52.000 --> 00:02:53.000 00:02:53.000 --> 00:02:57.000 to have all that code kind of in your face when you're trying to do that reading, 00:02:57.000 --> 00:03:01.000 and that's actually why we've provided the things like get integer, get line and get 00:03:01.000 --> 00:03:03.000 wheel, and the simple I/O library 00:03:03.000 --> 00:03:05.000 to just manage that for you. 00:03:05.000 --> 00:03:09.000 Basically what they're doing is in a loop they're trying to read that integer 00:03:09.000 --> 00:03:09.000 00:03:09.000 --> 00:03:13.000 off the console. And if it fails, write resetting the stream, 00:03:13.000 --> 00:03:16.000 going back around asking the user to type in 00:03:16.000 --> 00:03:20.000 - give it another try, until they get something that's well formed. So 00:03:20.000 --> 00:03:22.000 typically we're just going to use these, 00:03:22.000 --> 00:03:24.000 because they just provide conveniences. You could certainly use this, but it would just 00:03:24.000 --> 00:03:28.000 require more effort on your part to kind of manage the error conditions and retry 00:03:28.000 --> 00:03:31.000 and whatnot. So 00:03:31.000 --> 00:03:35.000 that's why it's there. 00:03:35.000 --> 00:03:38.000 The C++ file I/O; so 00:03:38.000 --> 00:03:42.000 the console is actually just a particular instance of the stream. Cout and cin 00:03:42.000 --> 00:03:47.000 are the string that's attached to the users interface console there. 00:03:47.000 --> 00:03:51.000 That the same sort of mechanism is used to read files on disks, so text files on 00:03:51.000 --> 00:03:53.000 disks that have contents you like to 00:03:53.000 --> 00:03:56.000 pull into a database, or you want to write some information out to a file, you 00:03:56.000 --> 00:03:58.000 use the file stream for that. 00:03:58.000 --> 00:04:01.000 There is a header called fstream, standard C++ header 00:04:01.000 --> 00:04:02.000 in this case, so 00:04:02.000 --> 00:04:04.000 enclosed in < >, 00:04:04.000 --> 00:04:08.000 that declares the isstream and the osstream. The input file stream for reading, 00:04:08.000 --> 00:04:12.000 the output file stream for writing. 00:04:12.000 --> 00:04:14.000 Declaring these variables; this [inaudible] 00:04:14.000 --> 00:04:18.000 just sets up a default stream that is not connected to anything on disc. 00:04:18.000 --> 00:04:22.000 Before you do anything with it you really do need to attach it to some 00:04:22.000 --> 00:04:25.000 named location, some file by name on your disk 00:04:25.000 --> 00:04:27.000 to have the right thing happen, to read from some 00:04:27.000 --> 00:04:29.000 contents, or to write the contents somewhere. 00:04:29.000 --> 00:04:32.000 The operation that does that is open, 00:04:32.000 --> 00:04:34.000 so the isstream and the osstream are objects, 00:04:34.000 --> 00:04:39.000 so dot notation is used to send messages to it. In this case, telling the 00:04:39.000 --> 00:04:40.000 input stream 00:04:40.000 --> 00:04:45.000 to open the file whose name is "names.txt." 00:04:45.000 --> 00:04:48.000 The behavior for open is to assume that you meant the file in the current 00:04:48.000 --> 00:04:52.000 directory if you don't otherwise give a more fully specified path. So 00:04:52.000 --> 00:04:56.000 this is almost always the way we're going to do this, we're just going to open a file by name. It's going to look 00:04:56.000 --> 00:04:59.000 for it in the project directory, where your code is, where you project is, so 00:04:59.000 --> 00:05:01.000 kind of right there locally. 00:05:01.000 --> 00:05:04.000 Now this will look for a file whose name is exactly names.txt, 00:05:04.000 --> 00:05:09.000 and then from that point the file positions, the kind of cursor we 00:05:09.000 --> 00:05:12.000 call it, is positioned at the beginning of the input stream. The first character read 00:05:12.000 --> 00:05:16.000 will be the first character of names.txt, and as you move forward 00:05:16.000 --> 00:05:18.000 it will read its way all the way to the end. 00:05:18.000 --> 00:05:21.000 Similarly, doing an outopen, 00:05:21.000 --> 00:05:25.000 it opens a file and kind of positions the writing at the very beginning 00:05:25.000 --> 00:05:27.000 that will - the first character written will be the first character then when 00:05:27.000 --> 00:05:32.000 you finish. And that file, they'll be written in sequence. 00:05:32.000 --> 00:05:36.000 So this is one of those places, actually, probably the only one that this 00:05:36.000 --> 00:05:39.000 direction is going to be relevant for. I talked a little bit last time about C-strings 00:05:39.000 --> 00:05:42.000 and C++ strings, and you might have been a little bit 00:05:42.000 --> 00:05:43.000 worried about why 00:05:43.000 --> 00:05:45.000 I'm telling you you need to know that both exist. 00:05:45.000 --> 00:05:47.000 And so last time I talked a little about 00:05:47.000 --> 00:05:51.000 one way in which C-strings don't do what you think, in that one case of 00:05:51.000 --> 00:05:55.000 concatenation, and how you can do a - force a conversion from the old to the new. 00:05:55.000 --> 00:05:57.000 Now, I also mentioned that there was a conversion that went in the 00:05:57.000 --> 00:06:01.000 opposite direction. You had a new string, and you wanted the old one. 00:06:01.000 --> 00:06:02.000 And 00:06:02.000 --> 00:06:04.000 one of the first questions you might ask is well why would I ever want to do that? Why 00:06:04.000 --> 00:06:08.000 would I ever want to go backwards? Why do I want to move back to the older yucky thing? 00:06:08.000 --> 00:06:10.000 This is the case that comes up; 00:06:10.000 --> 00:06:12.000 the open operation 00:06:12.000 --> 00:06:15.000 on isstream and osstream 00:06:15.000 --> 00:06:19.000 expects its argument to be specified as an old style string. 00:06:19.000 --> 00:06:22.000 This is actually just an artifact; it has to do with it - 00:06:22.000 --> 00:06:24.000 the group that was working on 00:06:24.000 --> 00:06:27.000 designing the string package. The group that was designing the string package were 00:06:27.000 --> 00:06:31.000 not in sync, and they were not working together. The string package was 00:06:31.000 --> 00:06:33.000 finalized before the string package was ready 00:06:33.000 --> 00:06:37.000 and so it depended on what was available at the time and that was only the old style 00:06:37.000 --> 00:06:37.000 string. 00:06:37.000 --> 00:06:41.000 So as a result, it wants an old style string, and that's what it takes, and you 00:06:41.000 --> 00:06:43.000 can't give it a C++ 00:06:43.000 --> 00:06:47.000 string. So in double quotes - so this is the case where the double quotes 00:06:47.000 --> 00:06:49.000 are actually old style strings, 00:06:49.000 --> 00:06:52.000 in almost all situations gets converted on your behalf automatically. 00:06:52.000 --> 00:06:55.000 In this case it's not being converted and it's exactly what's wanted. 00:06:55.000 --> 00:06:59.000 So if you have a name that's a string constant or a literal, you can just pass it 00:06:59.000 --> 00:07:01.000 in double quotes to open. 00:07:01.000 --> 00:07:03.000 If you have a C++ variable, 00:07:03.000 --> 00:07:07.000 so you've asked the user for what file to open, and you've used getline to 00:07:07.000 --> 00:07:08.000 read it into a string, 00:07:08.000 --> 00:07:13.000 if you try to pass that C++ string variable to open, it will not match 00:07:13.000 --> 00:07:14.000 what it's expecting. 00:07:14.000 --> 00:07:18.000 I do need to do that conversion asking it to go .c_str 00:07:18.000 --> 00:07:21.000 to convert itself into the old style format. 00:07:21.000 --> 00:07:24.000 So that was sort of where I was getting to when I kind of 00:07:24.000 --> 00:07:26.000 positioned you to realize this was gonna 00:07:26.000 --> 00:07:29.000 someday come up. This is the one piece of the interface that will interact with this 00:07:29.000 --> 00:07:31.000 quarter that requires that old string, 00:07:31.000 --> 00:07:33.000 where you'll have to make that effort to 00:07:33.000 --> 00:07:36.000 convert it backwards. 00:07:36.000 --> 00:07:39.000 Both of these operations can fail. 00:07:39.000 --> 00:07:43.000 When you open a file and [inaudible] - question here? So how hard 00:07:43.000 --> 00:07:44.000 [inaudible]? 00:07:44.000 --> 00:07:48.000 You know it's obviously extremely easy to do it; 00:07:48.000 --> 00:07:50.000 the issue has to do with compatibility. 00:07:50.000 --> 00:07:54.000 They announced it this way, people wrote code that expected it this way 00:07:54.000 --> 00:07:57.000 and then you change it out from under them and all this code breaks that used 00:07:57.000 --> 00:07:58.000 to work. 00:07:58.000 --> 00:08:01.000 And so as a result of this [inaudible] 00:08:01.000 --> 00:08:02.000 compatibility an issue of 00:08:02.000 --> 00:08:04.000 once we kind of published it and we told people this was how it works, we can't 00:08:04.000 --> 00:08:07.000 really take it away from them. And so part of that's - sort of part of what we're doing within C++2, 00:08:07.000 --> 00:08:10.000 which is things that used to work in C still need to work in C, 00:08:10.000 --> 00:08:11.000 and so as a result 00:08:11.000 --> 00:08:14.000 there's a certain amount of history that we're all carrying forward with us in a very 00:08:14.000 --> 00:08:16.000 annoying way. I totally agree 00:08:16.000 --> 00:08:19.000 that it seems like we could just fix it, but we would break a lot of code in the process 00:08:19.000 --> 00:08:21.000 and anger a lot of 00:08:21.000 --> 00:08:24.000 existing programmers. 00:08:24.000 --> 00:08:28.000 So both of these open calls could fail; you might be able to - try to open a file and it 00:08:28.000 --> 00:08:31.000 doesn't exist, you don't have the permissions for it, you spelled the name wrong. 00:08:31.000 --> 00:08:34.000 Similarly trying to open it for writing, it's like you might not have write 00:08:34.000 --> 00:08:36.000 permission in the directory. 00:08:36.000 --> 00:08:38.000 And 00:08:38.000 --> 00:08:41.000 in either situation you need to know, well did it open or did it not? 00:08:41.000 --> 00:08:44.000 There's not a return value from open that tells you that. 00:08:44.000 --> 00:08:47.000 What there is is a member function called 00:08:47.000 --> 00:08:52.000 .fail, that you can ask the stream at any point, are you in a fail state. So for 00:08:52.000 --> 00:08:54.000 operations that actually kinda have a chance of succeeding or failing in the 00:08:54.000 --> 00:08:57.000 string, you'll tend to actually almost write the code as a 00:08:57.000 --> 00:08:57.000 try it 00:08:57.000 --> 00:09:01.000 then check in .sale. So try to read this thing, check in .sale. Try to 00:09:01.000 --> 00:09:03.000 open this file check in .sale as your way 00:09:03.000 --> 00:09:07.000 of following up on did it work and making sure that you 00:09:07.000 --> 00:09:09.000 have good contents before you keep going. 00:09:09.000 --> 00:09:12.000 If the in .open has failed, 00:09:12.000 --> 00:09:14.000 then every subsequent read on it will fail. 00:09:14.000 --> 00:09:17.000 Once the string is in a fail state, nothing works. You can't read 00:09:17.000 --> 00:09:20.000 or write or do anything with it until you fix the error, 00:09:20.000 --> 00:09:23.000 and that's the in .clear 00:09:23.000 --> 00:09:26.000 command that kind of resets the state back into a known good state, 00:09:26.000 --> 00:09:29.000 and then you have a chance to retry. So for example, if you were trying to open a 00:09:29.000 --> 00:09:32.000 file that the user gave you a name for, 00:09:32.000 --> 00:09:35.000 they might type the name wrong. So you could try in .openit, check 00:09:35.000 --> 00:09:36.000 in .dot fail. 00:09:36.000 --> 00:09:40.000 If it failed, say no, no, I couldn't open that file, why don't you try again, get a new 00:09:40.000 --> 00:09:41.000 name, 00:09:41.000 --> 00:09:45.000 and then you'd clear the state, come back around and try another in .open 00:09:45.000 --> 00:09:51.000 to - until you get one that succeeds. 00:09:51.000 --> 00:09:53.000 Once you have one of those guys open 00:09:53.000 --> 00:09:55.000 for reading or writing, 00:09:55.000 --> 00:09:56.000 there are three 00:09:56.000 --> 00:10:01.000 main ways that you can do your input/output. 00:10:01.000 --> 00:10:06.000 We have seen this form a little bit, this one with the insertion/extraction, 00:10:06.000 --> 00:10:09.000 these other two are more likely to be useful in the file reading state as 00:10:09.000 --> 00:10:12.000 opposed to interacting with the user state, and they have to deal with just 00:10:12.000 --> 00:10:15.000 breaking down the input 00:10:15.000 --> 00:10:17.000 more 00:10:17.000 --> 00:10:19.000 fine graindly. 00:10:19.000 --> 00:10:21.000 Let's say this first one is reading and writing single characters. It might be 00:10:21.000 --> 00:10:24.000 that all I want to do is just go through the file and read it character by character. 00:10:24.000 --> 00:10:27.000 Maybe what I'm trying to write is something that will just count the characters and 00:10:27.000 --> 00:10:30.000 produce a frequency count across 00:10:30.000 --> 00:10:33.000 the file, tell me how many A's and B's and C's are in it, 00:10:33.000 --> 00:10:35.000 or just tell me how many characters are in the file at all. 00:10:35.000 --> 00:10:37.000 In .get 00:10:37.000 --> 00:10:40.000 is the number function that you send to an input file stream 00:10:40.000 --> 00:10:42.000 that will retrieve the next character. 00:10:42.000 --> 00:10:46.000 If [inaudible] the next character from the stream it returns EOF when there are no 00:10:46.000 --> 00:10:49.000 more characters. EOF is the end of file marker, it's actually capital 00:10:49.000 --> 00:10:53.000 EOF, it's the constant that's defined with the class. And 00:10:53.000 --> 00:10:56.000 so you could read till EOF as a way of just getting them character by 00:10:56.000 --> 00:10:58.000 character. 00:10:58.000 --> 00:11:02.000 Similarly there is a put on the other side, which is when you're writing, do you just 00:11:02.000 --> 00:11:04.000 want to write a single character. 00:11:04.000 --> 00:11:06.000 You could also do this with 00:11:06.000 --> 00:11:09.000 out << ch, which writes the character. This actually just does a 00:11:09.000 --> 00:11:11.000 put of the character, just 00:11:11.000 --> 00:11:15.000 kind of a matching function in the analog to get input 00:11:15.000 --> 00:11:19.000 that do single character io. 00:11:19.000 --> 00:11:22.000 Sometimes what you're trying to do is process it line by line. Each line is the 00:11:22.000 --> 00:11:25.000 name of somebody and you're kind of putting those names into a database. You 00:11:25.000 --> 00:11:28.000 don't want to just assemble the characters by characters, and you don't know how 00:11:28.000 --> 00:11:30.000 many 00:11:30.000 --> 00:11:31.000 tokens there might be, 00:11:31.000 --> 00:11:35.000 that the white space might be that there's Julie Diane Zelenski, sometimes 00:11:35.000 --> 00:11:38.000 there might be Julie Zelenski, you don't know how many name pieces might appear to be 00:11:38.000 --> 00:11:39.000 there. 00:11:39.000 --> 00:11:42.000 You can use getline to read an entire line in one chuck. 00:11:42.000 --> 00:11:45.000 So it'll read everything up to 00:11:45.000 --> 00:11:49.000 the first new line character it finds. It actually discards the new line and advances 00:11:49.000 --> 00:11:52.000 past it. So what you will get is - 00:11:52.000 --> 00:11:56.000 the sequence of characters that you will have read will be everything up to and not including 00:11:56.000 --> 00:11:59.000 the new line. The new line will be consumed though so that reading will 00:11:59.000 --> 00:12:00.000 pick up 00:12:00.000 --> 00:12:02.000 on the next line and go forward. 00:12:02.000 --> 00:12:06.000 Getline is a free function. 00:12:06.000 --> 00:12:12.000 It is not a member function on the stream. It takes a stream as its first 00:12:12.000 --> 00:12:12.000 argument. 00:12:12.000 --> 00:12:16.000 It takes a string by reference as its second argument, 00:12:16.000 --> 00:12:20.000 and it fills in the line with the text of 00:12:20.000 --> 00:12:24.000 the characters from here to the next line read in the file. 00:12:24.000 --> 00:12:26.000 00:12:26.000 --> 00:12:29.000 If it fails the way you will find out is by checking the fail 00:12:29.000 --> 00:12:31.000 states. You can do a getline 00:12:31.000 --> 00:12:34.000 inline and then in .fail after it to see, well did it write something 00:12:34.000 --> 00:12:39.000 in the line that was valid? If it failed, then the contents of line are 00:12:39.000 --> 00:12:40.000 00:12:40.000 --> 00:12:44.000 unchanged, so they'll be whatever nonsense they were. So 00:12:44.000 --> 00:12:46.000 it's a way of just pulling it line by line. 00:12:46.000 --> 00:12:51.000 This name has the same words in it as 00:12:51.000 --> 00:12:52.000 rgetlineGL 00:12:52.000 --> 00:12:55.000 in the sympio, which shows that it's kind of a reasonable name for the kind 00:12:55.000 --> 00:13:00.000 of thing that reads line by line, but there is a different arrangement to how it's - what 00:13:00.000 --> 00:13:03.000 it's used for and how it's it used. So rgetline takes no arguments and returns a line read 00:13:03.000 --> 00:13:04.000 for the console. 00:13:04.000 --> 00:13:08.000 The lower case getline takes the file stream to read from and the string to write 00:13:08.000 --> 00:13:10.000 it into 00:13:10.000 --> 00:13:11.000 and 00:13:11.000 --> 00:13:13.000 does not have a return value. 00:13:13.000 --> 00:13:16.000 You check in .fail if you 00:13:16.000 --> 00:13:18.000 want to know how it went. So write the entire line out there, [inaudible] a put line equivalence, so 00:13:18.000 --> 00:13:22.000 in fact you could just use the out 00:13:22.000 --> 00:13:26.000 stream insertion here, stick that line back out with an nline to kind of reproduce 00:13:26.000 --> 00:13:28.000 the same line your just read. 00:13:28.000 --> 00:13:32.000 And then these we've talked a little about, this idea of formatted 00:13:32.000 --> 00:13:35.000 read and write, where it's expecting things by format. It's expecting to see a character, 00:13:35.000 --> 00:13:38.000 it's expecting to see an integer, and it's expecting to see a 00:13:38.000 --> 00:13:39.000 string. 00:13:39.000 --> 00:13:43.000 It uses white space as the default delimiter between those things. So it's kind of 00:13:43.000 --> 00:13:46.000 scanning over white space and discarding it and then trying to pull the next thing out. 00:13:46.000 --> 00:13:47.000 00:13:47.000 --> 00:13:51.000 These are definitely much trickier to use because if the format that you're 00:13:51.000 --> 00:13:54.000 expecting doesn't show up, it causes the stream to get new fail state, and you 00:13:54.000 --> 00:13:56.000 have to kind of fix it and recreate it. 00:13:56.000 --> 00:14:00.000 So often even when you expect that things are going to be, let's say, a sequence of 00:14:00.000 --> 00:14:02.000 numbers or a name fall by number, 00:14:02.000 --> 00:14:05.000 you might instead choose to pull it as a string 00:14:05.000 --> 00:14:09.000 and then use operations on the string itself to kinda divide it up 00:14:09.000 --> 00:14:12.000 rather than depending on stream io because stream io is just a little bit harder to get 00:14:12.000 --> 00:14:14.000 that same effect. 00:14:14.000 --> 00:14:17.000 And then in all these cases write in .fail. 00:14:17.000 --> 00:14:19.000 There is also - 00:14:19.000 --> 00:14:22.000 you could check out.fail. It's just much less common that the 00:14:22.000 --> 00:14:25.000 writing will fail, so you don't see it as much, but it is true for example, if 00:14:25.000 --> 00:14:28.000 you had wanted a disk space and you were writing, a 00:14:28.000 --> 00:14:31.000 write operation could fail because it had 00:14:31.000 --> 00:14:35.000 wanted a space or some media error had happened on the disk, so 00:14:35.000 --> 00:14:36.000 both of those 00:14:36.000 --> 00:14:40.000 have reasons to check fail. 00:14:40.000 --> 00:14:43.000 So let me do just a little bit of 00:14:43.000 --> 00:14:45.000 live coding 00:14:45.000 --> 00:14:49.000 to show you that I - 00:14:49.000 --> 00:14:52.000 it works the way I'm 00:14:52.000 --> 00:14:54.000 telling you. Yeah? So the 00:14:54.000 --> 00:14:57.000 fail 00:14:57.000 --> 00:14:58.000 function, is it 00:14:58.000 --> 00:14:59.000 going 00:14:59.000 --> 00:15:02.000 to always be the stream that's failing and not 00:15:02.000 --> 00:15:04.000 the function that's failing? Yes, 00:15:04.000 --> 00:15:08.000 pretty much. There are a couple rare cases where the function actually also 00:15:08.000 --> 00:15:11.000 tells you a little bit about it, but a general fail just covers the whole general 00:15:11.000 --> 00:15:14.000 case of anything I have just got on the stream fail 00:15:14.000 --> 00:15:16.000 so any of the operations 00:15:16.000 --> 00:15:20.000 that could potentially run into some error condition will set the fail in such a way 00:15:20.000 --> 00:15:22.000 that your next call to in .fail will tell you about it. 00:15:22.000 --> 00:15:26.000 And so that's the - the general model will be; make the call, check the fail, 00:15:26.000 --> 00:15:28.000 if you know that there was a chance that something could have gone 00:15:28.000 --> 00:15:34.000 wrong and then you want to clean up after it and do something [inaudible]. 00:15:34.000 --> 00:15:38.000 So I'm gonna show you that I'm gonna get the name of the file from the 00:15:38.000 --> 00:15:40.000 user here, 00:15:40.000 --> 00:15:43.000 I'm going to use in .open of that, 00:15:43.000 --> 00:15:46.000 and I'm going to show you the error that you're gonna get when you forget to convert 00:15:46.000 --> 00:15:47.000 it, while I'm at it. 00:15:47.000 --> 00:15:50.000 And then I'll have like an in 00:15:50.000 --> 00:15:52.000 00:15:52.000 --> 00:15:53.000 .fail error 00:15:53.000 --> 00:15:55.000 wouldn't - 00:15:55.000 --> 00:15:57.000 file didn't open. 00:15:57.000 --> 00:16:02.000 First I just want to show you this little simple stuff; I've got 00:16:02.000 --> 00:16:06.000 my ifstream declared, my attempt to open it and then my check for seeing that it 00:16:06.000 --> 00:16:09.000 failed. I'm gonna 00:16:09.000 --> 00:16:13.000 anticipate the fact that the compiler's gonna be 00:16:13.000 --> 00:16:16.000 complaining about the fact that it hasn't heard about fstream, so I'm gonna tell it about 00:16:16.000 --> 00:16:16.000 fstream. 00:16:16.000 --> 00:16:20.000 And I'm gonna let this go ahead in compiling, although I know it has an error in it, 00:16:20.000 --> 00:16:22.000 because I want to show you sort of the things that are happening. So the first thing 00:16:22.000 --> 00:16:25.000 it's complaining about actually is this one, which is 00:16:25.000 --> 00:16:29.000 the fact that getline is not declared in the scope, which meant I forgot one more of my 00:16:29.000 --> 00:16:31.000 headers that I wanted. Let 00:16:31.000 --> 00:16:36.000 me move this up a little bit because it's sitting down a little far. 00:16:36.000 --> 00:16:39.000 And then the second thing it's complaining about is right here. 00:16:39.000 --> 00:16:43.000 This is pretty hard to see, but I'll read it to you so you can tell what it says; it says error, 00:16:43.000 --> 00:16:45.000 there's no matching function call 00:16:45.000 --> 00:16:48.000 and then it has sort of some gobbly gook that's a little bit scary, 00:16:48.000 --> 00:16:51.000 but includes the name ifstream. It's actually - the full name for ifstream is a 00:16:51.000 --> 00:16:53.000 lot bigger than you think, 00:16:53.000 --> 00:16:54.000 but it's saying that there's - 00:16:54.000 --> 00:16:58.000 the ifstream is open, and it says that it does not 00:16:58.000 --> 00:17:02.000 have a match to that, that there is no open call on the ifstream class, so no 00:17:02.000 --> 00:17:05.000 member function of the ifstream class whose name is open, 00:17:05.000 --> 00:17:07.000 whose argument is a string. 00:17:07.000 --> 00:17:11.000 And so that cryptic little bit of information is gonna be your reminder 00:17:11.000 --> 00:17:15.000 to jog your memory about the fact that open doesn't deal in the 00:17:15.000 --> 00:17:18.000 new string world, it wants the old string world. It will 00:17:18.000 --> 00:17:20.000 not take a new string, 00:17:20.000 --> 00:17:21.000 and I will convert it 00:17:21.000 --> 00:17:26.000 to my old string, 00:17:26.000 --> 00:17:30.000 and then be able to get this thing compiling. 00:17:30.000 --> 00:17:35.000 And so when it runs if I enter a file name of I say [inaudible], 00:17:35.000 --> 00:17:37.000 it'll say error file didn't open, some file that 00:17:37.000 --> 00:17:40.000 I don't have access for. It happens that I have one sitting here, I think, whose name is 00:17:40.000 --> 00:17:41.000 00:17:41.000 --> 00:17:45.000 handout.txt. I took the text of some handout and then I just 00:17:45.000 --> 00:17:47.000 left it there. So 00:17:47.000 --> 00:17:48.000 let me 00:17:48.000 --> 00:17:49.000 doing something with that file. Let's 00:17:49.000 --> 00:17:53.000 just do something simple where we just count the number of lines in it. Let's say - actually I'll make 00:17:53.000 --> 00:17:55.000 a little function that - 00:17:55.000 --> 00:17:58.000 just to talk a little bit about one of the things that's a little quirky about 00:17:58.000 --> 00:18:00.000 ifstreams 00:18:00.000 --> 00:18:01.000 is that 00:18:01.000 --> 00:18:04.000 when you pass an ifstream you will 00:18:04.000 --> 00:18:07.000 typically want to do so by reference. 00:18:07.000 --> 00:18:08.000 Not only is this kind of a good idea, 00:18:08.000 --> 00:18:12.000 because the ifstream is kind of changing in the process of being read. It's 00:18:12.000 --> 00:18:15.000 updating its internal state and you want to be sure that we're not 00:18:15.000 --> 00:18:19.000 missing this update that's going on. It's also the case that most 00:18:19.000 --> 00:18:22.000 libraries require you to pass it by reference. That it doesn't have a model for how 00:18:22.000 --> 00:18:25.000 to take a copy of a stream and make another copy that's distinct. That it really 00:18:25.000 --> 00:18:28.000 is always referring to the same file, so in fact in most libraries you have 00:18:28.000 --> 00:18:31.000 to pass it by reference. 00:18:31.000 --> 00:18:34.000 So I'll go ahead and pass it by reference. I'm gonna go in here and I'm just gonna do a line-by-line 00:18:34.000 --> 00:18:39.000 read and count as I go. I'm 00:18:39.000 --> 00:18:43.000 gonna write this as a wild [inaudible], 00:18:43.000 --> 00:18:45.000 and I'm gonna say 00:18:45.000 --> 00:18:46.000 read the next line 00:18:46.000 --> 00:18:48.000 from the file into the variable, 00:18:48.000 --> 00:18:53.000 and then if in .fail - so if it was unable to read another line, 00:18:53.000 --> 00:18:57.000 the - my assumption here is gonna be that 00:18:57.000 --> 00:19:00.000 we're done, so it will fail as eof . It's the most common reason it could 00:19:00.000 --> 00:19:04.000 fail. It could also fail if there was some sort of more catastrophic error, you're leading a file from a 00:19:04.000 --> 00:19:06.000 network and the network's gone down or something like that. In our 00:19:06.000 --> 00:19:09.000 case its right, the in .fail is going to tell us yeah, there's nothing more to read 00:19:09.000 --> 00:19:11.000 from this file, which means we've gotten to the end. 00:19:11.000 --> 00:19:14.000 We've advanced the count. Whenever we get a good line we go back 00:19:14.000 --> 00:19:15.000 around, so we're 00:19:15.000 --> 00:19:18.000 using kind of the wild true in this case because we have a little bit of work to do 00:19:18.000 --> 00:19:20.000 before we're ready to decide whether to keep going, 00:19:20.000 --> 00:19:22.000 in this case, reading that line. 00:19:22.000 --> 00:19:28.000 And then I return the count at the end, 00:19:28.000 --> 00:19:30.000 and then I can then down 00:19:30.000 --> 00:19:33.000 here print it nom lines 00:19:33.000 --> 00:19:37.000 = mi call to count lines of n 00:19:37.000 --> 00:19:39.000 and l. Okay. Let 00:19:39.000 --> 00:19:40.000 me move that up a little bit. 00:19:40.000 --> 00:19:45.000 Last time I posted the code that I wrote in the 00:19:45.000 --> 00:19:49.000 editor here, and I'll be happy to do that again today, so you 00:19:49.000 --> 00:19:52.000 shouldn't need to worry about copying it down, I will post it later if you want to 00:19:52.000 --> 00:19:53.000 have a copy of it for your records, but 00:19:53.000 --> 00:19:56.000 just showing, okay, yeah, we're just a line by line read, 00:19:56.000 --> 00:19:59.000 counting, and then a little bit more of the how do you open something, how do you 00:19:59.000 --> 00:20:03.000 check for failure. And 00:20:03.000 --> 00:20:06.000 when I put this together, what does it complain about? Well I think it complains about the fact that 00:20:06.000 --> 00:20:16.000 I told it my function returned void, but then I made it return it. And that 00:20:16.000 --> 00:20:19.000 should be okay now. And so if I read the handout.txt file, 00:20:19.000 --> 00:20:23.000 the number of lines in it happens to be 28. It's just some text I'd cut out of the handout, so 00:20:23.000 --> 00:20:25.000 there are 28 new line characters 00:20:25.000 --> 00:20:31.000 is basically what it's telling me 00:20:31.000 --> 00:20:32.000 there. 00:20:32.000 --> 00:20:36.000 So I can just do more things, like I could use - change this loop and instead use like get to 00:20:36.000 --> 00:20:39.000 do a single character count. I could say how many characters were in there. 00:20:39.000 --> 00:20:41.000 If I used 00:20:41.000 --> 00:20:42.000 the 00:20:42.000 --> 00:20:45.000 tokenization and I said, well just tell how many strings I find using string 00:20:45.000 --> 00:20:48.000 extraction, it would kind of count the number of non-space things that it found and 00:20:48.000 --> 00:20:49.000 things like that. 00:20:49.000 --> 00:20:51.000 Typically the 00:20:51.000 --> 00:20:55.000 IO is one of those errors I said where there's like a vast array of nuances to all 00:20:55.000 --> 00:21:00.000 the different things you can do with it, but the simple things actually are 00:21:00.000 --> 00:21:03.000 usually fairly easy, and those are the only ones that really going to matter to us as being 00:21:03.000 --> 00:21:05.000 able to do a little bit of simple reading and 00:21:05.000 --> 00:21:09.000 file reading/writing to get information into our programs. How do 00:21:09.000 --> 00:21:11.000 you feel about that? Question? Sorry, why do 00:21:11.000 --> 00:21:12.000 have getline 00:21:12.000 --> 00:21:14.000 an empty string? 00:21:14.000 --> 00:21:16.000 So getline, 00:21:16.000 --> 00:21:19.000 the one that was down here? This one? No, 00:21:19.000 --> 00:21:21.000 the one that - Oh, the 00:21:21.000 --> 00:21:26.000 one that's up here. So yeah, let's talk about that. The getline that's here is - 00:21:26.000 --> 00:21:29.000 the second argument to getline is being passed by reference, and so it's 00:21:29.000 --> 00:21:32.000 filling in that line with the information it read from the file. 00:21:32.000 --> 00:21:36.000 So I just declared the variable so I had a place to store it 00:21:36.000 --> 00:21:37.000 and I said, 00:21:37.000 --> 00:21:40.000 okay, read the next line from the file, store the thing you read in the line. It turns 00:21:40.000 --> 00:21:42.000 out I don't actually care about that information, but there's no way to tell 00:21:42.000 --> 00:21:44.000 getline to just throw it away anyway. Oh. 00:21:44.000 --> 00:21:47.000 So I'm using it to just kinda move through line-by-line, but it happens to 00:21:47.000 --> 00:21:51.000 be that getline requires me to store the answer somewhere, and I'm storing it. 00:21:51.000 --> 00:21:54.000 Instead of returning it, it happens to use the design where it fills it in by 00:21:54.000 --> 00:21:56.000 reference. 00:21:56.000 --> 00:21:59.000 There's actually - it turns out to be a little bit more efficient 00:21:59.000 --> 00:22:02.000 to do a pass by reference and fill something in, then to return it. And the 00:22:02.000 --> 00:22:05.000 C++ libraries in general prefer that style of 00:22:05.000 --> 00:22:06.000 00:22:06.000 --> 00:22:09.000 getting information back out of a function as opposed to the function return, 00:22:09.000 --> 00:22:13.000 which you think of as being a little more natural design. There's a slight 00:22:13.000 --> 00:22:16.000 inefficiency to that relative to the pass by reference and the libraries tend to be very 00:22:16.000 --> 00:22:19.000 hyper-conscious of that efficiency, so they tend to prefer this 00:22:19.000 --> 00:22:26.000 slightly more awkward style. Question? 00:22:26.000 --> 00:22:28.000 Why in the 00:22:28.000 --> 00:22:31.000 main [inaudible] does the 00:22:31.000 --> 00:22:32.000 error 00:22:32.000 --> 00:22:36.000 open [inaudible] file didn't open with [inaudible] like print error: file didn't open? You 00:22:36.000 --> 00:22:37.000 know 00:22:37.000 --> 00:22:40.000 it's just the way that error works. Error wants to make sure that you don't mistake what 00:22:40.000 --> 00:22:44.000 it does, and so it actually prefixes whatever you ask it to write with this big 00:22:44.000 --> 00:22:47.000 ERROR in uppercase letters, and so 00:22:47.000 --> 00:22:50.000 the purpose of error is twofold; is to report what happened and to halt 00:22:50.000 --> 00:22:54.000 processing. And so when it reports that it actually prefixes it with this big red 00:22:54.000 --> 00:22:58.000 E-R-R-O-R just to say don't miss this, and then it halts processing 00:22:58.000 --> 00:23:01.000 there. And it's just - the error [inaudible] libraries function, which is your way of handling any 00:23:01.000 --> 00:23:04.000 kind of catastrophic I can't recover from this. And it's certainly 00:23:04.000 --> 00:23:07.000 something we don't want anybody to overlook, and so we try to make it 00:23:07.000 --> 00:23:11.000 really jump out at you when 00:23:11.000 --> 00:23:15.000 it tells you that. So this is in symbio? :It is in genlib actually. Oh. So error's actually declared out of genlib. And can we use it - 00:23:15.000 --> 00:23:18.000 so it's global basically? It is global. It's a telefree function, and you will definitely have occasion 00:23:18.000 --> 00:23:22.000 to use it. Right, it's just - it's your way of saying something happened that there's just no 00:23:22.000 --> 00:23:26.000 recovery from and continuing on would not make sense. Here's a 00:23:26.000 --> 00:23:28.000 - stop and help 00:23:28.000 --> 00:23:32.000 and alert the user something's really wrong, so you don't 00:23:32.000 --> 00:23:34.000 want to keep going after this because there's no way to kind of 00:23:34.000 --> 00:23:36.000 patch things back together. In 00:23:36.000 --> 00:23:38.000 this case probably a more likely thing we'd do, is I should say 00:23:38.000 --> 00:23:42.000 give me another name, let's go back around and try again, would be a 00:23:42.000 --> 00:23:44.000 sort of better way to handle that. I can 00:23:44.000 --> 00:23:46.000 even show you how I would do that. 00:23:46.000 --> 00:23:49.000 I could say, well while true, 00:23:49.000 --> 00:23:51.000 enter the name, 00:23:51.000 --> 00:23:53.000 and maybe I could change this to be well 00:23:53.000 --> 00:23:55.000 if it didn't fail 00:23:55.000 --> 00:23:59.000 then go ahead and break out of the loop. Otherwise, just report that the file 00:23:59.000 --> 00:24:02.000 didn't open, 00:24:02.000 --> 00:24:04.000 and say try again. 00:24:04.000 --> 00:24:06.000 And then the last thing I will need to do 00:24:06.000 --> 00:24:09.000 is clear that state. 00:24:09.000 --> 00:24:11.000 So now it's prompting, 00:24:11.000 --> 00:24:12.000 trying to open it. 00:24:12.000 --> 00:24:15.000 If it didn't fail it will break and then it will move forward to counting the lines. 00:24:15.000 --> 00:24:16.000 00:24:16.000 --> 00:24:19.000 If it did fail it'll continue on through here reporting this message, and then 00:24:19.000 --> 00:24:22.000 that clear, very important, because that clear kind of gets us 00:24:22.000 --> 00:24:26.000 back in the state where we can try again. If we don't clear the error and we try to do 00:24:26.000 --> 00:24:29.000 another in .open, once the string is in a fail state it stays in a fail 00:24:29.000 --> 00:24:33.000 state until you clear it, and no subsequent operation will work whatsoever. 00:24:33.000 --> 00:24:35.000 It's just ignoring everything you ask it to do 00:24:35.000 --> 00:24:38.000 until you have acknowledged you have done something about the problem, which 00:24:38.000 --> 00:24:42.000 in this case was as simple as clearing and asking to open again. 00:24:42.000 --> 00:24:46.000 So if I do it this way 00:24:46.000 --> 00:24:50.000 I enter some name it'll say that didn't open, try again. And then if I say 00:24:50.000 --> 00:24:51.000 handout.txt, 00:24:51.000 --> 00:24:52.000 it'll open it and 00:24:52.000 --> 00:24:57.000 go ahead and read. All right, 00:24:57.000 --> 00:25:01.000 any questions about iostreams? We're 00:25:01.000 --> 00:25:07.000 gonna move away from this [inaudible], if there's anything about it you'd like to know I'd be happy to answer it. 00:25:07.000 --> 00:25:08.000 So let me 00:25:08.000 --> 00:25:11.000 get us back to 00:25:11.000 --> 00:25:15.000 our slides, 00:25:15.000 --> 00:25:17.000 and I'll kind 00:25:17.000 --> 00:25:21.000 of move on to the more object-oriented features of the things we're going to be 00:25:21.000 --> 00:25:25.000 depending on and using this quarter. 00:25:25.000 --> 00:25:27.000 So the libraries that we have been looking at, 00:25:27.000 --> 00:25:30.000 many of them are just provided as what we call free functions. Global functions that 00:25:30.000 --> 00:25:34.000 aren't assigned to a particular object, they are part of a class, so asking for random 00:25:34.000 --> 00:25:34.000 integer, 00:25:34.000 --> 00:25:37.000 reading a line, competing the square root, 00:25:37.000 --> 00:25:40.000 gobs of things are there that just kind of have 00:25:40.000 --> 00:25:43.000 functionality that you can use anywhere and everywhere procedurally. 00:25:43.000 --> 00:25:46.000 We've just started to see some things that are provided in terms of classes, 00:25:46.000 --> 00:25:50.000 the string of the class, that means that you have string objects that you're messaging and 00:25:50.000 --> 00:25:52.000 having them manipulate themselves. 00:25:52.000 --> 00:25:55.000 The stream object also is class, ifstream, ofstream, those are all classes 00:25:55.000 --> 00:25:57.000 that you send messages like open to 00:25:57.000 --> 00:26:04.000 and fail to, to ask about that streams state or reset its state. This idea of 00:26:04.000 --> 00:26:08.000 a class is one that's hopefully not new to you. Most of you are coming from Java 00:26:08.000 --> 00:26:11.000 have - this is pretty much the only mechanism for writing code for 00:26:11.000 --> 00:26:14.000 Java is in the context of a class. Those 00:26:14.000 --> 00:26:16.000 of you who haven't seen that as much, we're going to definitely be practicing 00:26:16.000 --> 00:26:20.000 on this in our - some simple things you need to know to kind of just get up to the 00:26:20.000 --> 00:26:24.000 vocabulary wise is class is just a way of taking a set of 00:26:24.000 --> 00:26:25.000 fields or data 00:26:25.000 --> 00:26:29.000 and attaching operations to it to where it kind of creates a kind of an 00:26:29.000 --> 00:26:33.000 entity that has both its state and its functionality kind of packaged 00:26:33.000 --> 00:26:34.000 together. 00:26:34.000 --> 00:26:38.000 So in the class interface you'll say here is a time object, and a time object has an 00:26:38.000 --> 00:26:39.000 hour and a minute 00:26:39.000 --> 00:26:40.000 and you can do things like 00:26:40.000 --> 00:26:42.000 tell me if this time's before that time or what the 00:26:42.000 --> 00:26:46.000 duration starting at this time and this end time would - there would be all these 00:26:46.000 --> 00:26:50.000 behaviors that are like [inaudible] to do. Can you print a time, sure. Can I read a time for a 00:26:50.000 --> 00:26:51.000 file, sure. 00:26:51.000 --> 00:26:54.000 As long as the interface for the time class provides those things, its kinda this fully 00:26:54.000 --> 00:26:56.000 flip - fleshed out 00:26:56.000 --> 00:26:58.000 new data type 00:26:58.000 --> 00:27:02.000 that then you use time objects of whenever you need to work with time. 00:27:02.000 --> 00:27:06.000 The idea is that the client use the object, which is the first role we're 00:27:06.000 --> 00:27:08.000 gonna be in for a couple weeks here, 00:27:08.000 --> 00:27:11.000 is you learn what the abstraction is. What does the class provide? It provides the notion of a 00:27:11.000 --> 00:27:14.000 sequence of characters, that's what stream does. And so that sequence 00:27:14.000 --> 00:27:17.000 has all these operations; like well tell me what characters are at this position, or 00:27:17.000 --> 00:27:19.000 find this sub-string, 00:27:19.000 --> 00:27:21.000 or insert these characters, remove those characters. And 00:27:21.000 --> 00:27:24.000 internally it's obviously doing some machinations to keep track of what you 00:27:24.000 --> 00:27:28.000 asked it to do and how to update its internal state. But what's neat is that from 00:27:28.000 --> 00:27:30.000 the outside as a client you just think well there's a sequence of 00:27:30.000 --> 00:27:34.000 characters there and I can ask that sequence of characters to do these 00:27:34.000 --> 00:27:35.000 operations, and 00:27:35.000 --> 00:27:37.000 it does what I ask, 00:27:37.000 --> 00:27:38.000 and that I don't need to know 00:27:38.000 --> 00:27:42.000 how it's implemented internally. What mechanisms it uses and how it responds 00:27:42.000 --> 00:27:44.000 to those things to update it state 00:27:44.000 --> 00:27:46.000 is very much 00:27:46.000 --> 00:27:50.000 kind of behind the abstraction or inside that black box, sometime we'll call it to kind 00:27:50.000 --> 00:27:51.000 of 00:27:51.000 --> 00:27:52.000 00:27:52.000 --> 00:27:54.000 suggest to ourselves that we can't see inside of it, we don't know how it works. It's 00:27:54.000 --> 00:27:57.000 like the microwave, you go up and you punch on the microwave and you say cook for a minute. Like 00:27:57.000 --> 00:28:01.000 what does the microwave do? I don't know, I have no idea, but things get hot, that's what I 00:28:01.000 --> 00:28:02.000 know. 00:28:02.000 --> 00:28:04.000 So the nice thing about [inaudible] is you can say, yeah, 00:28:04.000 --> 00:28:08.000 if you push this button things get hot and that's what I need to know. 00:28:08.000 --> 00:28:12.000 [Inaudible] has become widely 00:28:12.000 --> 00:28:13.000 industry standard in sort 00:28:13.000 --> 00:28:16.000 of all existing languages that are out there. It seems like there's been 00:28:16.000 --> 00:28:19.000 somebody who's gone to the trouble of trying to extend it to add these 00:28:19.000 --> 00:28:22.000 object [inaudible] features and languages like Java that are fully object 00:28:22.000 --> 00:28:25.000 oriented, are very much all the rage now. 00:28:25.000 --> 00:28:29.000 And I thought it was interesting to take just a minute to talk about well why is it so 00:28:29.000 --> 00:28:32.000 successful? Why is object oriented like the next big thing in programming? 00:28:32.000 --> 00:28:36.000 And there are some really good valid reasons for why it is a very 00:28:36.000 --> 00:28:39.000 sensible approach to writing programs 00:28:39.000 --> 00:28:41.000 that is 00:28:41.000 --> 00:28:43.000 worth thinking a little bit about. 00:28:43.000 --> 00:28:46.000 Probably the largest sort of 00:28:46.000 --> 00:28:49.000 motivation for the industry has to do with this idea of taming complexity 00:28:49.000 --> 00:28:51.000 that certainly one of the 00:28:51.000 --> 00:28:53.000 weaknesses of 00:28:53.000 --> 00:28:54.000 ourself as a discipline is that 00:28:54.000 --> 00:28:57.000 the complexity kinda can quickly spiral out of control. 00:28:57.000 --> 00:28:58.000 The programs that - 00:28:58.000 --> 00:29:01.000 as they get larger and larger, their interactions get harder and harder to 00:29:01.000 --> 00:29:02.000 model and we have more 00:29:02.000 --> 00:29:06.000 and more issues where we have bugs and security flaws and viruses 00:29:06.000 --> 00:29:09.000 and whatnot that exploit holes in these things. 00:29:09.000 --> 00:29:12.000 That we need a way as engineers to kind of 00:29:12.000 --> 00:29:15.000 tighten down our discipline and really produce things that actually 00:29:15.000 --> 00:29:17.000 don't have those kind of holes in them. 00:29:17.000 --> 00:29:20.000 And that object oriented probably means one of the ways to try to manage the complexities of 00:29:20.000 --> 00:29:22.000 systems. 00:29:22.000 --> 00:29:25.000 That instead of having lots and lots of code that [inaudible] things, if you can 00:29:25.000 --> 00:29:28.000 break it down into these objects, and each 00:29:28.000 --> 00:29:30.000 class that represents that object can be 00:29:30.000 --> 00:29:33.000 designed and tested and worked on independently, 00:29:33.000 --> 00:29:35.000 there's some hope that you can have a team of programmers working together, 00:29:35.000 --> 00:29:38.000 each managing their own classes 00:29:38.000 --> 00:29:41.000 and have them be able to not interfere with each other too much to kind of 00:29:41.000 --> 00:29:42.000 accomplish - 00:29:42.000 --> 00:29:45.000 get the whole end result done by having people collaborate, but without them kind 00:29:45.000 --> 00:29:48.000 of stepping on top of each other. 00:29:48.000 --> 00:29:51.000 It has a - the advantage of modeling the real world, that we tend to talk to talk about 00:29:51.000 --> 00:29:54.000 classes that kind of have names that speak to us, what's a ballot, what's 00:29:54.000 --> 00:29:59.000 a class list, what's a database, what is a 00:29:59.000 --> 00:30:01.000 time, a string, 00:30:01.000 --> 00:30:04.000 that - a fraction? These things kind of - we have ideas about what those things are 00:30:04.000 --> 00:30:06.000 in the real world, and having the class 00:30:06.000 --> 00:30:09.000 model that abstraction makes it easier to understand what the code is doing and 00:30:09.000 --> 00:30:11.000 what that objects role is 00:30:11.000 --> 00:30:13.000 in solving the problem. 00:30:13.000 --> 00:30:17.000 It also has the advantage of [inaudible] use. That once you build a class and it's 00:30:17.000 --> 00:30:19.000 operations, the idea is that it can 00:30:19.000 --> 00:30:24.000 be pulled out of the - neatly out of the one program and used in another if the 00:30:24.000 --> 00:30:25.000 design has been done, 00:30:25.000 --> 00:30:29.000 and can be changed extended fairly easily in the future if the design was 00:30:29.000 --> 00:30:30.000 00:30:30.000 --> 00:30:32.000 good to begin with. 00:30:32.000 --> 00:30:34.000 So let me tell you what 00:30:34.000 --> 00:30:38.000 kind of things we're going to be doing in our class library 00:30:38.000 --> 00:30:40.000 that will help you to kind of just become a big fan 00:30:40.000 --> 00:30:43.000 of having a bunch of pre-written classes around. 00:30:43.000 --> 00:30:44.000 We have, 00:30:44.000 --> 00:30:49.000 I think, seven classes - I think there's eight actually in our class library 00:30:49.000 --> 00:30:51.000 that just look at certain problems that either 00:30:51.000 --> 00:30:53.000 C++ 00:30:53.000 --> 00:30:56.000 provides in a way that's not as convenient for us, or is kind of missing, 00:30:56.000 --> 00:30:58.000 or that can be improved on where we've 00:30:58.000 --> 00:31:01.000 tackled those things and given you seven classes that you just get to use from 00:31:01.000 --> 00:31:02.000 the get go 00:31:02.000 --> 00:31:06.000 that solve problems that are likely to come up for you. 00:31:06.000 --> 00:31:07.000 One of them is the scanner, 00:31:07.000 --> 00:31:10.000 which I kind of separated by itself because it's a little bit of an unusual class, and 00:31:10.000 --> 00:31:14.000 then there's a bunch of container classes on that next line, the vector 00:31:14.000 --> 00:31:16.000 grid, staque, math and set 00:31:16.000 --> 00:31:19.000 that are used for storing data, different kinds of collections, 00:31:19.000 --> 00:31:21.000 and they differ in kind of 00:31:21.000 --> 00:31:24.000 what their usage pattern is and what they're storing, 00:31:24.000 --> 00:31:26.000 how they're storing it for you. 00:31:26.000 --> 00:31:29.000 But that most programs need to do stuff like this, need to store some kind of 00:31:29.000 --> 00:31:30.000 collection of date, 00:31:30.000 --> 00:31:32.000 why not have some good tools to do it. 00:31:32.000 --> 00:31:33.000 00:31:33.000 --> 00:31:36.000 These tools kinda let you live higher on the food chain. They're very efficient, 00:31:36.000 --> 00:31:39.000 they're debugged, they're commented, the abstraction's been thought about and 00:31:39.000 --> 00:31:40.000 kind of worked out 00:31:40.000 --> 00:31:43.000 and so they provide kinda this very useful piece of function [inaudible] kinda written to you 00:31:43.000 --> 00:31:46.000 ready to go. 00:31:46.000 --> 00:31:49.000 And then I - a little note here is that we study these - we are going to study these 00:31:49.000 --> 00:31:51.000 abstractions twice. 00:31:51.000 --> 00:31:53.000 We're gonna look at these seven classes 00:31:53.000 --> 00:31:57.000 today and Friday as a client, and then start using them all through the quarter. 00:31:57.000 --> 00:32:01.000 In about a week or so after the mid-term we're gonna come back to them 00:32:01.000 --> 00:32:02.000 and say, well how are they implemented? 00:32:02.000 --> 00:32:06.000 That after having used them and appreciated what they provided to you, it 00:32:06.000 --> 00:32:08.000 will be interesting, I think, to open up the hood 00:32:08.000 --> 00:32:11.000 and look down in there and see how they work. 00:32:11.000 --> 00:32:15.000 I think this is - there is an interesting pedagogical 00:32:15.000 --> 00:32:17.000 00:32:17.000 --> 00:32:20.000 debate going on about this, about 00:32:20.000 --> 00:32:21.000 whether 00:32:21.000 --> 00:32:22.000 00:32:22.000 --> 00:32:24.000 it's better to first know how to implement these things and then get to 00:32:24.000 --> 00:32:27.000 use them, or to use them and then later know how to implement them. 00:32:27.000 --> 00:32:30.000 And I liken it to a little bit if you think about some things we do 00:32:30.000 --> 00:32:33.000 very clearly one way or the other in our curriculum, and it's interesting to think about 00:32:33.000 --> 00:32:34.000 why. 00:32:34.000 --> 00:32:37.000 That when you learn, for example, arithmetic as a 00:32:37.000 --> 00:32:38.000 primary schooler, 00:32:38.000 --> 00:32:41.000 they don't give you a calculator and say, here, go do some division and multiplication, 00:32:41.000 --> 00:32:43.000 and then later try to teach you long division. 00:32:43.000 --> 00:32:46.000 You'll never do it. You'll be like, why would I ever do this, this little box 00:32:46.000 --> 00:32:48.000 does it for me, the black box. 00:32:48.000 --> 00:32:52.000 So in fact they drill you on your multiplication tables and 00:32:52.000 --> 00:32:56.000 your long division long before they let you touch a calculator, 00:32:56.000 --> 00:33:00.000 which I think is one way of doing it. And, so - and for example, it's like 00:33:00.000 --> 00:33:03.000 we could do that with you, make you do it the kind of painful way and then 00:33:03.000 --> 00:33:06.000 later say, okay, well here's these way you can avoid 00:33:06.000 --> 00:33:07.000 00:33:07.000 --> 00:33:09.000 being bogged down by that tedium. 00:33:09.000 --> 00:33:12.000 On the other had, think about the way we teach you to drive. 00:33:12.000 --> 00:33:14.000 We do not say, here's a wheel and 00:33:14.000 --> 00:33:15.000 then they say, 00:33:15.000 --> 00:33:18.000 let me tell you a little bit about the combustion engine, you 00:33:18.000 --> 00:33:21.000 know, we give you some spark plugs and 00:33:21.000 --> 00:33:25.000 try to get you to build your car from the ground up. It's like you learn to drive 00:33:25.000 --> 00:33:25.000 00:33:25.000 --> 00:33:26.000 and then if you 00:33:26.000 --> 00:33:29.000 are more interested in that you might learn what's under the hood, how to 00:33:29.000 --> 00:33:31.000 take care of your car, and eventually how to do 00:33:31.000 --> 00:33:35.000 more serious repairs or design of your own care. 00:33:35.000 --> 00:33:38.000 Where I think of that as being a client first model, like you learn how to use the car 00:33:38.000 --> 00:33:41.000 and drive and get places and then if it 00:33:41.000 --> 00:33:45.000 intrigues you, you can dig further to learn more about how the car works. 00:33:45.000 --> 00:33:48.000 So that's definitely - our model is more of the drive one than the arithmetic one that 00:33:48.000 --> 00:33:52.000 it's really nice to be able to drive places first. Like if I - we spent all quarter 00:33:52.000 --> 00:33:54.000 learning how to build a combustion engine and you didn't get to go 00:33:54.000 --> 00:33:55.000 anywhere, 00:33:55.000 --> 00:33:56.000 00:33:56.000 --> 00:33:59.000 I'd feel like you wouldn't have tasted what - where you're trying to get, and why that's 00:33:59.000 --> 00:34:01.000 so fabulous. So 00:34:01.000 --> 00:34:04.000 we will see them first as a client, and you'll get to do really neat things. You'll discover this thing called 00:34:04.000 --> 00:34:08.000 the map where you can put thousands, millions of entries in and 00:34:08.000 --> 00:34:11.000 have instantaneous look-up access on that. 00:34:11.000 --> 00:34:14.000 That you can put these things in a stack or a queue and then have them maintained 00:34:14.000 --> 00:34:15.000 for you and popped back out 00:34:15.000 --> 00:34:19.000 and all the storage of that being managed and the safety of that being managed without 00:34:19.000 --> 00:34:23.000 you having to kinda take any active role in that. That they provide functionality to 00:34:23.000 --> 00:34:24.000 you, that you just get 00:34:24.000 --> 00:34:25.000 to - 00:34:25.000 --> 00:34:29.000 leverage from the get go, and hopefully it will cause you to be 00:34:29.000 --> 00:34:32.000 curious though, like how does it work, why does it work so well, 00:34:32.000 --> 00:34:33.000 and what kind 00:34:33.000 --> 00:34:36.000 of things must happen behind the scenes and under the hood 00:34:36.000 --> 00:34:39.000 so that when we get to that you're actually kind of inspired to know 00:34:39.000 --> 00:34:43.000 how it did it, what it did. 00:34:43.000 --> 00:34:44.000 So I'm gonna tell you about the scanner 00:34:44.000 --> 00:34:48.000 and maybe even tell you a little bit about the vector today, and then we'll do the remaining 00:34:48.000 --> 00:34:52.000 ones on Friday, perhaps even carrying over a little bit into the weeks 00:34:52.000 --> 00:34:55.000 to get ourselves used to what we've got. 00:34:55.000 --> 00:34:58.000 The scanner I kind of separated because the scanner's more of a task based object then it 00:34:58.000 --> 00:34:59.000 is a 00:34:59.000 --> 00:35:02.000 collection or a container for storing things. The scanner's job is to break 00:35:02.000 --> 00:35:07.000 apart input into tokens. To take a string in this case that either you read from 00:35:07.000 --> 00:35:10.000 the file or you got from the user, or you constructed some way, and just tokenize 00:35:10.000 --> 00:35:12.000 it. It's called tokenizer parsec. 00:35:12.000 --> 00:35:13.000 00:35:13.000 --> 00:35:18.000 That this is something a little bit like - strained extraction kind of does this, 00:35:18.000 --> 00:35:22.000 but strained extraction, as I said, isn't very flexible, 00:35:22.000 --> 00:35:23.000 that it doesn't 00:35:23.000 --> 00:35:25.000 make it easy for you to kind of - you 00:35:25.000 --> 00:35:28.000 have to sort of fully anticipate what's coming up on the string. There's not 00:35:28.000 --> 00:35:29.000 anyway you can sort of 00:35:29.000 --> 00:35:31.000 take a look at it and then to decide what to do with it and 00:35:31.000 --> 00:35:35.000 decide how to change your parstring strategy. And scanner has a kind of flexibility that 00:35:35.000 --> 00:35:36.000 lets it be a little bit more 00:35:36.000 --> 00:35:40.000 configurable about what you expect coming up and how it works. 00:35:40.000 --> 00:35:43.000 So the idea is that basically it just takes your input, you know, this line contains ten 00:35:43.000 --> 00:35:44.000 tokens, 00:35:44.000 --> 00:35:46.000 and as you go into a loop saying, 00:35:46.000 --> 00:35:48.000 give me the next token, it will 00:35:48.000 --> 00:35:52.000 sub-string out and return to you this four character string followed by this single 00:35:52.000 --> 00:35:54.000 character space and then this four character line 00:35:54.000 --> 00:35:58.000 and space, and so the default behavior is to extract all the tokens to come up, 00:35:58.000 --> 00:36:03.000 to use white-space and punctuation as delimiters. So it will kind of 00:36:03.000 --> 00:36:05.000 aggregate letters and numbers together 00:36:05.000 --> 00:36:09.000 and then individual spaces and new lines and tabs will come out as single 00:36:09.000 --> 00:36:14.000 character tokens. The parenthesis and dots and number signs would all come out as single character 00:36:14.000 --> 00:36:15.000 tokens, 00:36:15.000 --> 00:36:17.000 00:36:17.000 --> 00:36:20.000 and it just kind of divides it up for you. 00:36:20.000 --> 00:36:21.000 Okay. 00:36:21.000 --> 00:36:25.000 It has fancy options though that let you do things like discard those face 00:36:25.000 --> 00:36:29.000 tokens because you don't care about them. To do things like read 00:36:29.000 --> 00:36:31.000 the fancy number formats. So it can read 00:36:31.000 --> 00:36:35.000 integer formats and real formats, it can do the real format with exponentiation 00:36:35.000 --> 00:36:38.000 in it with leading minus', things like that, 00:36:38.000 --> 00:36:40.000 that 00:36:40.000 --> 00:36:41.000 you can control 00:36:41.000 --> 00:36:44.000 with these setters and getters, like what it is you wanted to do about those things. 00:36:44.000 --> 00:36:48.000 You can it things like when I see an opening quote, I want you to gather everything to 00:36:48.000 --> 00:36:50.000 the closing quote, and so it does kind of 00:36:50.000 --> 00:36:53.000 gather 00:36:53.000 --> 00:36:56.000 phrases out of sequence if that's what you want. And so you have control over 00:36:56.000 --> 00:37:00.000 when and where it decides to do those things that lets you kind of 00:37:00.000 --> 00:37:05.000 handle a variety of kind of parsing and dividing tasks by using the scanner 00:37:05.000 --> 00:37:08.000 to get that job done. So I listed some things you might need, if you're 00:37:08.000 --> 00:37:11.000 reading txt files, you're parsing expressions, you were processing some kind of commands, that 00:37:11.000 --> 00:37:15.000 this scanner is a very handy way to just divide that [inaudible] up. 00:37:15.000 --> 00:37:17.000 You could certainly do this kind of stuff manually, 00:37:17.000 --> 00:37:18.000 for example, 00:37:18.000 --> 00:37:23.000 like using the find on the string and finding those faces and dividing it up, but 00:37:23.000 --> 00:37:25.000 that the idea is just doing that 00:37:25.000 --> 00:37:27.000 in a more convenient way for you 00:37:27.000 --> 00:37:33.000 than you having to handle that process manually. 00:37:33.000 --> 00:37:35.000 This is what its interface looks like. 00:37:35.000 --> 00:37:39.000 So this is a C++ class definition. It looks 00:37:39.000 --> 00:37:42.000 very similar to a Java class definition, but there's a little bit of 00:37:42.000 --> 00:37:46.000 variation in some of the ways the syntax comes through in the class. 00:37:46.000 --> 00:37:48.000 The class being here is scanner, 00:37:48.000 --> 00:37:52.000 the public colon introduces a sequence of where everything from 00:37:52.000 --> 00:37:55.000 here until the next access modifier is 00:37:55.000 --> 00:37:58.000 public. So I don't actually have public repeated again and again on all the 00:37:58.000 --> 00:38:00.000 00:38:00.000 --> 00:38:01.000 individual entries here. 00:38:01.000 --> 00:38:04.000 It tells us that the scanner has a constructor 00:38:04.000 --> 00:38:08.000 that takes no arguments; it just initializes a new empty scanner. 00:38:08.000 --> 00:38:12.000 I'm gonna skip the destructor for a second; I'll come back to it. 00:38:12.000 --> 00:38:15.000 There is a set input member function that you give it the string that you want 00:38:15.000 --> 00:38:15.000 00:38:15.000 --> 00:38:19.000 scanned and then there's these two 00:38:19.000 --> 00:38:21.000 operations that tend to be used in a look where you keep asking are there more 00:38:21.000 --> 00:38:23.000 tokens and if so, give me the next token, so it 00:38:23.000 --> 00:38:27.000 just kind of pulls them out one by one. I picked 00:38:27.000 --> 00:38:31.000 just one of the space - of the particular advanced options to show you 00:38:31.000 --> 00:38:34.000 the format for them. There's actually about six more that deal with 00:38:34.000 --> 00:38:35.000 00:38:35.000 --> 00:38:37.000 some other more obscure things. 00:38:37.000 --> 00:38:38.000 This one is 00:38:38.000 --> 00:38:40.000 how is it you'd like it to deal with spaces, 00:38:40.000 --> 00:38:44.000 when you see face tokens, should they be returned as ordinary tokens or should you 00:38:44.000 --> 00:38:48.000 just discard them entirely and not even bother with them? 00:38:48.000 --> 00:38:51.000 The default is what's called preserve spaces, so it really does return them, so if 00:38:51.000 --> 00:38:54.000 you ask and there's only spaces left in the file, it will say there are more tokens 00:38:54.000 --> 00:38:58.000 and as you call the next token we'll return those spaces as individual tokens. 00:38:58.000 --> 00:39:01.000 If you instead have set the space option of ignore spaces, then it will just 00:39:01.000 --> 00:39:05.000 skip over all of those, and if all that was left in the file was white space 00:39:05.000 --> 00:39:07.000 when you ask for more tokens, it will say no. 00:39:07.000 --> 00:39:10.000 And when you ask for a token and there's some spaces leading up to 00:39:10.000 --> 00:39:15.000 something it will just skip right over those and return the next non-space token. 00:39:15.000 --> 00:39:19.000 There's a variety of these other ones that exist 00:39:19.000 --> 00:39:23.000 that handle the floating point and the double quote and other kind of 00:39:23.000 --> 00:39:25.000 fancy behaviors. 00:39:25.000 --> 00:39:29.000 There's one little detail I'll show you that's a C++ ism that isn't 00:39:29.000 --> 00:39:31.000 - doesn't really have a Java analog, 00:39:31.000 --> 00:39:34.000 which is the constructor which is used as the initialization function for a 00:39:34.000 --> 00:39:35.000 class 00:39:35.000 --> 00:39:36.000 has a 00:39:36.000 --> 00:39:38.000 corresponding destructor. 00:39:38.000 --> 00:39:41.000 Every class has the option of doing this. 00:39:41.000 --> 00:39:41.000 That is 00:39:41.000 --> 00:39:45.000 the - kind of when the object is being created, the constructor is being called. When the 00:39:45.000 --> 00:39:50.000 object is being de-allocated or destroyed, going out of scope, the destructor is 00:39:50.000 --> 00:39:51.000 called. 00:39:51.000 --> 00:39:54.000 And the pairing allows sort of the constructor to do any kind of set up that needs to be 00:39:54.000 --> 00:39:58.000 done and the destructor to do any kind of tear down that needs to be done. 00:39:58.000 --> 00:40:01.000 In most cases there's not that much that needs to be there, but 00:40:01.000 --> 00:40:06.000 it is part of the mechanism that allows all classes to have an option kind of at 00:40:06.000 --> 00:40:09.000 birth and death to do what it needs to do. For example, my file 00:40:09.000 --> 00:40:10.000 stream 00:40:10.000 --> 00:40:13.000 object, when you - 00:40:13.000 --> 00:40:16.000 when it goes away, closes it file automatically. So it's a place where the 00:40:16.000 --> 00:40:24.000 destructor gets used to do cleanup as that object is no longer valid. 00:40:24.000 --> 00:40:25.000 So a little bit of 00:40:25.000 --> 00:40:26.000 scanner 00:40:26.000 --> 00:40:28.000 code 00:40:28.000 --> 00:40:32.000 showing kind of the most common access pattern, is you declare the 00:40:32.000 --> 00:40:37.000 scanner. So at this point the scanner is empty, it has no contents to scan. 00:40:37.000 --> 00:40:39.000 Before I start pulling stuff out of it, 00:40:39.000 --> 00:40:42.000 I'm typically gonna call a set input on it, passing some string. In this case the 00:40:42.000 --> 00:40:46.000 string I'm passing is the one that was entered by the user, using getline. 00:40:46.000 --> 00:40:48.000 And then the 00:40:48.000 --> 00:40:51.000 ubiquitous loop that says well while the scanner has more tokens, get the next 00:40:51.000 --> 00:40:52.000 token. 00:40:52.000 --> 00:40:55.000 And in this case I'm not even actually paying attention to what those tokens are, I'm 00:40:55.000 --> 00:40:56.000 just counting them. 00:40:56.000 --> 00:40:59.000 So this one is kind of a 00:40:59.000 --> 00:41:03.000 very simple access that just says just call the next token as many times as you can 00:41:03.000 --> 00:41:04.000 until there 00:41:04.000 --> 00:41:10.000 are no more tokens to pull out. Way in the back? [Inaudible] I 00:41:10.000 --> 00:41:11.000 mean, like 00:41:11.000 --> 00:41:16.000 in the beginning when it says scanner, scanner, do we write scanner scanner = new 00:41:16.000 --> 00:41:17.000 scanner () or [inaudible]? 00:41:17.000 --> 00:41:19.000 Yes. 00:41:19.000 --> 00:41:22.000 Not exactly. So that's a very good example of like where Java and C++ are gonna 00:41:22.000 --> 00:41:25.000 conspire to trip you up just a little bit, 00:41:25.000 --> 00:41:30.000 that in Java objects were always printed using the syntax of new. You say new 00:41:30.000 --> 00:41:33.000 this thing, and in fact that actually does an allocation 00:41:33.000 --> 00:41:35.000 out in what's called the heap 00:41:35.000 --> 00:41:37.000 of that object and then from there you use it. 00:41:37.000 --> 00:41:40.000 In C++ you actually don't have to put things in the heap, and in fact 00:41:40.000 --> 00:41:43.000 we will rarely put things in the heap, and that's what new is for. 00:41:43.000 --> 00:41:47.000 So we're gonna use the stack to allocate them. So when I say scanner scanner, 00:41:47.000 --> 00:41:50.000 that really declares a scanner object right there 00:41:50.000 --> 00:41:53.000 and in this case there are no [inaudible] my constructor, so I don't have anything in 00:41:53.000 --> 00:41:56.000 parenths. If there were some arguments I would put parenths and put the 00:41:56.000 --> 00:41:57.000 information there, 00:41:57.000 --> 00:42:01.000 but the constructor is being called even with out this new. New actually is 00:42:01.000 --> 00:42:04.000 more about where the memory comes from. The constructor is called regardless of 00:42:04.000 --> 00:42:07.000 where the memory came from. And so this is the mechanism of C++ to get 00:42:07.000 --> 00:42:11.000 yourself an object tends to be, say the class name, say the name of the variable. 00:42:11.000 --> 00:42:14.000 If you have arguments for the constructor, they will go in parenths 00:42:14.000 --> 00:42:16.000 after the variable's name. 00:42:16.000 --> 00:42:18.000 So if scanner had 00:42:18.000 --> 00:42:20.000 something, I would be putting it right here, 00:42:20.000 --> 00:42:25.000 open parenth, yada, yada. 00:42:25.000 --> 00:42:27.000 So that's a little 00:42:27.000 --> 00:42:30.000 C++/Java 00:42:30.000 --> 00:42:32.000 difference. Oh, that's good. Question over 00:42:32.000 --> 00:42:35.000 here? 00:42:35.000 --> 00:42:37.000 When do we have to use the destructor? 00:42:37.000 --> 00:42:41.000 So typically you will not ever make a call that explicitly calls the 00:42:41.000 --> 00:42:43.000 destructor. It happens for you automatically. So you're - [inaudible] you're gonna 00:42:43.000 --> 00:42:47.000 see it in the interface as part of the completeness of the class it, here's how I 00:42:47.000 --> 00:42:49.000 set up, here's how I tear down. 00:42:49.000 --> 00:42:51.000 When we start implementing classes we'll have a reason to think more seriously about 00:42:51.000 --> 00:42:55.000 what goes in the destructor. But now you will never explicitly call it. Just know that 00:42:55.000 --> 00:42:57.000 it automatically gets called for you. 00:42:57.000 --> 00:43:01.000 The constructor kinda gets automatically called; the destructor gets automatically called, so 00:43:01.000 --> 00:43:04.000 just know that they're there. One 00:43:04.000 --> 00:43:08.000 of the things that's - I just want to encourage you not to get too 00:43:08.000 --> 00:43:11.000 bogged down in is that there's a lot of syntax to C++. I'm trying to give 00:43:11.000 --> 00:43:15.000 you the important parts that are going to matter early on, and we'll see more and 00:43:15.000 --> 00:43:16.000 more as we go through. 00:43:16.000 --> 00:43:18.000 Don't let it get you too overwhelmed, the feeling of it's 00:43:18.000 --> 00:43:21.000 almost but not quite like Java and it's going to make me crazy. 00:43:21.000 --> 00:43:25.000 Realize that 00:43:25.000 --> 00:43:27.000 there's just a little bit of differences that you kinda got to absorb, and once you 00:43:27.000 --> 00:43:30.000 get your head around them actually you will find yourself very able to 00:43:30.000 --> 00:43:33.000 express yourself without getting too tripped up by it. But it's just at the beginning I'm sure 00:43:33.000 --> 00:43:35.000 it feels like you've got this big list of here's a thousand things that are a 00:43:35.000 --> 00:43:37.000 little bit different that - 00:43:37.000 --> 00:43:41.000 and it will not be long before it will feel like your native language, so 00:43:41.000 --> 00:43:46.000 hang in there with us. 00:43:46.000 --> 00:43:47.000 So 00:43:47.000 --> 00:43:50.000 I wanted to show you the vector before we get done today and then we'll 00:43:50.000 --> 00:43:55.000 have a lot more chance to talk about this on Friday. That the other six 00:43:55.000 --> 00:43:57.000 classes that come in [inaudible] class library 00:43:57.000 --> 00:44:00.000 are all container classes. So containers are these things like they're buckets 00:44:00.000 --> 00:44:04.000 or shells or bags. They hold things for you. You stick things into the 00:44:04.000 --> 00:44:07.000 container and then later you can retrieve them. 00:44:07.000 --> 00:44:11.000 This turns out to be the most common need in all programs. If you look 00:44:11.000 --> 00:44:14.000 at all the things programs do, [inaudible] manipulating information, where are 00:44:14.000 --> 00:44:18.000 they putting that information, where are they storing it? 00:44:18.000 --> 00:44:22.000 One of the sorts of obvious needs is something that is just kind of a 00:44:22.000 --> 00:44:25.000 linear collection. I need to put together the 100 student that are in 00:44:25.000 --> 00:44:29.000 this class in a list, well what do I do - what do I use to do that? 00:44:29.000 --> 00:44:33.000 There is a build in kind of raw array, or primitive array in C++. I'm not 00:44:33.000 --> 00:44:35.000 even gonna show it to you right now. 00:44:35.000 --> 00:44:37.000 The truth is 00:44:37.000 --> 00:44:42.000 it's functional, it does kinda what it sets out to do, but it's very weak. 00:44:42.000 --> 00:44:44.000 It has constraints on how big it is 00:44:44.000 --> 00:44:48.000 and how it's access to it is. For example, you can make an array that has 10 members 00:44:48.000 --> 00:44:51.000 and then you can axe the 12th member or the 1,500th member 00:44:51.000 --> 00:44:55.000 without any good error reporting from either the compiler or the runtime 00:44:55.000 --> 00:44:55.000 system. 00:44:55.000 --> 00:44:58.000 That it's designed for kind of to be a professional's tool and it's very efficient, 00:44:58.000 --> 00:45:00.000 but it's not very safe. 00:45:00.000 --> 00:45:04.000 It doesn't have any convenience attached to it whatsoever. If you have a - you 00:45:04.000 --> 00:45:07.000 create a ten number array and later you decide you need to put 12 things into 00:45:07.000 --> 00:45:07.000 it, 00:45:07.000 --> 00:45:11.000 then your only recourse is to go create a new 12 number array and copy over 00:45:11.000 --> 00:45:13.000 those ten things 00:45:13.000 --> 00:45:16.000 and get rid of your old array and make a totally new one, that you can't take the 00:45:16.000 --> 00:45:18.000 one you have and just grow it 00:45:18.000 --> 00:45:19.000 00:45:19.000 --> 00:45:20.000 in the standard language. 00:45:20.000 --> 00:45:23.000 So we'll come back to see it because it turns out there's some reasons we're gonna need to 00:45:23.000 --> 00:45:27.000 know how it works. But for now if you say if I needed to make a list what I want 00:45:27.000 --> 00:45:28.000 to use is the vector. 00:45:28.000 --> 00:45:31.000 So we have a vector class 00:45:31.000 --> 00:45:32.000 in our class library 00:45:32.000 --> 00:45:36.000 that just solves this problem of you need to collect up this sequence of 00:45:36.000 --> 00:45:39.000 things, a bunch of scores on a test, 00:45:39.000 --> 00:45:41.000 a bunch of students who are in a class, 00:45:41.000 --> 00:45:44.000 a bunch of name 00:45:44.000 --> 00:45:46.000 that are being invited to a party. 00:45:46.000 --> 00:45:50.000 And what it does for you is the things that array does but with safety 00:45:50.000 --> 00:45:52.000 and convenience built into it. 00:45:52.000 --> 00:45:55.000 So it does bounds checking. If you created a vector and you put ten things 00:45:55.000 --> 00:45:56.000 into it, 00:45:56.000 --> 00:45:59.000 then you can ask for the zero through 9th entries, but you cannot ask 00:45:59.000 --> 00:46:02.000 for the 22nd entry, it will raise an error and 00:46:02.000 --> 00:46:05.000 it will use that error function, you will get a big red error message, you will not 00:46:05.000 --> 00:46:07.000 00:46:07.000 --> 00:46:09.000 bludgeon on unknowingly. 00:46:09.000 --> 00:46:12.000 You can add things and insert them and then remove them. So I can go into the array and 00:46:12.000 --> 00:46:15.000 say I'd like to put something in slot zero, it will shuffle everything over and make 00:46:15.000 --> 00:46:19.000 that space. If I say delete the element that's at zero it will move everything 00:46:19.000 --> 00:46:21.000 down. So it just does all this kind of handling of 00:46:21.000 --> 00:46:24.000 keeping the integrity of the list 00:46:24.000 --> 00:46:26.000 and its ordering maintained 00:46:26.000 --> 00:46:28.000 on your behalf. 00:46:28.000 --> 00:46:30.000 It also does all the 00:46:30.000 --> 00:46:33.000 management of how much storage space is needed. So if I put ten things into 00:46:33.000 --> 00:46:36.000 the vector and I put the 11th or the 12th or the - add 00:46:36.000 --> 00:46:37.000 100 more, 00:46:37.000 --> 00:46:39.000 it knows how to make the space necessary for it. 00:46:39.000 --> 00:46:42.000 Behind the scenes it's figuring out where I can get that space and how to take 00:46:42.000 --> 00:46:46.000 care of it. It always knows what count it has and what's going on there, but 00:46:46.000 --> 00:46:50.000 its doing this on our behalf in a way that that rawray just does not, that becomes 00:46:50.000 --> 00:46:55.000 very tedious and error prone if it's our responsibility to deal with it. 00:46:55.000 --> 00:46:59.000 So what the vector is kind of running, it's an instruction. And this is a key word for us in 00:46:59.000 --> 00:47:01.000 things that we're going to be talking about this quarter 00:47:01.000 --> 00:47:01.000 is that 00:47:01.000 --> 00:47:03.000 what you really wanted was a list. 00:47:03.000 --> 00:47:07.000 I want a list of students and I want to be able to put it in sorted order or 00:47:07.000 --> 00:47:08.000 find this person or print them. 00:47:08.000 --> 00:47:11.000 The fact that where the memory came from and how it's keeping track of is really 00:47:11.000 --> 00:47:15.000 a tedious detail that I'd rather not have to deal with. And that's exactly 00:47:15.000 --> 00:47:17.000 what the vector's gonna do for you, is make it so 00:47:17.000 --> 00:47:21.000 you store things and the storage is somebody else's problem. 00:47:21.000 --> 00:47:23.000 You use a list, 00:47:23.000 --> 00:47:27.000 you get an abstraction. 00:47:27.000 --> 00:47:30.000 How that - there's one little quirk, and this is 00:47:30.000 --> 00:47:33.000 not so startling to those of you who have 00:47:33.000 --> 00:47:35.000 worked on a recent version of Java, 00:47:35.000 --> 00:47:38.000 is in order to make the vector generally useful, 00:47:38.000 --> 00:47:40.000 it cannot store just one type of thing. 00:47:40.000 --> 00:47:43.000 That you can't make a vector that stores [inaudible] and 00:47:43.000 --> 00:47:46.000 service everyone's needs, that it has to be able to hold vectors of doubles 00:47:46.000 --> 00:47:49.000 or vectors of strings or vectors of student structures 00:47:49.000 --> 00:47:51.000 equally well. 00:47:51.000 --> 00:47:55.000 And so the way the vector class is actually supplied is using a 00:47:55.000 --> 00:47:58.000 feature in the C++ language called templates where 00:47:58.000 --> 00:48:02.000 the vector describes what it's storing using a placeholder. It says, well this is a 00:48:02.000 --> 00:48:04.000 vector of something and 00:48:04.000 --> 00:48:08.000 when you put these things in they all have to be the same type of thing 00:48:08.000 --> 00:48:11.000 and when you get one out you'll get the thing you put in, 00:48:11.000 --> 00:48:14.000 but I will not commit to, and the interface saying it's always an integer, 00:48:14.000 --> 00:48:16.000 it's always a double. 00:48:16.000 --> 00:48:19.000 It's left open and then the client has to describe what they want when they're 00:48:19.000 --> 00:48:20.000 ready to use it. 00:48:20.000 --> 00:48:24.000 So this is like the Java generics. When you're using an array list you said, well what 00:48:24.000 --> 00:48:27.000 kind of things am I sticking in my array list, and then that way 00:48:27.000 --> 00:48:34.000 the compiler can keep track of it for you and help you to use it correctly. 00:48:34.000 --> 00:48:36.000 The interpart of this kinda 00:48:36.000 --> 00:48:38.000 looks as 00:48:38.000 --> 00:48:40.000 we've seen before. It's a class vector, 00:48:40.000 --> 00:48:42.000 it has a constructor and destructor 00:48:42.000 --> 00:48:44.000 and it has some operations that 00:48:44.000 --> 00:48:46.000 return things like the number of elements that you can find out whether it 00:48:46.000 --> 00:48:50.000 has zero elements, you can get the element at index, you can set the element at 00:48:50.000 --> 00:48:51.000 index, 00:48:51.000 --> 00:48:54.000 you can add, insert and remove 00:48:54.000 --> 00:48:55.000 things within there. 00:48:55.000 --> 00:48:56.000 00:48:56.000 --> 00:48:59.000 The one thing that's a little bit unusual about it is that every time it's 00:48:59.000 --> 00:49:02.000 talking about the type of something that's going into the vector or 00:49:02.000 --> 00:49:04.000 something that's coming out of the vector, 00:49:04.000 --> 00:49:06.000 it uses this elem type 00:49:06.000 --> 00:49:11.000 which traces its origin back to this template header up there, 00:49:11.000 --> 00:49:14.000 that is the clue to you that the vector 00:49:14.000 --> 00:49:15.000 doesn't 00:49:15.000 --> 00:49:19.000 commit to I'm storing ants, I'm storing doubles, I'm storing strings, it stores some 00:49:19.000 --> 00:49:22.000 generic elem type thing, 00:49:22.000 --> 00:49:26.000 which went the client is ready to create a vector, they will have to make 00:49:26.000 --> 00:49:30.000 that commitment and say this vector is gonna hold doubles, this vector is 00:49:30.000 --> 00:49:31.000 gonna hold ants, 00:49:31.000 --> 00:49:34.000 and from that point forward that vector knows that the 00:49:34.000 --> 00:49:39.000 getat on a vector of ants returns something of n type. And then add on a vector of nts 00:49:39.000 --> 00:49:41.000 expects a perimeter of n type, 00:49:41.000 --> 00:49:44.000 which is distinct from a vector of strings or a vector 00:49:44.000 --> 00:49:45.000 of doubles. So I'll 00:49:45.000 --> 00:49:49.000 show you a little code and we'll have to just really talk about this more deeply on 00:49:49.000 --> 00:49:49.000 Friday. 00:49:49.000 --> 00:49:51.000 A 00:49:51.000 --> 00:49:54.000 little bit of this in text for how I make a vector of [inaudible] how I make a vector of 00:49:54.000 --> 00:49:56.000 strings, and 00:49:56.000 --> 00:49:56.000 then 00:49:56.000 --> 00:49:58.000 some of the things that you could try to mix up 00:49:58.000 --> 00:50:01.000 that the template will actually 00:50:01.000 --> 00:50:02.000 not let you get away with, 00:50:02.000 --> 00:50:05.000 mixing those types. So 00:50:05.000 --> 00:50:07.000 we'll see this on Friday, so don't worry, 00:50:07.000 --> 00:50:08.000 00:50:08.000 --> 00:50:10.000 there will be time to look at it 00:50:10.000 --> 00:50:17.000 and meanwhile good luck getting your compiler set up.