It's much easier to use a dedicated library for this task. With Boost Tokenizer's Escaped List Separator, it's a breeze:
#include <vector>
#include <string>
#include <iostream>
#include <fstream>
#include <boost/tokenizer.hpp>
int main()
{
std::ifstream myfile("myCSVFile.txt");
if (myfile.is_open())
{
std::string line;
while (std::getline(myfile, line))
{
typedef boost::escaped_list_separator<char> Separator;
typedef boost::tokenizer<Separator> Tokenizer;
std::vector<std::string> tokens;
Tokenizer tokenizer(line);
for (Tokenizer::iterator iter = tokenizer.begin(); iter != tokenizer.end(); ++iter)
{
tokens.push_back(*iter);
}
if (tokens.size() == 4)
{
std::cout << tokens[0] << "\t" << tokens[2] << "\n";
}
else
{
std::cerr << "illegal line\n";
}
}
}
}
Note that in C++11, you can simplify the loop:
for (auto &token : tokenizer)
{
tokens.push_back(token);
}
As you can see, the idea is to just store all values of a line in a std::vector
and then output what's required.
Now this may lead to performance problems if you really deal with huge files. In that case, use a counter together with the tokenizer:
#include <vector>
#include <string>
#include <iostream>
#include <fstream>
#include <boost/tokenizer.hpp>
int main()
{
std::ifstream myfile("myCSVFile.txt");
if (myfile.is_open())
{
std::string line;
while (std::getline(myfile, line))
{
typedef boost::escaped_list_separator<char> Separator;
typedef boost::tokenizer<Separator> Tokenizer;
Tokenizer tokenizer(line);
int count = 0;
for (Tokenizer::iterator iter = tokenizer.begin(); (iter != tokenizer.end()) && (count < 3); ++iter)
{
if ((count == 0) || (count == 2))
{
std::cout << *iter;
if (count == 0)
{
std::cout << "\t";
}
}
++count;
}
std::cout << "\n";
}
}
}
You can use both techniques (std::vector<std::string>
with later output or loop with counter) even with your self-made string-splitting algorithm. The basic idea is the same:
With std::vector<std::string>
:
std::vector<std::string> tokens;
while ((pos = s.find(delimiter)) != std::string::npos) {
token = s.substr(0, pos);
tokens.push_back(token);
s.erase(0, pos + delimiter.length());
}
if (tokens.size() == 4)
{
std::cout << tokens[0] << "\t" << tokens[2] << "\n";
}
else
{
std::cerr << "illegal line\n";
}
With a counter:
int count = 0;
while ((pos = s.find(delimiter)) != std::string::npos && (count < 4)) {
token = s.substr(0, pos);
if ((count == 0) || (count == 2))
{
std::cout << token;
if (count == 0)
{
std::cout << "\t";
}
}
++count;
s.erase(0, pos + delimiter.length());
}