Parsing Numeric Data

M

Mike Copeland

I'm looking for a technique to parse a series of numeric values from
a line of input. For example, I have the following data lines:

1 2 37 36 4 7 5 6 8 9 10 20 16
601 1100 11 3900 0 0 Starting Values

I want to extract the numeric values from each line, but as can be
seen there are different numbers of values and one line has non-numeric
data that I wish to ignore. Currently I use strtok to (laboriously)
work through each data line, but I assume there must be better ways to
extract such data (and store it into an array or STL container) than
that.
Any thoughts? TIA
 
I

Ian Collins

I'm looking for a technique to parse a series of numeric values from
a line of input. For example, I have the following data lines:

1 2 37 36 4 7 5 6 8 9 10 20 16
601 1100 11 3900 0 0 Starting Values

I want to extract the numeric values from each line, but as can be
seen there are different numbers of values and one line has non-numeric
data that I wish to ignore. Currently I use strtok to (laboriously)
work through each data line, but I assume there must be better ways to
extract such data (and store it into an array or STL container) than
that.
Any thoughts? TIA

One simple approach is to read a line, then use the line to build a
stringstream and extract the data from there. For example:

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

int main( int argc, char** argv )
{
typedef std::vector<int> LineOfData;
typedef std::vector<LineOfData> LinesOfData;

LinesOfData lines;

std::ifstream fin(argv[1]);

while( fin )
{
std::string s;

std::getline( fin, s );

if( fin )
{
std::istringstream in(s);
LineOfData line;

while( in )
{
int n;
in >> n;

if( in )
{
line.push_back(n);
}
}

lines.push_back(line);
}
}

for( LinesOfData::const_iterator line = lines.begin();
line != lines.end(); ++line )
{
for( LineOfData::const_iterator n = line->begin();
n != line->end(); ++n )
{
std::cout << *n << ' ';
}
std::cout << std::endl;
}
}
 
J

Jorgen Grahn

I'm looking for a technique to parse a series of numeric values from
a line of input. For example, I have the following data lines:

1 2 37 36 4 7 5 6 8 9 10 20 16
601 1100 11 3900 0 0 Starting Values

I want to extract the numeric values from each line, but as can be
seen there are different numbers of values and one line has non-numeric
data that I wish to ignore. Currently I use strtok to (laboriously)
work through each data line, but I assume there must be better ways to
extract such data (and store it into an array or STL container) than
that.

I don't see what's hard about it. Here's one approach (but untested,
and you'll have to read the documentation to ensure that the behavior
is really the one you want).

void numbers(const char* s, std::vector<unsigned>& v)
{
while(1) {
char* e;
unsigned n = strtoul(s, &e, 10);
if(e==s) break;
if(!e) break;
v.push_back(n);
s = e;
}
}

/Jorgen
 
L

Luca Risolia

I'm looking for a technique to parse a series of numeric values from
a line of input. For example, I have the following data lines:

1 2 37 36 4 7 5 6 8 9 10 20 16
601 1100 11 3900 0 0 Starting Values

I want to extract the numeric values from each line, but as can be
seen there are different numbers of values and one line has non-numeric
data that I wish to ignore. Currently I use strtok to (laboriously)
work through each data line, but I assume there must be better ways to
extract such data (and store it into an array or STL container) than
that.
Any thoughts? TIA

#include <iostream>
#include <sstream>
#include <vector>

using namespace std;

class IStreamExceptions { // RAII
public:

IStreamExceptions(istream& is, const ios_base::iostate state)
: is_(is), old_state(is.exceptions()) {
is_.exceptions(state);
}

~IStreamExceptions() {
is_.exceptions(old_state);
}
private:
istream& is_;
const ios_base::iostate old_state;
};

vector<int> readints(istream& in) {
IStreamExceptions e(in, ios_base::failbit | ios_base::badbit);
vector<int> v;
for (;;)
try {
int i;
in >> i;
v.push_back(i);
} catch (ios_base::failure f) { // ignore
if (in.eof())
return v;
in.clear();
in.ignore();
}
}

int main(int argc, char** argv) {
istringstream is("345 string 678 90 90 x");
for (const int& e : readints(is)) // or cin
cout << e << '\n';
return 0;
}
 
T

tes

I'm looking for a technique to parse a series of numeric values from
a line of input. For example, I have the following data lines:

1 2 37 36 4 7 5 6 8 9 10 20 16
601 1100 11 3900 0 0 Starting Values

I want to extract the numeric values from each line, but as can be
seen there are different numbers of values and one line has non-numeric
data that I wish to ignore. Currently I use strtok to (laboriously)
work through each data line, but I assume there must be better ways to
extract such data (and store it into an array or STL container) than
that.
Any thoughts? TIA

I really dont understand the more difficult solutions posted so far. Use
a [boost|std]::regex_iterator
 
J

Jorgen Grahn

I'm looking for a technique to parse a series of numeric values from
a line of input. For example, I have the following data lines:

1 2 37 36 4 7 5 6 8 9 10 20 16
601 1100 11 3900 0 0 Starting Values

I want to extract the numeric values from each line, but as can be
seen there are different numbers of values and one line has non-numeric
data that I wish to ignore. Currently I use strtok to (laboriously)
work through each data line, but I assume there must be better ways to
extract such data (and store it into an array or STL container) than
that.
Any thoughts? TIA

I really dont understand the more difficult solutions posted so far. Use
a [boost|std]::regex_iterator

If you don't understand my strtoul()-based one or Ian Collins'
iostreams-based one, you should read up on those subjects. They seem
very straightforward to me.

Or perhaps you meant to say "I don't understand why they didn't
recommend regexes instead"? In my case, because I haven't used Boost
yet, and boost.regex seems overly complicated at a quick glance.

/Jorgen
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,733
Messages
2,569,439
Members
44,829
Latest member
PIXThurman

Latest Threads

Top