0

I'm trying to take an input which will consist of 3 substrings and parse it:

City name, latitude and longitude.

EX: "Monticello 36.8297222 -84.8491667"

So that I can push_back() the city, latitude, and longitude into their own vector objects. But I can't figure out how to do that.

vector<string> city;
vector<float> latitude;
vector<float> longitude;

int main(int argc, char* argv[]){
    fstream inData;
    inData.open(argv[1]);   // open the specified file for reading. 
    string line;
    if (!inData.fail())         // if the file exits and is opened successfully
    {
        while(getline(inData, line))            // read every line from the file until the end
        {
            //here is where I want to parse and pushback into it's vector
        }
    }
    inData.close();
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770

4 Answers4

0

std::getline can take an additional parameter, a delimiter character, which is by default set to '\n'. You are in fact using it to read line by line.

What you could do, after reading in one line, is to assign that line to an instance of std::istringstream and let the operator>> split it by space (default behaviour).

std::vector<std::vector<std::string>> vectors(3);
while(std::getline(inData, line)){
    std::istringstream iss{line};

    std::string token;
    size_t i = 0;
    while(iss >> token){
        vectors[i++].push_back(token);
    }
}
Edd
  • 1,350
  • 11
  • 14
  • I know how to split it and push it back into 1 vector. But the whole point of this question was to split the line and have each element pushbacked into it's own vector – George Wisten Mar 23 '17 at 22:42
  • ah, sorry. didn't get that – Edd Mar 23 '17 at 22:45
  • You might want to remove the line about using getline again, now that you have changed to using istringstream – The Dark Mar 23 '17 at 22:55
  • `operator>>` reads whitespace-delimited values, so there is little difference between using `std::getline(iss, token, ' ')` and `iss >> token` – Remy Lebeau Mar 23 '17 at 22:58
  • thanks guys, I forgot to remove that part after I edited. – Edd Mar 23 '17 at 22:58
0

You can use a stringstream (better: an istringstream) to parse the line and write the results into variables; use then the variables to pushback them into the vectors:

while(getline(inData, line)) 
{
  std::istringstream ss (line);

  std::string city_s;
  float longitude_f;
  float latitude_f;

  if (ss >> city_s >> latitude_f >> longitude_f) {
    city.push_back(city_s);
    latitude.push_back(latitude_f);
    longitude.push_back(longitude_f);
  }
}
Stephan Lechner
  • 34,891
  • 4
  • 35
  • 58
  • You will probably want to check the result of `operator>>` before doing the pushes: `if (ss >> city_s >> latitude_f >> longitude_f) { city.push_back(city_s); latitude.push_back(latitude_f); longitude.push_back(longitude_f); }` – Remy Lebeau Mar 23 '17 at 22:59
0

A refactored and more complete version of the original code. Uses c++11.

#include <vector>
#include <string>
#include <fstream>
#include <iostream>

struct place {
    std::string city;
    double latitude;
    double longitude;
};

std::vector<place> read_places(std::istream& is)
{
    place buffer;
    std::vector<place> places;
    while (is >> buffer.city >> buffer.latitude >> buffer.longitude) {
        places.push_back(std::move(buffer));
    }
    return places;
}

int main(int argc, char* argv[]) {

    // preconditions
    if (argc < 2) {
        std::cerr << "usage: myprog <inputfile>\n";
        std::exit(4);
    }

    std::fstream inData(argv[1]);
    if (!inData) { std::cerr << "failed to open " << argv[1]; std::exit(100); }

    auto places = read_places(inData);
    inData.close();

    // now use places
    // ...
}
Richard Hodges
  • 68,278
  • 7
  • 90
  • 142
0

Also you can use string tokenizer - strtok() and use " " as a delimiter. Here is the link which might help you - http://www.cplusplus.com/reference/cstring/strtok/

vivekn
  • 35
  • 6