Download presentation
Presentation is loading. Please wait.
Published byGerard Mills Modified over 8 years ago
1
Lecture Overview ● Unix: ● C++: – Streams and File I/O
2
Streams ● A stream is a flow of data to/from your program. ● The notion of a stream is that the program is unaware of the source/destination of the data on the stream; it only know bytes come in/out. ● We have already seen two streams in action: cin and cout. – Input stream (from the keyboard) – Output stream (to the monitor)
3
Streams ● When you use cin and cout, you are simply taking data off/putting data on a stream. ● File input and output will be done almost identically: – The main difference will be that you have to open a file stream first.
4
File Input/Output ● To send output to or read from a file, you first need to connect the file to an appropriate stream. ● The stream definitions needed are in library (std namespace). – To read: use the class ifstream – To write: use the class ofstream
5
How to open a file? ● To connect a file to one of these streams, you need to: – Declare a stream ifstream inFile; ofstream outFile; – Connect a specific file inFile.open(“filename”); outFile.open(“filenameTwo”); – Read from and to from the streams like you would cin and cout, with > – When finished, close the streams inFile.close(); outfile.close();
6
File Opening Caveat ● If you open a file the way you just saw, it either creates it from scratch, or erases anything in a file that already exists. ● To avoid this and instead append output, use this opening: outStream.open(“importantFile”, ios::app);
7
Reading from a file ● You can treat the file stream the same as you would treat cin! ● Just use the extraction operator (>>) to get information out. instream >> var1 >> var2; ● Like using cin, this will ignore whitespace. (Though you won't have to wait for a return key press.)
8
Writing to a file ● Again, much like using cout. ● Use the insertion operator to put data into file (instead of the screen) outFile << “The number is “ << intVar << endl;
9
Pretty Easy! ● So, you can treat files more or less like standard in and standard out. ● Just remember for general usage: – declare, open, use, close.
10
Another ways to declare file streams ● Using the constructor style (more on this when we do classes) – ifstream inFile(“filename.txt”); – ofstream outFile(“writingFile”); – ofstream outFile(“writingFile”, ios::app); ● This lets you declare and open the file in one step.
11
Character I/O ● We've only discussed > so far for working with streams so far, both of which ignore whitespace. ● How can you read in single characters? – Use get! char input; cin.get(input); inFile.get(input); ● You can mix and match get and >>, but be aware they can behave strangely together, since >> pulls off input up until the next whitespace.
12
Character I/O ● You can output characters much the same way, with put: cout.put('a'); outFile.put(charVar);
13
Character I/O ● You can also get C-strings (i.e. Character arrays) from input streams: char cArray[80]; cin.getline(cArray); inFile.getline(cArray);
14
Character I/O ● Other input stream functions: – inStream.putback(char a): put character a as the next character in the stream. – instream.peek(): returns the next character on the stream without moving the stream forward. – instream.ignore(int num, char a): skip the next num worth of characters or until you see a, whichever comes first.
15
Checking to make sure your file opened correctly ● Once you have opened a file and connected it to a filestream, you can check for success with the function outFile.fail() ● This function will return true if the file did not open properly. instream.open(“stuff.txt”); if(instream.fail()){ cout << “Failure opening file!\n”; exit(1); }
16
Checking for the End of a File ● Two ways to do it. ● 1) Input file streams have a member function which tells you if the end of a file was reached: inStream.get(next) while(! inStream.eof()){ cout << next; instream.get(next); } ● This will let you know that you have hit the end of a file once you have attempted to read past the end of the file.
17
Checking for the end of a file ● The other way to do it is with the >> operator itself. while(inStream >> next){ //stuff with next } ● The read expression returns boolean information regarding the success of the read.
18
Formatting an output stream ● Remember the magic formula from the first day for formatting? ● They are what are known as stream functions. ● These let you change the characteristics of a stream.
19
ostream functions ● setf(ios_Flag): Sets a specified flag ● unsetf(ios_Flag): Unsets a specified flag ● setf(0, ios::floatfield): Resets the flags to default. ● precision(int): Sets the precision for floating point output. ● precision(): Returns the current precision ● width(int): Sets the output width for the next output. ● fill(char): Sets the character to fill the output field with when what is output is smaller than the field.
20
IOS Flags ● There are special flags that control the output format. ● Turning these on or off changes the output. Some examples: – ios::showpos determines if a + should be shown before positive integers. Default is off. – ios::dec determines if integers are output in decimal format. ● There are more on page 530 of the Savitch text.
21
Output Stream Manipulators ● These are ways to use the function in an output line. ● For example, to use width: cout << varX << setw(7) << varY; ● setw is the most common. The others have their own: – setf(ios_flag) is setiosflags(ios_flag) – unsetf(ios_flag) is resetiosflags(ios_flag) – precision(int) is setprecision(int) – width(int) is setw(int) – fill(char) is setfill(char)
22
Saving and restoring flags ● There is a method called flags() that returns a long representing the flag settings. It can also take a long as a parameter and sets the flags accordingly. ● If you wanted to save flag settings, then change and restore them: long flagSettings = outStream.flags(); //Do stuff here to/with outStream outStream.flags(flagSettings); ● You can save precision similarly.
23
Pointers and Dynamic Memory ● I said several times last class how call-by-reference is similar to passing a pointer. ● So, let's talk about pointers and dynamic memory. ● Basic idea – there is a variable type that rather than storing a value, stores information about where a value is kept in memory.
24
Operators to know ● *: This is both the operator to declare a pointer, and the dereferencing operator. int *pointer; // Declares a pointer *pointer = 7; // Access the memory that pointer is pointing to. ● &: Address-of operator. Pre-pending this to a variable gets you the address of that variable. int x, *pointer; pointer = &x; *pointer = 7; cout << x; // This will output 7!
25
What happens in this code? ● Start with this code: int x = 8, y = 9; *p1, *p2; p1 = &x; p2 = &y; ● Let's look at the memory when you do either p1 = p2; *p1 = *p2;
26
How do I allocate my own memory? ● Those of you with C experience may remember malloc. ● Fortunately, we don't need malloc! ● We use the new operator. int *p1 = new int; ● This sets aside memory in the heap for an integer, and then sets the pointer to point to it. ● Technically, you are invoking a constructor – this will be covered in more detail soon.
27
To note about new ● On older compilers, if you called new and there was not enough space on the heap, NULL was returned. ● Newer compilers have programs terminate if they call new and there is not enough space.
28
Pointers can also be passed in to and returned from functions ● Here is a prototype with pointers: int* function(int* pointerArg); ● This accepts a pointer as an argument, and returns one when it completes. ● This is how you will eventually return arrays and other dynamically allocated data.
29
A little bit about pointer style ● Depending on where you use it, the * operator can act differently. – int* p1, p2, p3; will declare three pointers. – double *ptr, x, y; declares one pointer. – *ptr is actually accessing the memory stored. – ptr points to the memory being stored. – void func(char *x); and void func(char* x); are the same. – void func(char); and void func(char*); are not! ● Some people avoid this with typedefs. typedef int* IntPtr; will let you use IntPtr instead of int*.
30
Declaring dynamic arrays ● This is actually very straightforward thanks to new. double *array; array = new double[10]; ● This can be done with typedefs too: typedef double* DblPtr; DblPtr array; array = new double[10];
31
Allocating Dynamic Multi- Dimensional Arrays ● This is where it gets a little tricky. I learned to declare multiple-dimensions like this: int **array2D = new int*[10]; for(int i = 0; i < 10; i++) *array2D[i] = new int[6]; ● You may prefer the typedef method: typedef int* IntArrayPtr; IntArrayPtr *array2D = new IntArrayPtr[10]; for(int i = 0; i < 10; i++) array2D[i] = new int[6]; ● The long and short of it is that you have an array of pointers.
32
Deleting dynamic memory ● If we're done using a variable, it's a good idea to reclaim it's memory on the heap! ● Thus, we have the delete keyword. You can use it on a pointer to reclaim the memory pointed to. int *ptr = new int;... delete ptr; ● Be careful! When you delete, that pointer is now undefined, and so are any other pointers that pointed there! You must make sure that you set ALL pointers that pointed there to NULL, or prevent their dereferencing.
33
Deleting an array ● To delete a dynamically allocated array, just include [] BETWEEN delete and the variable name. int* array = new int[10];.... delete [] array;
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.