Absolute C++ (4th Edition) part 51 ppt

10 311 0
Absolute C++ (4th Edition) part 51 ppt

Đang tải... (xem toàn văn)

Thông tin tài liệu

I/O Streams 507 Display 12.2 Appending to a File 1 //Appends data to the end of the file alldata.txt. 2 #include <fstream> 3 #include <iostream> 4 using std::ofstream; 5 using std::cout; 6 using std::ios; 7 int main( ) 8 { 9 cout << "Opening data.txt for appending.\n"; 10 ofstream fout; 11 fout.open("data.txt", ios::app); 12 fout << "5 6 pick up sticks.\n" 13 << "7 8 ain’t C++ great!\n"; 14 fout.close( ); 15 cout << "End of appending to file.\n"; 16 return 0; 17 } S AMPLE D IALOGUE data.txt (Before program is run) 1 2 bucket my shoe. 3 4 shut the door. data.txt (After program is run) 1 2 bucket my shoe. 3 4 shut the door. 5 6 pick up sticks. 7 8 ain’t C++ great! S CREEN O UTPUT Opening data.txt for appending. End of appending to file. 508 Streams and File I/O Tip A NOTHER S YNTAX FOR O PENING A F ILE Each of the classes ifstream and ofstream has constructors that allow you to specify a file name and sometimes other parameters for opening a file. A few examples will make the syntax clear. The two statements ifstream inStream; inStream.open("infile.txt"); can be replaced by the following equivalent line: ifstream inStream("infile.txt"); The two statements ofstream outStream; outStream.open("outfile.txt"); can be replaced by the following equivalent line: ofstream outStream("outfile.txt"); As our final example, the two lines ofstream outStream; outStream.open("important.txt", ios::app); are equivalent to the following: ofstream outStream("important.txt", ios::app); A PPENDING TO A F ILE If you want to append data to a file so that it goes after any existing contents of the file, open the file as follows. S YNTAX Output_Stream .open( File_Name , ios::app); E XAMPLE ofstream outStream; outStream.open("important.txt", ios::app); I/O Streams 509 Tip C HECK T HAT A F ILE W AS O PENED S UCCESSFULLY A call to open can be unsuccessful for a number of reasons. For example, if you try to open an input file and there is no file with the external name that you specified, then the call to open will fail. As another example, an attempt to open an output file could fail because the file exists and your program (that is, your account) does not have write permission for the file. When such things happen, you may not receive an error message and your program may simply proceed to do something unexpected. Thus, you should always follow a call to open with a test to see whether the call to open was successful, and end the program (or take some other appropriate action) if the call to open was unsuccessful. You can use the member function named fail to test whether or not a stream operation has failed. There is a member function named fail for each of the classes ifstream and ofstream. The fail function takes no arguments and returns a bool value. You should place a call to fail immediately after each call to open; if the call to open fails, the function fail will return true. For example, if the following call to open fails, then the program will output an error message and end; if the call succeeds, the fail function returns false and the program will continue. inStream.open("stuff.txt"); if (inStream.fail( )) { cout << "Input file opening failed.\n"; exit(1); } Display 12.3 contains the program from Display 12.1 rewritten to include tests to see if the input and output files were opened successfully. It processes files in exactly the same way as the pro- gram in Display 12.1. In particular, assuming that the file infile.txt exists and has the contents shown in Display 12.1, the program in Display 12.3 will create the file outfile.txt that is shown in Display 12.1. However, if there were something wrong and one of the calls to open failed, then the program in Display 12.3 would end and send an appropriate error message to the screen. For example, if there were no file named infile.txt, then the call to inStream.open would fail, the program would end, and an error message would be written to the screen. Notice that we used cout to output the error message; this is because we want the error message to go to the screen, as opposed to going to a file. Since this program uses cout to output to the screen (as well as doing file I/O), we have added an include directive for the header file <iostream>. (Actually, your program does not need to have #include <iostream> when your program has #include <fstream>, but it causes no problems to include it, and it reminds you that the program is using screen output in addition to file I/O.) the member function fail 510 Streams and File I/O Display 12.3 File I/O with Checks on open 1 //Reads three numbers from the file infile.txt and writes the sum to the 2 //file outfile.txt. 3 #include <fstream> 4 #include <iostream> 5 #include <cstdlib> //for exit 6 using std::ifstream; 7 using std::ofstream; 8 using std::cout; 9 using std::endl; 10 int main( ) 11 { 12 ifstream inStream; 13 ofstream outStream; 14 inStream.open("infile.txt"); 15 if (inStream.fail( )) 16 { 17 cout << "Input file opening failed.\n"; 18 exit(1); 19 } 20 outStream.open("outfile.txt"); 21 if (outStream.fail( )) 22 { 23 cout << "Output file opening failed.\n"; 24 exit(1); 25 } 26 int first, second, third; 27 inStream >> first >> second >> third; 28 outStream << "The sum of the first 3\n" 29 << "numbers in infile.txt\n" 30 << "is " << (first + second + third) << endl; 31 inStream.close( ); 32 outStream.close( ); 33 return 0; 34 } S AMPLE D IALOGUE (if the file infile.txt does not exist) Input file opening failed. I/O Streams 511 S UMMARY OF F ILE I/O S TATEMENTS In this example the input comes from a file with the name infile.txt, and the output goes to a file with the name outfile.txt. ■ Place the following include directives in your program file: #include <fstream> #include <iostream> #include <cstdlib> Add the following using directives (or something similar): using std::ifstream; using std::ofstream; using std::cout; using std::endl; //if endl is used. ■ Choose a stream name for the input stream and declare it to be a variable of type ifstream. Choose a stream name for the output file and declare it to be of type ofstream. For example: ifstream inStream; ofstream outStream; ■ Connect each stream to a file using the member function open with the external file name as an argument. Remember to use the member function fail to test that the call to open was successful: inStream.open("infile.txt"); if (inStream.fail( )) { cout << "Input file opening failed.\n"; exit(1); } outStream.open("outfile.txt"); if (outStream.fail( )) { cout << "Output file opening failed.\n"; exit(1); } ■ Use the stream inStream to get input from the file infile.txt just like you use cin to get input from the keyboard. For example: inStream >> someVariable >> someOtherVariable; For file I/O For cout For exit 512 Streams and File I/O Self-Test Exercises 1. Suppose you are writing a program that uses a stream called fin, which will be connected to an input file, and a stream called fout, which will be connected to an output file. How do you declare fin and fout? What include directive, if any, do you need to place in your program file? 2. Suppose you are continuing to write the program discussed in the previous exercise and you want your program to take its input from the file stuff1.txt and send its output to the file stuff2.txt. What statements do you need to place in your program in order to connect the stream fin to the file stuff1.txt and to connect the stream fout to the file stuff2.txt? Be sure to include checks to make sure that the openings were successful. 3. Suppose that you are still writing the same program that we discussed in the previous two exercises and you reach the point at which you no longer need to get input from the file stuff1.txt and no longer need to send output to the file stuff2.txt. How do you close these files? 4. Suppose you want to change the program in Display 12.1 so that it sends its output to the screen instead of the file outfile.txt. (The input should still come from the file infile.txt.) What changes do you need to make to the program? 5. A programmer has read half of the lines in a file. What must the programmer do to the file to enable reading the first line a second time? ■ CHARACTER I/O Chapter 9 described character I/O from the keyboard with cin and to the screen with cout. All those details apply equally well to file I/O. Just use an input stream connected to a file in place of cin or an output stream connected to a file in place of cout. In par- ticular, get, getline, putback, peek, and ignore work the same for file input as they do for keyboard input; 1 put works the same for file output as it does for screen output. ■ Use the stream outStream to send output to the file outfile.txt just like you use cout to send output to the screen. For example: outStream << "someVariable = " << someVariable << endl; ■ Close the streams using the function close: inStream.close( ); outStream.close( ); I/O Streams 513 ■ CHECKING FOR THE END OF A FILE A common way of processing an input file is to use a loop that processes data from the file until the end of the file is reached. There are two standard ways to test for the end of a file. The most straightforward way is to use the eof member function. Every input-file stream has a member function called eof that can be used to test for reaching the end of the input file. The function eof takes no arguments, so if the input stream is called fin, then a call to the function eof is written fin.eof( ) This is a Boolean expression that can be used to control a while loop, do-while loop, or an if-else statement. This expression returns true if the program has read past the end of the input file; otherwise, it returns false. Since we usually want to test that we are not at the end of a file, a call to the member function eof is typically used with a not in front of it. Recall that in C++ the symbol ! is used to express not. For example, the entire contents of the file connected to the input stream inStream can be written to the screen with the following while loop: inStream.get(next); while (! inStream.eof( )) { cout << next; inStream.get(next); } The above while loop reads each character from the input file into the char variable next using the member function get, and then it writes the character to the screen. After the program has passed the end of the file, the value of inStream.eof( ) changes from false to true. Thus, (! inStream.eof( )) changes from true to false and the loop ends. Notice that inStream.eof( ) does not become true until the program attempts to read one character beyond the end of the file. For example, suppose the file contains the following (without any newline character after the c): ab c 1 If you have not yet read about getline, putback, peek, or ignore, do not be concerned. They are not used in this chapter, except for one brief reference to ignore at the very end of this chapter. You can ignore that one reference to ignore. eof member function ending an input loop with the eof function If you prefer, you can use cout.put(next) here. 514 Streams and File I/O This is actually the following list of four characters: ab<the newline character ’\n’>c The above loop will read an ’a’ and write it to the screen, then read a ’b’ and write it to the screen, then read the newline character ’\n’ and write it to the screen, and then read a ’c’ and write it to the screen. At that point the loop will have read all the characters in the file. However, inStream.eof( ) will still be false. The value of inStream.eof( ) will not change from false to true until the program tries to read one more character. That is why the above while loop ends with inStream.get(next). The loop needs to read one extra character in order to end the loop. There is a special end-of-file marker at the end of a file. The member function eof does not change from false to true until this end-of-file marker is read. That’s why the previous while loop could read one character beyond what you think of as the last char- acter in the file. However, this end-of-file marker is not an ordinary character and should not be manipulated like an ordinary character. You can read this end-of-file marker, but you should not write it out again. If you write out the end-of-file marker, the result is unpredictable. The system automatically places this end-of-file marker at the end of each file for you. The second way to check for the end of the file is to note (and use) the fact that a read with an extraction operator actually returns a Boolean value. The expression (inStream >> next) returns true if the read was successful and returns false when your code attempts to read beyond the end of the file. For example, the following will read all the numbers in a file of integers connected to the input stream inStream and compute their sum in the variable sum: double next, sum = 0; while (inStream >> next) sum = sum + next; cout << "the sum is " << sum << endl; The above loop may look a bit peculiar, because inStream >> next reads a number from the stream inStream and returns a Boolean value. An expression involving the extraction operator >> is simultaneously both an action and a Boolean condition. 2 If there is another number to be input, then the number is read and the Boolean value true is returned, so the body of the loop is executed one more time. If there are no more numbers to be read in, then nothing is input and the Boolean value false is returned, so the loop ends. In this example the type of the input variable next was 2 Technically, the Boolean condition works this way: The returned value of the operator >> is an input stream reference ( istream& or ifstream&), as explained in Chapter 8. This stream refer- ence is automatically converted to a bool value. The resulting value is true if the stream was able to extract data, and false otherwise. the macho way to test for end of file I/O Streams 515 double, but this method of checking for the end of the file works the same way for other data types, such as int and char. This second method of testing for the end of a file is preferred by many C++ pro- grammers for what appears to be a cultural reason. It was commonly used in C pro- gramming. It is also possible that, depending on implementation details, this second method might be a bit more efficient. In any event, whether you use this second method or not, you need to know it so you can understand other programmer’s code. An illustration of using the eof member function is given in Display 12.4. Display 12.4 Checking for the End of a File (part 1 of 2) 1 2 //Copies story.txt to numstory.txt, 3 //but adds a number to the beginning of each line. 4 //Assumes story.txt is not empty. 5 #include <fstream> 6 #include <iostream> 7 #include <cstdlib> 8 using std::ifstream; 9 using std::ofstream; 10 using std::cout; 11 int main( ) 12 { 13 ifstream fin; 14 ofstream fout; 15 fin.open("story.txt"); 16 if (fin.fail( )) 17 { 18 cout << "Input file opening failed.\n"; 19 exit(1); 20 } 21 fout.open("numstory.txt"); 22 if (fout.fail( )) 23 { 24 cout << "Output file opening failed.\n"; 25 exit(1); 26 } 516 Streams and File I/O Self-Test Exercises 6. What output will be produced when the following lines are executed, assuming the file list.txt contains the data shown (and assuming the lines are embedded in a complete and correct program with the proper include and using directives)? ifstream ins; ins.open("list.txt"); Display 12.4 Checking for the End of a File (part 2 of 2) 27 28 char next; 29 int n = 1; 30 fin.get(next); 31 fout << n << " "; 32 while (! fin.eof( )) 33 { 34 fout << next; 35 if (next == '\n') 36 { 37 n++; 38 fout << n << ' '; 39 } 40 fin.get(next); 41 } 42 fin.close( ); 43 fout.close( ); 44 return 0; 45 } S AMPLE D IALOGUE There is no output to the screen and no input from the keyboard. story.txt (Not changed by program) The little green men had pointed heads and orange toes with one long curly hair on each toe. numstory.txt (After program is run) 1 The little green men had 2 pointed heads and orange 3 toes with one long curly 4 hair on each toe. Notice that the loop ends with a read (fin.get). The member function fin.eof does not return true until your program tries to read one more character after reading the last character in the file. . fout.open("data.txt", ios::app); 12 fout << "5 6 pick up sticks. " 13 << "7 8 ain’t C++ great! "; 14 fout.close( ); 15 cout << "End of appending to file. "; . door. data.txt (After program is run) 1 2 bucket my shoe. 3 4 shut the door. 5 6 pick up sticks. 7 8 ain’t C++ great! S CREEN O UTPUT Opening data.txt for appending. End of appending to file. 508 Streams. opened successfully. It processes files in exactly the same way as the pro- gram in Display 12.1. In particular, assuming that the file infile.txt exists and has the contents shown in Display 12.1,

Ngày đăng: 04/07/2014, 05:21

Tài liệu cùng người dùng

Tài liệu liên quan