Creating a dynamic array of objects from stream data involves reading the input in a loop and constructing objects based on the extracted data. This technique is useful for processing structured input data, such as records in a file or user input.
Consider a Character
class with attributes Name
, Level
, and isAlive
. You can read multiple Character
objects from a stream and store them in a std::vector
for dynamic sizing:
#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) {
party.emplace_back(input);
}
for (const auto& member : party) {
member.Log();
}
}
Legolas - Level 80 (Alive)
Gimli - Level 70 (Alive)
Aragorn - Level 60 (Dead)
In this example, the Character
constructor reads data from the stream, and emplace_back()
adds a new Character
to the std::vector
.
For better error handling and ensuring you read valid data, you can use a member function to read from the stream and check its state:
#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 = (alive != 0);
return true;
}
return false;
}
void Log() const {
std::cout << Name << " - Level " << Level
<< (isAlive ? " (Alive)" : " (Dead)")
<< std::endl;
}
};
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)
This approach ensures that only valid Character
objects are added to the vector.
std::getline()
If the data is structured across multiple lines or uses custom delimiters, std::getline()
can be useful:
#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 example uses std::getline()
to read each line of input, creating a Character
object from each line.
Creating a dynamic array of objects from stream data allows for flexible and efficient processing of structured input, making it a powerful technique in C++.
Answers to questions are automatically generated and may not have been reviewed.
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.