8.3.1. Using an istringstream

An istringstream is often used when we have some work to do on an entire line, and other work to do with individual words within a line.

As one example, assume we have a file that lists people and their associated phone numbers. Some people have only one number, but others have several—a home phone, work phone, cell number, and so on. Our input file might look like the following:

morgan 2015552368 8625550123
drew 9735550130
lee 6095550132 2015550175 8005550000

Each record in this file starts with a name, which is followed by one or more phone numbers. We’ll start by defining a simple class to represent our input data:

// members are public by default; see § 7.2 (p. 268)
struct PersonInfo {
    string name;
    vector<string> phones;
};

Objects of type PersonInfo will have one member that represents the person’s name and a vector holding a varying number of associated phone numbers.

Our program will read the data file and build up a vector of PersonInfo. Each element in the vector will correspond to one record in the file. We’ll process the input in a loop that reads a record and then extracts the name and phone numbers for each person:

string line, word;  // will hold a line and word from input, respectively
vector<PersonInfo> people; // will hold all the records from the input
// read the input a line at a time until cin hits end-of-file (or another error)
while (getline(cin, line)) {
    PersonInfo info;      // create an object to hold this record's data
    istringstream record(line); // bind record to the line we just read
    record >> info.name;  // read the name
    while (record >> word)        // read the phone numbers
        info.phones.push_back(word);  // and store them
    people.push_back(info); // append this record to people
}

Here we use getline to read an entire record from the standard input. If the call to getline succeeds, then line holds a record from the input file. Inside the while we define a local PersonInfo object to hold data from the current record.

Next we bind an istringstream to the line that we just read. We can now use the input operator on that istringstream to read each element in the current record. We first read the name followed by a while loop that will read the phone numbers for that person.

The inner while ends when we’ve read all the data in line. This loop works analogously to others we’ve written to read cin. The difference is that this loop reads data from a string rather than from the standard input. When the string has been completely read, “end-of-file” is signaled and the next input operation on record will fail.

We end the outer while loop by appending the PersonInfo we just processed to the vector. The outer while continues until we hit end-of-file on cin.


Exercises Section 8.3.1

Exercise 8.9: Use the function you wrote for the first exercise in § 8.1.2 (p. 314) to print the contents of an istringstream object.

Exercise 8.10: Write a program to store each line from a file in a vector<string>. Now use an istringstream to read each element from the vector a word at a time.

Exercise 8.11: The program in this section defined its istringstream object inside the outer while loop. What changes would you need to make if record were defined outside that loop? Rewrite the program, moving the definition of record outside the while, and see whether you thought of all the changes that are needed.

Exercise 8.12: Why didn’t we use in-class initializers in PersonInfo?


..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.144.31.163