string.scanf?

Discussion in 'C++' started by JustSomeGuy, Jun 4, 2004.

  1. JustSomeGuy

    JustSomeGuy Guest

    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;
     
    JustSomeGuy, Jun 4, 2004
    #1
    1. Advertising

  2. JustSomeGuy

    qWake Guest

    "JustSomeGuy" <> 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.
     
    qWake, Jun 4, 2004
    #2
    1. Advertising

  3. 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]
     
    E. Robert Tisdale, Jun 4, 2004
    #3
  4. JustSomeGuy

    Phlip Guest

    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/bin/view/Main/TestFirstUserInterfaces
     
    Phlip, Jun 4, 2004
    #4
  5. JustSomeGuy

    JustSomeGuy Guest

    Thank you all!
     
    JustSomeGuy, Jun 5, 2004
    #5
  6. JustSomeGuy

    Jorge Rivera Guest

    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<<endl;
    }
     
    Jorge Rivera, Jun 6, 2004
    #6
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. lehrig

    scanf string in python

    lehrig, Jul 18, 2003, in forum: Python
    Replies:
    7
    Views:
    17,441
    Erik Max Francis
    Jul 19, 2003
  2. Radith
    Replies:
    18
    Views:
    587
    Michael Mair
    Aug 2, 2005
  3. =?ISO-8859-1?Q?Martin_J=F8rgensen?=

    scanf (yes/no) - doesn't work + deprecation errors scanf, fopen etc.

    =?ISO-8859-1?Q?Martin_J=F8rgensen?=, Feb 16, 2006, in forum: C Programming
    Replies:
    185
    Views:
    3,516
    those who know me have no need of my name
    Apr 3, 2006
  4. =?ISO-8859-1?Q?Martin_J=F8rgensen?=

    difference between scanf("%i") and scanf("%d") ??? perhaps bug inVS2005?

    =?ISO-8859-1?Q?Martin_J=F8rgensen?=, Apr 26, 2006, in forum: C Programming
    Replies:
    18
    Views:
    703
    Richard Bos
    May 2, 2006
  5. spaces in scanf format string

    , Nov 5, 2006, in forum: C Programming
    Replies:
    3
    Views:
    921
Loading...

Share This Page