'Trying to use getline (string) in C++ to parse a kml file

I'm using getline() to parse coordinate lines from a kml file into a vector.

The relevant part of the kml file looks like this (replaced numbers with x)...

<coordinates>
      -xxxxxxxxx,xxxxxxxxx,0
      -xxxxxxxxx,xxxxxxxxx,0
      -xxxxxxxxx,xxxxxxxxx,0
      -xxxxxxxxx,xxxxxxxxx,0
      -xxxxxxxxx,xxxxxxxxx,0
      -xxxxxxxxx,xxxxxxxxx,0
      -xxxxxxxxx,xxxxxxxxx,0
      -xxxxxxxxx,xxxxxxxxx,0
      -xxxxxxxxx,xxxxxxxxx,0
      -xxxxxxxxx,xxxxxxxxx,0
      -xxxxxxxxx,xxxxxxxxx,0
      -xxxxxxxxx,xxxxxxxxx,0
</coordinates>

When using getline() to print the kml file line by line it does it just fine so I figured something like this would work to parse coordinates into a vector...

#include <iostream>
#include <vector>
#include <fstream>
#include <string>
using namespace std;

vector <string> coordinates;

int main() {
   fstream inputFile("Fish.kml", fstream::in);
   string str;

   bool running = true;
   int counter = 0;

   while (running) {
      getline(inputFile, str, '\0');

      if (str == "        <coordinates>") {
         counter++;
      }
      if (counter > 0 && str != "        </coordinates>") {
         coordinates.push_back(str);

      } 
      if (counter > 0 && str == "        </coordinates>") {
         counter = -1;
         running = false;
      }
   }

   inputFile.close();

   for (int i = 0; i < coordinates.size(); i++) {
      cout << coordinates[i] << "\n";
   }

   return 0;
}

My thinking was to use if statements to check whether the getline() function is about to read the coordinates by checking if the line, "coordinates", has been read or not. If it has it will increase the counter to above zero that way in the next loop the rest of the program knows to start logging coordinates. Same thinking applies to stopping the code by checking to see if the line "/coordinates" has been read. It's all I could think of with my current knowledge, but obviously I must be missing something important because...

When I compile and run I don't get any errors but the program doesn't do anything. This is what it looks like, It does nothing, my computer fans kick on and I have to cancel the process...

irectory>test.exe
^C

Any ideas what is going on here? Thank you!

Update:

#include <iostream>
#include <vector>
#include <fstream>
#include <string>
using namespace std;

vector <string> coordinates;

int main() {
   fstream inputFile("Fish.kml", fstream::in);
   string str;

   bool running = true;
   int counter = 0;

   while (getline(inputFile, str, '\0')) {

      if (str == "        <coordinates>") {
         counter++;
      }
      if (counter > 0 && str != "        </coordinates>") {
         coordinates.push_back(str);

      } 
      if (counter > 0 && str == "        </coordinates>") {
         counter = -1;
         inputFile.close();
      }
   }


   for (int i = 0; i < coordinates.size(); i++) {
      cout << coordinates[i] << "\n";
   }

   return 0;
}

I updated the code above as suggested and it does not get stuck while executing anymore. But it does not print the vector back. I'm not sure if it is failing to record the lines of coordinates or if I didn't print it properly.

c++


Solution 1:[1]

replace while(running) with while(getline(inputFile, str) and remove running variable as it is no longer needed.

And also

  if (str == "<coordinates>") {
     counter++;
  }
  if (counter > 0 && str != "</coordinates>") {
     coordinates.push_back(str);

  } 
  if (counter > 0 && str == "</coordinates>") {
     counter = -1;
  }

Solution 2:[2]

Hopefully the following code would help you a little bit. I worte it myself. It only reads the first coordinates part.

//
// Created by albert on 4/1/22.
//

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

using namespace std;

vector<float> split(string s, string del) {
    int start = 0;
    int end = s.find(del, start);
    vector<float> ret;
    while (end != string::npos) {
        string substr = s.substr(start, end - start);
        if (!substr.empty())
            ret.push_back(stof(substr));
        start = end + del.size();
        end = s.find(del, start);
    }
    string substr = s.substr(start, end - start);
    if (!substr.empty())
        ret.push_back(stof(substr));
    return ret;
}

int main() {
    fstream istream;
    istream.open("map.kml", fstream::in);

    vector<vector<float>> coordinates;
    bool flag = false;

    if (istream.is_open()) {
        cout << "file is open" << endl;
        string str;
        while (getline(istream, str, '\n')) {
            if (str == "          <coordinates>")
                flag = true;
            else if (str == "          </coordinates>") {
                flag = false;
                break;
            } else if (flag)
                coordinates.push_back(split(str, string(1, ',')));

        }
    }

    istream.close();

    for (int i = 0; i < coordinates.size(); i++) {
        cout << coordinates[i][0] << "      " << coordinates[i][1] << "      " << coordinates[i][2] << "\n";
    }
    cout << coordinates.size() << endl;
    return 0;
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Albert G Lieu