Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > string.scanf?

Reply
Thread Tools

string.scanf?

 
 
JustSomeGuy
Guest
Posts: n/a
 
      06-04-2004
I have a string that looks like:
"123.45:123.45"
I am using sscanf "%f%*c%f" to extract the two floats and ignore the colon.
However there may be more than two floats....
Is there perhaps a better way to do this in C++?
Like make the string appear as a stream and do it with operator>>

string x;
float f1, f2;
x >> f1;
x >> f2;




 
Reply With Quote
 
 
 
 
qWake
Guest
Posts: n/a
 
      06-04-2004
"JustSomeGuy" <(E-Mail Removed)> wrote in message
news:WrSvc.664663$Ig.177566@pd7tw2no...
> I have a string that looks like:
> "123.45:123.45"
> I am using sscanf "%f%*c%f" to extract the two floats and ignore the

colon.
> However there may be more than two floats....
> Is there perhaps a better way to do this in C++?
> Like make the string appear as a stream and do it with operator>>
>
> string x;
> float f1, f2;
> x >> f1;
> x >> f2;


What you are doing is trying to separate tokens that are part of a string.
Lookup the C "strtok" function that will do that for you quite simply. Read
the input in a C-style string and parse it with strtok. Your program can
count the tokens as it goes, you just convert them to float with something
like "atof" or any other way you like.


 
Reply With Quote
 
 
 
 
E. Robert Tisdale
Guest
Posts: n/a
 
      06-04-2004
JustSomeGuy wrote:

> I have a string that looks like:


> "123.45:123.45"


> I am using sscanf "%f%*c%f"
> to extract the two floats and ignore the colon.
> However there may be more than two floats....
> Is there perhaps a better way to do this in C++?
> Like make the string appear as a stream and do it with operator>>


> cat main.cc

#include <iostream>
#include <sstream>
#include <cstdlib>

int main(int argc, char* argv[]) {
std::string x("123.45:123.45");
std::istringstream iss(x);
const
size_t n = 2;
float f[n];
size_t j = 0;
while (iss >> f[j]) {
std::cout << f[j]
<< " = f[" << j << "]" << std::endl;
++j;
char c = '\0';
if (iss >> c && ':' == c)
continue;
else
break;
}
return EXIT_SUCCESS;
}

> g++ -Wall -ansi -pedantic -o main main.cc
> ./main

123.45 = f[0]
123.45 = f[1]
 
Reply With Quote
 
Phlip
Guest
Posts: n/a
 
      06-04-2004
JustSomeGuy wrote:

> I have a string that looks like:
> "123.45:123.45"
> I am using sscanf "%f%*c%f" to extract the two floats and ignore the

colon.
> However there may be more than two floats....
> Is there perhaps a better way to do this in C++?
> Like make the string appear as a stream and do it with operator>>
>
> string x;
> float f1, f2;
> x >> f1;
> x >> f2;


I recently refactored this ugly code:

typedef std::map<string, string> params_t;

bool
Product(params_t & testCase)
{
double num (strtod(testCase["Input1" ].c_str(), NULL));
double den (strtod(testCase["Input2"].c_str(), NULL));
double quo (strtod(testCase["Product()" ].c_str(), NULL));

return num * den == quo;
}

It now looks like this:

static double
getDouble(params_t & testCase, string columnName)
{
double num(double());
std::stringstream z (testCase[columnName]);
if (z >> num)
return num;
return 0.0; // TODO will throw soon
}

bool
Product(params_t & testCase, string & because)
{
double num (getDouble(testCase, "Input1" ));
double den (getDouble(testCase, "Input2" ));
double quo (getDouble(testCase, "Product()"));

return num * den == quo;
}

Focus on the 'streamstring z' deep inside. One might extract your floats
using:

string x;
stringstream z(x);
double f1, f2;
char space;
z >> f1;
z >> space;
z >> f2;

BTW use 'double' without a reason to use 'float', just as one uses 'int'
without a reason to use 'short' or 'long'. On modern CPUs 'double's can be
faster, too.

My refactor replaced redundant calls to strtod() (another way to do it) with
a single call to operator>>().

--
Phlip
http://industrialxp.org/community/bi...UserInterfaces




 
Reply With Quote
 
JustSomeGuy
Guest
Posts: n/a
 
      06-05-2004
Thank you all!


 
Reply With Quote
 
Jorge Rivera
Guest
Posts: n/a
 
      06-06-2004
JustSomeGuy wrote:
> I have a string that looks like:
> "123.45:123.45"


I have two suggestions:

This first one uses a dummy character to use istringstreams capabilities
for parsing...
(You can extend this to more floats by iterating until iss fails....)

using namespace std;
string x("123.45:123.46");

char colon; // Store the colon (or any other character)
float f1, f2; // Our target floating numbers

//Initialize an istringstream
istringstream iss(x);

// Extract the tokens
iss>>f1>>colon>>f2;

The second approach uses the strings find function to figure out the
location of the colons, then send the substring to isstream

string x("123.45:123.46:305.37");
istringstream iss("");
vector<double> mFloats;
string::size_type next_colon;
float temp = 0.0f;

x = std::string("3.0");
do
{
next_colon = x.find(':'); // Find next colon
iss.clear(); // Needed to reuse iss
iss.str(x.substr(0, next_colon)); // Use the first token
x = x.substr(next_colon+1); // Update x (You may want to use a temp
string)
iss>>temp; // Extract the current float
mFloats.push_back(temp); // Add float to the vector
}while(string::npos != next_colon);

// Output the elements
size_t doubles = mFloats.size();
cout<<"Found "<<doubles<<" number..."<<endl;
for(size_t i=0; i<doubles; i++)
{
cout<<"\t"<<i<<": "<<mFloats[i]<<endl;
}
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off




Advertisments