0

I have the following data:

$GPVTG,,T,,M,0.00,N,0.0,K,A*13

I need to read the data, however there are blanks in between the commas, therefore I am not sure how I should read the data.

Also, how do I select GPVTG only for a group of data? For example:

GPVTG,,T,,M
GPGGA,184945.00
GPRMC,18494
GPVTG,,T,,M,0
GPGGA,184946.000,3409

I have tried using:

 /* read data line */
 fgets(gpsString,100,gpsHandle);
 char type[10] = "GPVTG";
 sscanf(gpsString," %GPVTG", &type);
 if (strcmp(gpsString, "GPTVG") == 0){
   printf("%s\n",gpsString);
 }
Jon Purdy
  • 53,300
  • 8
  • 96
  • 166
  • Please clarify. What are "blanks" in between the commas? I don't see any blanks in the sample data you provided. Are you referring to the empty fields in the CSV record? – jia103 Feb 18 '14 at 17:01
  • 1
    You've tagged it C++ but posted C, which do you want the answer in? – dutt Feb 18 '14 at 17:03
  • @jia103 I think he means `""` between them `,,` – yizzlez Feb 18 '14 at 17:03
  • If c type file handling is necessary you should tag it with C. If it is possible to use streams you can omit it. – daramarak Feb 18 '14 at 17:04
  • 1
    Since you tagged your answer as C++, you should look into using `std::string`, `std::getline` and `std::istringstream`. There are many examples in StackOverflow using them. – Thomas Matthews Feb 18 '14 at 17:06
  • I tag it `C++` based on the title of OP's question. – herohuyongtao Feb 18 '14 at 17:06
  • If you're dealing with CSV data, make sure to review the typical situations seen in the wild listed [here](http://en.wikipedia.org/wiki/Comma-separated_values). If you're worried about quotes, then you might also have commas embedded in the quotes. I'd recommend starting by nailing down exactly what you're going to support and what you're not going to support; otherwise, your parser can get extremely complex really quick. – jia103 Feb 18 '14 at 17:11
  • Depending on how simple you're allowed to make it, have you thought about using `strtok()` to tokenize into fields? Note that this will work if you don't have to worry about embedded commas. – jia103 Feb 18 '14 at 17:13
  • I am trying to read a file that contains all the data, I am suppose to read only GPVTG heading from the list of data that i am supposed to have. how do i do that? – user3324475 Feb 18 '14 at 17:21
  • http://stackoverflow.com/questions/236129/how-to-split-a-string-in-c/236976#236976 Second answer is exactly what you need. – user1849353 Feb 18 '14 at 17:22
  • @jia103 `strtok` is a good way to get into serious trouble down the road. It's never a good solution. – James Kanze Feb 18 '14 at 18:25
  • @James Kanze If you're referring to the unsafe issues with `strtok`, then that's a good point. I forgot about that. If OP is using Windows, then there might be `strtok_s` available instead. – jia103 Feb 18 '14 at 20:31
  • @jia103 That would help, but the basic idea of a parser which modifies its input is an anathema to me. At any rate, there are much better ways of doing it in C++, using `std::string` and iterators. – James Kanze Feb 19 '14 at 11:49

3 Answers3

0

If you want use C++ style code based on fstream:

fin.open(input);

cout << "readed";

string str;

getline(fin, str); // read one line per time
David G
  • 94,763
  • 41
  • 167
  • 253
0

How about this

#include <istream>
#include <sstream>

class CSVInputStream {
public:
  CSVInputStream(std::istream& ist) : input(ist) {}
  std::istream& input; 
};

CSVInputStream& operator>>(CSVInputStream& in, std::string& target) {
  if (!in.input) return in;
  std::getline(in.input, target , ',');
  return in;
}

template <typename T>
CSVInputStream& operator>>(CSVInputStream& in, T& target) {
  if (!in.input) return in;
  std::string line;
  std::getline(in.input, line , ',');
  std::stringstream translator;
  translator << line;
  translator >> target;
  return in;
}

//--------------------------------------------------------------------
// Usage follow, perhaps in another file
//--------------------------------------------------------------------

#include <fstream>
#include <iostream>

int main() {
  std::ifstream file;
  file.open("testcsv.csv");
  CSVInputStream input(file);
  std::string sentence_type;
  double track_made_good;
  char code;
  double unused;
  double speed_kph;
  char speed_unit_kph;
  double speed_kmh;
  char speed_unit_kmh;
  input >> sentence_type >> track_made_good >> code;
  input >> unused >> unused;
  input >> speed_kph >> speed_unit_kph;
  input >> speed_kmh >> speed_unit_kmh;
  std::cout << sentence_type << " - " << track_made_good << " - ";
  std::cout << speed_kmh << " " << speed_unit_kmh << " - ";
  std::cout << speed_kph << " " << speed_unit_kph << std::endl;;
}

This separates the comma separation from the reading of the values, and can be reused on most other comma separated stuff.

daramarak
  • 6,115
  • 1
  • 31
  • 50
0

Thats what i'd do

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

using namespace std;

vector<string> &split(const string &s, char delim, vector<string> &elems) {
    stringstream ss(s);
    string item;
    while (getline(ss, item, delim)) {
        elems.push_back(item);
    }
    return elems;
}

vector<string> split(const string &s, char delim) {
    vector<string> elems;
    split(s, delim, elems);
    return elems;
}


int main()
{

    ifstream ifs("file.txt");

    string data_string;

    while ( getline( ifs, data_string ) )
    {
            //i think you'd want to erase first $ charachter
        if ( !data_string.empty() ) data_string.erase( data_string.begin() );

            //now all data put into array:
        vector<string> data_array = split ( data_string, ',' );

        if ( data_array[0] == "GPVTG" )
        {
            //do whatever you want with that data entry
            cout << data_string;
        }
    }

    return 0;
}

Should handle your task. All empty elements will be empty "" strings in array. Ask if you need anything else.

Credits for split functions belong to Split a string in C++? answer.

Community
  • 1
  • 1
user1849353
  • 87
  • 1
  • 10