0

I'm trying to make a function that takes an argument should be something like this

string s1 = "[1 -2.5 3;4 5.25 6;7 8 9.12]";

It's supposed to return it to be only the numbers only without the semicolons or the [ and ] and spaces

Like this:

1 -2.5 3 4 5.25 6 7 8 9.12 

So I can later convert the string to float and save them into an array

Any ideas?

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


string s1 = "[1 -2.5 3;4 5.25 6;7 8 9.12]";

void cutter(string s){


    for(int i=1;i<s.length();i++){
        if(i != s.find(" ") &&  i != s.find(";") ){
            cout << s[i];
            s.erase(0,i-1);

        }
        else if(i == s.find(" ") || i == s.find(";") ){
            cout<<endl;

        }


    }

}

int main()
{
    cutter(s1);
    return 0;
}
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
  • 1
    Replace the `[;]` with spaces and then load the string into a string stream and read it like you would normally read space separated data. – NathanOliver Apr 29 '19 at 13:04
  • i can't replace it thats how the input should be .. its a way to write matrixes a semicolon means the end of a row – Yusuf Sameh Apr 29 '19 at 13:10
  • 1
    @YusufSameh -- Then write a function that makes a copy of the string, manipulates the copy, and returns it. Also removing characters from a string does not require you to write error-prone loops. Use the STL algorithm functions to remove characters. – PaulMcKenzie Apr 29 '19 at 13:10
  • @YusufSameh Then replace the `[]`, load it into a stringstream, and then use `getline` to read until the `;` so you can parse the rows correctly. – NathanOliver Apr 29 '19 at 13:12
  • Check this out : https://stackoverflow.com/questions/53849/how-do-i-tokenize-a-string-in-c – vcp Apr 29 '19 at 13:59

4 Answers4

2

To remove the [ and ] and also replace the ; with spaces you can do something like this:

#include <algorithm>

void cutter(string &s) {
    s.erase(std::remove(s.begin(), s.end(), '['), s.end());
    s.erase(std::remove(s.begin(), s.end(), ']'), s.end());
    std::replace(s.begin(), s.end(), ';', ' ');
}

No need for any manual loops over the string. Also note that in the signature of the function, you need string &s, not string s. Without that & you're passing a copy of the string to the function and that copy is discarded at the end, resulting in no change to the original. With the & you pass a reference instead and the program works as intended.


Of course, you could also keep it pass by copy and instead return the modified string:

std::string cutter(std::string s) {
    // modify the string here
    return s; // returns the modified copy
}

And in main, do:

s1 = cutter(s1); // assign the result to the original to change it
Blaze
  • 16,736
  • 2
  • 25
  • 44
  • I personally *hate* out parameters. I would have made the function signature `std::string cutter(std::string s)`. – Jesper Juhl Apr 29 '19 at 13:14
  • thanks it worked but i still need each number alone so i can pass it into an array – Yusuf Sameh Apr 29 '19 at 13:16
  • 1
    @JesperJuhl See where you're coming from; however, in place operations for strings are useful sometimes. I'd be tempted to make two versions – Lightness Races in Orbit Apr 29 '19 at 13:18
  • 1
    @JesperJuhl good point, I made an edit to include that possibility. – Blaze Apr 29 '19 at 13:18
  • @YusufSameh you can't have each number alone in one string without delimiting them somehow. Sounds like you want an array or vector of strings each containing one string. As NathanOliver suggested, string streams would be a good way to accomplish this. – Blaze Apr 29 '19 at 13:23
0

If you have , then this is almost trivial:

std::vector<std::string> result;

boost::remove_erase_if(s1, boost::is_any_of("[]"));

boost::split(result, s1, boost::is_any_of(" ;"));

you might want to take a copy of s1 though as it will be mutated in this example.

darune
  • 10,480
  • 2
  • 24
  • 62
0

Below is a solution that uses two functions.

One function returns a new string without [, ] and ;

The other function converts a string with float values to a vector of floats.

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

std::string s1 = "[1 -2.5 3;4 5.25 6;7 8 9.12]";

std::string cutter(std::string &s){
    std::string res = "";
    for (auto c : s)                                 // Loop over all chars in s
    {
        if (c == ';') res += ' ';                    // Replace ; with space
        else if ((c != '[') && (c != ']')) res += c; // Skip [ and ]
    }
    return res;
}

std::vector<float> string_to_floats(std::string &s)
{
      float f;
      std::vector<float> res;

      std::stringstream stream(s);        // Create and initialize the stream
      while(1)
      {
          stream >> f;                    // Try to read a float
          if (stream.fail()) return res;  // If it failed, return the result
          res.push_back(f);               // Save the float in the result vector
      }
}

int main()
{
    std::string s2 = cutter(s1);
    std::cout << s2 << std::endl;

    std::vector<float> values = string_to_floats(s2);
    std::cout << "Number of floats: " << values.size() << std::endl;
    for (auto f : values) std::cout << f << std::endl;

    return 0;
}

Output:

1 -2.5 3 4 5.25 6 7 8 9.12
Number of floats: 9
1
-2.5
3
4
5.25
6
7
8
9.12
Support Ukraine
  • 42,271
  • 4
  • 38
  • 63
0

and here's a regex based solution (c++11 and above):

#include <iostream>
#include <regex>

using namespace std;

string cutter(string src) {
 string out, dlm;
 regex e(R"(-?\d+\.?\d*)");
 smatch m;

 while(regex_search(src,m,e)) {
  for(const auto &x: m) 
   { out += dlm + string(x); dlm = ' '; }
  src = m.suffix().str();
 }

 return out;
}

int main()
{
 string s1 = "[1 -2.5 3;4 5.25 6;7 8 9.12]";

 cout << cutter(move(s1)) << endl;   
 return 0;
}

output:

1 -2.5 3 4 5.25 6 7 8 9.12

Plus, solution based on removal of extra chars (but the first one idiomatically is more preferable):

#include <iostream>
#include <regex>

using namespace std;

string cutter(const string &src) {
 regex e("[ ;]+");
 string out = std::regex_replace(src,e," ");
 return out.substr(1, out.size()-2);
}

int main()
{
 string s1 = "[1 -2.5 3;4 5.25 6;7 8 9.12]";

 cout << cutter(s1) << endl;   
 return 0;
}
Dmitry
  • 1,275
  • 1
  • 5
  • 14