-1

I am trying to extract float numbers from a string 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;
}
phuclv
  • 37,963
  • 15
  • 156
  • 475
  • 1
    *"doesn't work"* is a horrible problem description. You should be as specific as you can be – UnholySheep Jun 05 '22 at 19:17
  • Also you should start by making a proper [mre]. The posted code doesn't compile – UnholySheep Jun 05 '22 at 19:17
  • Welcome to StackOverflow. From a quick look over your code I notice the space characters in your string `a` whilst you are searching for a `"\t"` for splitting. – PhilMasteG Jun 05 '22 at 19:19
  • 2
    indent your code properly. That's one of the most basic things you must do when programming. Also see [Why is "using namespace std;" considered bad practice?](https://stackoverflow.com/q/1452721/995714) – phuclv Jun 06 '22 at 14:35

2 Answers2

1

Don't parse the string like that. Just read the values in your desired locale, for example most non-English European locales like de_DE.utf8, ru_RU.utf8, or it_IT.UTF-8... You can even set different locales for different streams, so for example below I'm using the default system locale 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;
}

In C++ std::locale("") gives you the current system locale which is probably el_GR.UTF-8 in your case. You can also specify a specific locale to use such as std::locale("fr_FR.utf8"). Then use std::locale::global to set the obtained locale globally. Each specific stream can further be imbued to a different locale if necessary. You can also use setlocale for setting some locale preferences

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

In the example above I'm setting the current locale via LC_ALL, but on Windows you can't change that easily from the console so just do that in your code. And I'm printing the output directly but pushing it into an array is trivial

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 and any kinds of istream 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

phuclv
  • 37,963
  • 15
  • 156
  • 475
0

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 :)

KokosNaPalmie
  • 59
  • 1
  • 5