Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   C++ (http://www.velocityreviews.com/forums/f39-c.html)
-   -   string.scanf? (http://www.velocityreviews.com/forums/t283515-string-scanf.html)

JustSomeGuy 06-04-2004 03:58 AM

string.scanf?
 
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;





qWake 06-04-2004 04:07 AM

Re: string.scanf?
 
"JustSomeGuy" <nope@nottelling.com> 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.



E. Robert Tisdale 06-04-2004 04:48 AM

Re: string.scanf?
 
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]

Phlip 06-04-2004 05:41 AM

Re: string.scanf?
 
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





JustSomeGuy 06-05-2004 03:34 PM

Re: string.scanf?
 
Thank you all!



Jorge Rivera 06-06-2004 04:16 PM

Re: string.scanf?
 
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;
}


All times are GMT. The time now is 12:59 PM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.