Home > Mobile >  how to extract floats form a string
how to extract floats form a string

Time:06-07

I am trying to extract from a string float numbers and after that they will be saved in an array. here's a code I found and even though I made the necessary changes it doesn't work:

#include <iostream>
#include <string>
using namespace std;

string a="2,134 43,54 22,334";
string b[30];

int found,i=0;
while(a!="\0"){
found=a,find("\t");
for(int f=0;f<found;f  ){
b[i] =a[f];
}
a.erase(0,found 1);
i  ;
}
for(int d=0;d<i;d  ){
cout<<b[d]<<endl;
}
return 0;
}

CodePudding user response:

If you don't care about performance that much, you can use this simple algorithm :

#include <iostream>
#include <vector>


int main()
{
    std::string a = "2,134 43,54 22,334";

    std::vector<std::string> floats; // I used vector instead of array - easier and safer

    std::string buffer;
    for (auto& itr : a)
    {
        if (itr == ' ') // space -- float ended
        {
            floats.push_back(buffer);
            buffer.erase();
        }
        else
        {
            buffer  = itr;
        }
    }

    if (!buffer.empty()) // if something left in the buffer -> push it
        floats.push_back(buffer);

    // printing 'floats' array
    for (auto& itr : floats)
        std::cout << itr << '\n';

   return 0;
}

this algorithm goes through every char inside 'a' and checks:

  • if digit or comma -> add it to buffer
  • if space -> reading float ended (now looking for a new one), pushing buffer to array and clearing buffer so you can read new float

if you want me to explain someting feel free to ask :)

CodePudding user response:

Don't parse the string like that. Just read the values in your desired locale, for example most non-English European locales like el_GR.UTF-8 (probably your case), de_DE.utf8, ru_RU.utf8, fr_FR.utf8, or it_IT.UTF-8... You can even set different locales for different streams, so for example I'm using the default system locale (set via LC_ALL) for std::cin and a custom locale which uses : as the radix point in std::cout

#include <iostream>
#include <sstream>
#include <locale>
#include <clocale>
#include <stdlib.h>

template <class charT, charT sep>
class punct_facet: public std::numpunct<charT> {
protected:
    charT do_decimal_point() const { return sep; }
};

int main(int argc, char** argv) {
    // Use default locale for most std streams
    std::locale::global(std::locale(""));
    // Use C locale with custom radix point for stdout
    std::cout.imbue(std::locale(std::locale("C"), new punct_facet<char, ':'>));

    std::stringstream str(argv[1]);
    double d;
    while (str >> d)
    {
        std::cout << d << '\n';
    }
    return 0;
}

Sample output:

$ g   read_locale.cpp -o read_locale
$ LC_ALL=el_GR.UTF-8 ./read_locale "2,134 43,54 22,334"
2:134
43:54
22:334
$ LC_ALL=en_US.utf8 ./read_locale "2.134 43.54 22,334"
2:134
43:54
22334

Notice the difference in the last output? That's because , is the thousand separator in the English locale

Demo on Godbolt

Demo on ideone

Note that those online platforms don't have a non-US locale so I have to use the custom locale. On Linux you can check the available locales with locale -a


In case you really want to get the floating-point numbers as strings (why?) then just read normally. No need for such complex parsing. std::cin will just stop at blank spaces as expected

#include <iostream>
#include <sstream>
#include <string>

int main(int argc, char** argv) {
    std::stringstream str(argv[1]);
    std::string s;
    while (str >> s)
    {
        std::cout << s << '\n';
    }
    return 0;
}

Sample output:

$ g   read_numbers_as_string.cpp -o read_numbers_as_string
$ ./read_numbers_as_string "2,134 43,54 22,334"
2,134
43,54
22,334

Demo

  • Related