Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
C++ For Dummies (2004) [eng].pdf
Скачиваний:
84
Добавлен:
16.08.2013
Размер:
8.09 Mб
Скачать

320 Part V: Optional Features

4

5

6

Press any key to continue . . .

Reading Directly from a Stream

The inserter and extracter operators provide a convenient mechanism for reading formatted input. However, there are times when you just want to say, “give it to me, I don’t care what the format is.” There are two methods that are useful in this context. The function getline() returns a string of characters up until some terminator — the default is a newline. getline() strips off the terminator but makes no other attempt to reformat or otherwise interpret the input.

The member function read() is even more fundamental. This function reads the number of characters that you specify, or less if the program encounters an end-of-file. The function gcount() always returns the actual number of characters read.

The following program uses both getLine() and read() to open a file with random contents and spit them out to the display.

// FileInput - read blocks of data from a file #include <fstream>

#include <iostream> using namespace std;

ifstream* openFile(istream& input)

{

for(;;)

{

//open the file specified by the user char fileName[80];

cout << “Enter the name of a file” << endl;

//read input from the user in such a way

//that the input can’t overflow the buffer input.getline(fileName, 80);

//open file for reading; don’t create the file //if it isn’t there

ifstream* pFileStream = new ifstream(fileName); if (pFileStream->good())

{

return pFileStream;

}

cerr << “Couldn’t find “ << fileName << endl;

}

Chapter 24: Using Stream I/O 321

return 0;

}

int main(int nNumberofArgs, char* pszArgs[])

{

// get a file stream

ifstream* pFileStream = openFile(cin);

// read blocks of data 80 bytes at a time char buffer[80];

while (!pFileStream->eof() && pFileStream->good())

{

//read a block - 80 is the max but gcount() returns

//the actual number of bytes read

pFileStream->read(buffer, 80);

int noBytes = pFileStream->gcount();

// do something with the block for(int i = 0; i < noBytes; i++)

{

cout << buffer[i];

}

}

system(“PAUSE”); return 0;

}

The FileInput program first invokes openFile() to open a file. This version demonstrates two interesting aspects. First, the function reads from an istream object in the same way that it would read from cin. In fact, the main() function passes the cin object. However, a function that uses an arbitrary istream object can read from input files without modification.

The openFile() uses the getline() member function to read a string. One of the arguments to the function is the size of the buffer. getline() will not read beyond this point. Thus, getline(fileName, 80) reads up to the end of the line but not more than 80 characters and stores the result into the character buffer fileName.

Using the getline() function to read keyboard input is safer than using the extractor when reading into a simple character array — the extractor can read beyond the end of the array. The getline() function will not read more than the number of characters you specify.

The main() function reads 80 byte blocks from the file stream object returned from openFile(). The program checks the actual number of characters read using the gcount() function. The number returned from gcount() will never be more than the 80 bytes specified in the call to read() and will only be less when the program reaches the end-of-file. The program uses the conventional inserter to display the characters read.

322 Part V: Optional Features

The FileInput program simply outputs the contents of the file that you specify as shown in the following sample run:

Enter the name of a file MyName.txt

Stephen Davis is suave and handsome and definitely not balding prematurely Press any key to continue . . .

What’s Up with endl?

Most programs in this book terminate an output stream by inserting the object endl. However, some programs include a \n within the text to output a newline. What’s the deal?

The \n is, in fact, the newline character. The expression cout << “First line\nSecond line; outputs two lines. The endl object outputs a newline, but continues one step further.

Disks are slow devices. Writing to disk more often than necessary will slow your program down considerably. To avoid this, the fstream class collects up output into an internal buffer. The class writes the contents to disk when the buffer is full (this is known as flushing the buffer). The endl object auto­ matically flushes the output buffer. The member function flush() flushes the output buffer without tacking a newline onto the end.

Using the strstream Subclasses

The stream classes give the programmer mechanisms for easily breaking input among int, float, and char array variables (among others). A set of so-called “string stream” classes allow the program to “read” from an array of characters in memory. The classes istringstream and ostringstream are defined in the include file sstream.

The older versions of these are classes are istrstream and ostrstream defined in the include file strstream.

The string stream classes have the same semantics as the corresponding file based classes. This is demonstrated in the following StringStream program that parses account information from a file:

// StringStream - read and parse the contents of a file #include <fstream>

#include <sstream> #include <iostream>

Chapter 24: Using Stream I/O 323

using namespace std;

// parseAccountInfo - read a passed buffer as if it were

//

an actual file - read the following

//

format:

//

name, account balance

//

return true if all worked well

bool parseString(char* pString, char* pName, int arraySize,

{

long& accountNum, double& balance)

 

//associate an istrstream object with the input

//character string

istringstream inp(pString);

//read up to the comma separator inp.getline(pName, arraySize, ‘,’);

//now the account number

inp >> accountNum;

//and the balance inp >> balance;

//return the error status return !inp.fail();

}

int main(int nNumberofArgs, char* pszArgs[])

{

// get a file stream

ifstream* pFileStream = new ifstream(“Accounts.txt”); if (!pFileStream->good())

{

cout << “Can’t open Accounts.txt” << endl; return 0;

}

// read a line out of file, parse it and display results for(;;)

{

// add a divider

cout << “=============================” << endl;

//read a buffer char buffer[256];

pFileStream->getline(buffer, 256); if (pFileStream->fail())

{

break;

}

//parse the individual fields char name[80];

long accountNum;

324 Part V: Optional Features

double balance;

bool result = parseString(buffer, name, 80, accountNum, balance);

//output the result cout << buffer << “\n”; if (result == false)

{

cout << “Error parsing string\n”; continue;

}

cout << “name = “ << name << “,”

<<“account = “ << accountNum << “, “

<<“balance = “ << balance << endl;

//put the fields back together in a different

//order (inserting the ‘ends’ makes sure the

//buffer is null terminated

ostringstream out; out << name << “, “

<<balance << “ “

<<accountNum << ends;

//output the result - istringstream also works with

//the string class but I have been staying with

//character arrays until the discussion of the templates

string oString = out.str(); cout << oString << “\n” << endl;

}

system(“PAUSE”); return 0;

}

This program begins by opening a file called Accounts.txt containing account information in the format of: name, accountNumber, balance,\n. Assuming that the file was opened successfully, the program enters a loop, reading lines until the contents of the file are exhausted. The call to getline() reads up to the default newline terminator. The program passes the line just read to the function parseString().

parseString() associates an istringstream object with the character string. The program reads characters up to the ‘,’ (or the end of the string buffer) using the getline() member function. The program then uses the conventional extractors to read accountNum and balance. The reads from inp will have worked if inp.fail() returns a false.

After the call to parseString(), main() outputs the buffer read from the file followed by the parsed values. It then uses the ostringstream class to reconstruct a string object with the same data but a different format.