3

How to convert:

 string x = "1+2+3";

to:

 char y[] = {'1', '2', '3'};

What approach should I do?

2
  • Since you except only one-digit numbers, simple for loop should suffice. What problems have you encountered so far with your attempts? Commented Feb 14, 2021 at 14:28
  • use std::getline on the string, and pass '+' as the delimiter Commented Feb 14, 2021 at 15:07

4 Answers 4

5

The task is to split a string separated by '+'. In the below example, the delimiter ',' is used.

Splitting a string into tokens is a very old task. There are many many solutions available. All have different properties. Some are difficult to understand, some are hard to develop, some are more complex, slower or faster or more flexible or not.

Alternatives

  1. Handcrafted, many variants, using pointers or iterators, maybe hard to develop and error prone.
  2. Using old style std::strtok function. Maybe unsafe. Maybe should not be used any longer
  3. std::getline. Most used implementation. But actually a "misuse" and not so flexible
  4. Using dedicated modern function, specifically developed for this purpose, most flexible and good fitting into the STL environment and algortithm landscape. But slower.

Please see 4 examples in one piece of code.

#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <regex>
#include <algorithm>
#include <iterator>
#include <cstring>
#include <forward_list>
#include <deque>

using Container = std::vector<std::string>;
std::regex delimiter{ "," };


int main() {

    // Some function to print the contents of an STL container
    auto print = [](const auto& container) -> void { std::copy(container.begin(), container.end(),
        std::ostream_iterator<std::decay<decltype(*container.begin())>::type>(std::cout, " ")); std::cout << '\n'; };

    // Example 1:   Handcrafted -------------------------------------------------------------------------
    {
        // Our string that we want to split
        std::string stringToSplit{ "aaa,bbb,ccc,ddd" };
        Container c{};

        // Search for comma, then take the part and add to the result
        for (size_t i{ 0U }, startpos{ 0U }; i <= stringToSplit.size(); ++i) {

            // So, if there is a comma or the end of the string
            if ((stringToSplit[i] == ',') || (i == (stringToSplit.size()))) {

                // Copy substring
                c.push_back(stringToSplit.substr(startpos, i - startpos));
                startpos = i + 1;
            }
        }
        print(c);
    }

    // Example 2:   Using very old strtok function ----------------------------------------------------------
    {
        // Our string that we want to split
        std::string stringToSplit{ "aaa,bbb,ccc,ddd" };
        Container c{};

        // Split string into parts in a simple for loop
#pragma warning(suppress : 4996)
        for (char* token = std::strtok(const_cast<char*>(stringToSplit.data()), ","); token != nullptr; token = std::strtok(nullptr, ",")) {
            c.push_back(token);
        }

        print(c);
    }

    // Example 3:   Very often used std::getline with additional istringstream ------------------------------------------------
    {
        // Our string that we want to split
        std::string stringToSplit{ "aaa,bbb,ccc,ddd" };
        Container c{};

        // Put string in an std::istringstream
        std::istringstream iss{ stringToSplit };

        // Extract string parts in simple for loop
        for (std::string part{}; std::getline(iss, part, ','); c.push_back(part))
            ;

        print(c);
    }

    // Example 4:   Most flexible iterator solution  ------------------------------------------------

    {
        // Our string that we want to split
        std::string stringToSplit{ "aaa,bbb,ccc,ddd" };


        Container c(std::sregex_token_iterator(stringToSplit.begin(), stringToSplit.end(), delimiter, -1), {});
        //
        // Everything done already with range constructor. No additional code needed.
        //

        print(c);


        // Works also with other containers in the same way
        std::forward_list<std::string> c2(std::sregex_token_iterator(stringToSplit.begin(), stringToSplit.end(), delimiter, -1), {});

        print(c2);

        // And works with algorithms
        std::deque<std::string> c3{};
        std::copy(std::sregex_token_iterator(stringToSplit.begin(), stringToSplit.end(), delimiter, -1), {}, std::back_inserter(c3));

        print(c3);
    }
    return 0;
}
Sign up to request clarification or add additional context in comments.

Comments

1

You can use an std::vector<std::string> instead of char[], that way, it would work with more than one-digit numbers. Try this:

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

int main() {
    using namespace std;
    std::string str("1+2+3");
    std::string buff;
    std::stringstream ss(str);
    
    std::vector<std::string> result;
    while(getline(ss, buff, '+')){
        result.push_back(buff);
    }
    
    for(std::string num : result){
        std::cout << num << std::endl;
    }
}

Here is a coliru link to show it works with numbers having more than one digit.

Comments

0

Here are my steps:

  • convert the original string into char*
  • split the obtained char* with the delimiter + by using the function strtok. I store each token into a vector<char>
  • convert this vector<char> into a C char array char*
#include <iostream>
#include <string.h>
#include <vector>
using namespace std;

int main()
{
    string line = "1+2+3";
    std::vector<char> vectChar;
    // convert the original string into a char array to allow splitting
    char* input= (char*) malloc(sizeof(char)*line.size());
    strcpy(input,line.data());
    // splitting the string 
    char *token = strtok(input, "+");

    int len=0;
    while(token) {
        std::cout << *token;
        vectChar.push_back(*token);
        token = strtok(NULL, "+");
    }
    // end of splitting step

    std::cout << std::endl;
    //test display the content of the vect<char>={'1', '2', ...}
    for (int i=0; i< vectChar.size(); i++)
    {
        std::cout << vectChar[i];
    }
    // Now that the vector contains the needed list of char
    // we need to convert it to char array (char*)
    // first malloc
    char* buffer = (char*) malloc(vectChar.size()*sizeof(char));
    // then convert the vector into char*
    std::copy(vectChar.begin(), vectChar.end(), buffer);
    std::cout << std::endl;
    //now buffer={'1', '2', ...}
    // les ut stest by displaying
    while ( *buffer != '\0')
    {
        printf("%c", *buffer);
        buffer++;
    }

}

Comments

0

You can run/check this code in https://repl.it/@JomaCorpFX/StringSplit#main.cpp

Code

#include <iostream>
#include <vector>

std::vector<std::string> Split(const std::string &data, const std::string &toFind)
{
    std::vector<std::string> v;
    if (data.empty() || toFind.empty())
    {
        v.push_back(data);
        return v;
    }
    size_t ini = 0;
    size_t pos;
    while ((pos = data.find(toFind, ini)) != std::string::npos)
    {
        std::string s = data.substr(ini, pos - ini);
        if (!s.empty())
        {
            v.push_back(s);
        }
        ini = pos + toFind.length();
    }
    if (ini < data.length())
    {
        v.push_back(data.substr(ini));
    }

    return v;
}

int main()
{
    std::string x = "1+2+3";
    for (auto value : Split(x, u8"+"))
    {
        std::cout << "Value: " << value << std::endl;
    }
    std::cout << u8"Press enter to continue... ";
    std::cin.get();
    return EXIT_SUCCESS;
}

Output

Value: 1
Value: 2
Value: 3
Press enter to continue...

clang++

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.