简体   繁体   中英

Treat a space(or tab) separated file “like” and array - C++

I have a short tab/space separated file (I can create it accordingly) with the structure

[data00] <space> [data01] <space> [data02] <space> [data03] <newline>
[data10] <space> [data11] <space> [data12] <space> [data13] <newline>
...

The first column representing a numerical ID. I create this file to feed it to another executable, so the format is fixed. After feeding it, the executable outputs another file with the similar structure:

[data00] <space> [data01]<newline>
[data10] <space> [data11]<newline>
...

Given an ID, I need to read the corresponding [dataX1] , perform operations on [dataX3] in the first file, feed it back to the executable, and iterate.

I think of two way of doing this:

  • Operate on the two textfile "as if" they were array, given that their structure is fixed, but I am lost on what function/syntax to use. This should be a small function that would allow me to read the interesting bit by passing it the relevant numeric ID hiding all the pesky I/O code, as I probably need to repeat this operation a lot in different context
  • Keep the first file in arrays and trick the executable by feeding it a stream (is this possible? the executable expects a file as argument).

I could easily read the files into arrays and write the files anew each time, but I want to avoid useless read and write operation, when what I need to read/write is just one cell each time. What I don't now how to do is how to stop/identify the interest bit when I read a whole line from the text file by using,say, getline .

First we will write a function that will split an inputted string based upon a given separator. (In this case we will use space.)

int split(const std::string& line, const std::string& seperator, std::vector<std::string> * values){
    std::string tString = "";
    unsigned counter = 0;
    for(unsigned l = 0; l < line.size(); ++l){
        for(unsigned i = 0; i < seperator.size(); ++i){
            if(line[l+i]==seperator[i]){
                if(i==seperator.size()-1){
                    values->push_back(tString);
                    tString = "";
                    ++counter;
                }else continue;
            }else{
                tString.push_back(line[l]);
                break;
            }
        }
    }
    return counter;
}

Now we will write ourselves a simple main to read a file, use split to break it up, and then output the data based upon its location within the file.

int main(){
    std::vector<std::vector<std::string> > lines;
    std::string tString = "";
    std::vector<std::string> tVector;
    std::ifstream fileToLoad;

    fileToLoad.open(FILE_NAME);

    if(fileToLoad.is_open()){
        while(std::getline(fileToLoad,tString)){
            split(tString, " ", &tVector);
            lines.push_back(tVector);
            tVector.clear();
        }

        //Now print our output.
        for(unsigned i1 = 0; i1 < lines.size(); ++i1){
            for(unsigned i2 = 0; i2 < lines[i1].size(); ++i2){
                std::cout<<"["<<i1<<","<<i2<<"] = "<<lines[i1][i2]<<std::endl;
            }
        }
    }else{
        std::cerr<<"FAILED TO OPEN FILE: "<<FILE_NAME<<std::endl;
        return 1;
    }
    return 0;
}

The input file I used has the data:

450 105 10 10.5 -10.56001 23
10 478 1290 384 1289 3489234 1 2 3 4 5
1 2 3 4 5 6.1 19 -1.5

And the output gives:

[0,0] = 450
[0,1] = 105
[0,2] = 10
[0,3] = 10.5
[0,4] = -10.56001
[1,0] = 10
[1,1] = 478
[1,2] = 1290
[1,3] = 384
[1,4] = 1289
[1,5] = 3489234
[1,6] = 1
[1,7] = 2
[1,8] = 3
[1,9] = 4
[2,0] = 1
[2,1] = 2
[2,2] = 3
[2,3] = 4
[2,4] = 5
[2,5] = 6.1
[2,6] = 19

Now all that you need to do is use your favorite parsing algorithm to change each string into a double. (strtod, atof, etc) Depending how important optimization is you may also want to modify the container from vector, depending upon your use cases.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM