What I want to do: I need to create in void main() 3 auto objects. For each object I have the information in a txt file.
How do I get the information (engine, max_speed... etc) for each object. How do I skip reading "engine" and how do I skip a whole auto when creating the second object. Thanks!
The txt file: (auto.txt)
auto1
engine: gasoline
max_speed: 250
engine_cc: 1980
avg_consumption_urban: 11
avg_speed_urban: 50
avg_consumption: 8
avg_speed: 100
auto2
engine: diesel
max_speed: 230
engine_cc: 1600
avg_consumption_urban: 9
avg_speed_urban: 50
avg_consumption: 6
avg_speed: 80
auto3
engine: hybrid
max_speed: 190
engine_cc: 1450
avg_consumption_urban: 7
avg_speed_urban: 50
avg_consumption: 4
avg_speed: 90
What I have so far (I used this code using a more simple version of the auto.txt to read and display - see below for the simple version of my txt file):
This is my ifstream method in the Auto class
friend ifstream& operator>>(ifstream& in, Auto &a)
{
delete[]a.engine;
a.engine = new char[10];
in >> a.engine;
in >> a.max_speed;
in >> a.engine_cc;
in >> a.avg_consumption_urban;
in >> a.avg_speed_urban;
in >> a.avg_consumption;
in >> a.avg_speed;
return in;
}
And this is how I read from the file in void main
ifstream f("auto.txt", ios_base::in);
f >> auto1;
auto1.display();
f.close();
This is the text I read from. This is a simplified version.
gasoline
250
1980
11
50
8
100
You can use
std::ifstream::ignore
with a custom delimiter if you don't want to check what was read:But seeing these keys being delimited by
:
or a space from their values, you can also do usestd::getline
to read till:
or simpleoperator>>
to read tostd::string
up to the whitespace including:
and then check that.If what you mean is writing another
Auto
to a file, you can open the file in append mode - withstd::ios_base::out | std::ios_base::app
.On the other hand, if you mean reading the information, you can skip over what appears to be constant number of lines by repeatedly calling (in a loop):
Edit:
To read the values after
:
you can use:operator>>
- formatted extraction and then eitherstd::getline
orstd::istream::ignore
the rest of the line (with\n
as a delimiter), so the nextstd::getline
reads properly the next linestd::getline
with\n
delimiter to read the rest of the line, then parse that withstd::istringstream
and formatted extraction.In both cases, you can know if there were some excess characters after the value.
In the file format, there is no efficient method to position to a given record. The records are variable sized for example, one has an engine speed of 100 (3 characters) while another has 80 (2 characters).
Since each field is on a separate line, you could read each text line searching for "engine" at the start of the text.
This project smells like it could use a database.
If you are having to read line by line, you might as well read record by record. That is, have the record object read its members from the file.
If you get the file position before you read a record, you could store the information into a
std::map<unsigned int, Engine>
and use the file pointer as the index into the map.Did I say this smells like a it could use a database?
Another idea is to read in all the records and shove them into a
std::vector
. Create astd::map<unsigned int, unsigned int>
to map vector indices to file positions.Still smells like you should use a database.
By placing the Engine records into a vector you could create other index tables (Databases can create index tables for you). For example, a
std::map<string, unsigned int>
to map engine types to vector indices.Look into Database theory, especially Normal Forms. You would benefit a lot from this knowledge when you use a database.