From a file, how do I read from a certain point in

2019-01-29 06:27发布

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

2条回答
乱世女痞
2楼-- · 2019-01-29 06:54

How do I skip reading "engine"?

You can use std::ifstream::ignore with a custom delimiter if you don't want to check what was read:

f.ignore(std::numeric_limits<std::streamsize>::max(), ':');

But seeing these keys being delimited by : or a space from their values, you can also do use std::getline to read till : or simple operator>> to read to std::string up to the whitespace including : and then check that.

How do I skip a whole auto?

If what you mean is writing another Auto to a file, you can open the file in append mode - with std::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):

f.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

Edit:

To read the values after : you can use:

  1. operator>> - formatted extraction and then either std::getline or std::istream::ignore the rest of the line (with \n as a delimiter), so the next std::getline reads properly the next line
  2. std::getline with \n delimiter to read the rest of the line, then parse that with std::istringstream and formatted extraction.

In both cases, you can know if there were some excess characters after the value.

查看更多
Melony?
3楼-- · 2019-01-29 06:58

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 a std::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.

查看更多
登录 后发表回答