Input Streams

Reading Multiple Objects from Stream

What is the best way to read multiple objects from a stream?

Abstract art representing computer programming

Reading multiple objects from a stream can be efficiently handled using a loop. This approach allows you to continuously extract data until the end of the stream is reached or an error occurs.

Example with a Simple Class

Consider a simple Character class and reading multiple Character objects from a stream:

#include <iostream>
#include <sstream>
#include <vector>

class Character {
 public:
  std::string Name;
  int Level;
  bool isAlive;

  Character(std::istringstream& stream) {
    stream >> Name >> Level >> isAlive;
  }

  void Log() const {
    std::cout << Name << " - Level " << Level
      << (isAlive ? " (Alive)" : " (Dead)")
      << '\n';
  }
};

int main() {
  std::istringstream input{
      "Legolas 80 1 Gimli 70 1 Aragorn 60 0"};
  std::vector<Character> party;

  while (input) {
    Character c(input);

    // Check if the extraction was successful
    if (input) {
      party.emplace_back(std::move(c));
    }
  }

  for (const auto& member : party) {
    member.Log();
  }
}
Legolas - Level 80 (Alive)
Gimli - Level 70 (Alive)
Aragorn - Level 60 (Dead)

This example reads characters from the input stream until no more data is available.

Handling Errors and End of Stream

To make the process more robust, you should handle potential errors and check the state of the stream correctly. Here’s an improved version:

#include <iostream>
#include <sstream>
#include <vector>

class Character {
 public:
  std::string Name;
  int Level;
  bool isAlive;

  bool readFromStream(std::istringstream& stream) {
    int alive;
    if (stream >> Name >> Level >> alive) {
      isAlive = static_cast<bool>(alive);
      return true;
    }
    return false;
  }

  void Log() const {
    std::cout << Name << " - Level " << Level
      << (isAlive ? " (Alive)" : " (Dead)")
      << '\n';
  }
};

int main() {
  std::istringstream input{
      "Legolas 80 1 Gimli 70 1 Aragorn 60 0"};
  std::vector<Character> party;
  Character character;

  while (character.readFromStream(input)) {
    party.push_back(character);
  }

  for (const auto& member : party) {
    member.Log();
  }
}
Legolas - Level 80 (Alive)
Gimli - Level 70 (Alive)
Aragorn - Level 60 (Dead)

In this version, the readFromStream() method returns false when it fails to read more data, effectively ending the loop.

Using std::getline()

If your objects are defined across multiple lines or use custom delimiters, consider using std::getline():

#include <iostream>
#include <sstream>
#include <vector>

class Character {
 public:
  std::string Name;
  int Level;
  bool isAlive;

  Character(const std::string& line) {
    std::istringstream stream(line);
    stream >> Name >> Level >> isAlive;  
  }

  void Log() const {
    std::cout << Name << " - Level " << Level
      << (isAlive ? " (Alive)" : " (Dead)")
      << '\n';
  }
};

int main() {
  std::istringstream input{
    "Legolas 80 1\nGimli 70 1\nAragorn 60 0"};
  std::vector<Character> party;
  std::string line;

  while (std::getline(input, line)) {  
    party.emplace_back(line);          
  }

  for (const auto& member : party) {
    member.Log();
  }
}
Legolas - Level 80 (Alive)
Gimli - Level 70 (Alive)
Aragorn - Level 60 (Dead)

This approach allows for more complex input formats, making your code adaptable to various data sources.

Reading multiple objects from a stream involves using loops and proper state checking to ensure data is read correctly and efficiently.

This Question is from the Lesson:

Input Streams

A detailed introduction to C++ Input Streams using std::cin and istringstream. Starting from the basics and progressing up to advanced use cases including creating collections of custom objects from our streams.

Answers to questions are automatically generated and may not have been reviewed.

This Question is from the Lesson:

Input Streams

A detailed introduction to C++ Input Streams using std::cin and istringstream. Starting from the basics and progressing up to advanced use cases including creating collections of custom objects from our streams.

A computer programmer
Part of the course:

Professional C++

Comprehensive course covering advanced concepts, and how to use them on large-scale projects.

Free, unlimited access

This course includes:

  • 125 Lessons
  • 550+ Code Samples
  • 96% Positive Reviews
  • Regularly Updated
  • Help and FAQ
Free, Unlimited Access

Professional C++

Comprehensive course covering advanced concepts, and how to use them on large-scale projects.

Screenshot from Warhammer: Total War
Screenshot from Tomb Raider
Screenshot from Jedi: Fallen Order
Contact|Privacy Policy|Terms of Use
Copyright © 2024 - All Rights Reserved