C++ equivalent for PHP's explode() function

Echo89 0 Tallied Votes 974 Views Share

Well, I have just made this funtion that will split an array using a delimiter. I'm new to C++ so I will take any suggestions you have.

Anyhow, good luck! Enjoy!

#include <iostream>
#include <string>
#include <vector>
#include <stdlib.h>

using namespace std;

vector<string> explode(string del, string str)
{
	int slen = str.length();
	int dlen = del.length();
	int found_a;
	string before;
	vector<string> final;
	vector<string> fail (0);

	if(dlen == 0) return fail;
	if(slen == 0) return fail;

	for(int counter = 0; counter < slen; counter ++)
	{
		found_a = str.find(del);
		if(found_a != string::npos)
		{
			before = str.substr(0, found_a + dlen);
			final.push_back(before);
			str.replace(0, found_a + dlen, "");
		}
		else
		{
			if(str.length() > 0)
			{
				final.push_back(str);
				str.replace(0, str.length(), "");
			}
			else
			{
				break;
			}
		}
	}
	return final;
}
Echo89 9 Web Developer

I just realized a bug, will fix this tomorrow.

Lucaci Andrew 140 Za s|n

I like your ideea. Here's what I have cooked up in 5 minutes:

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

vector<string> explode(string inputstring, string delimiter){
    vector<string> explodes;
    inputstring.append(delimiter);
    while(inputstring.find(delimiter)!=string::npos){
        explodes.push_back(inputstring.substr(0, inputstring.find(delimiter)));
        inputstring.erase(inputstring.begin(), inputstring.begin()+inputstring.find(delimiter)+delimiter.size());
    }
    return explodes;
}

int main(){
    string a="a23<del>b345<del>b657<del>c65", delimiter="<del>";
    vector<string> explodes=explode(a, delimiter);
    for (int i=0;i<(int)explodes.size();i++){
        cout<<explodes[i]<<" ";
    }
    return 0;
}
Echo89 9 Web Developer

Wow, thanks a lot man, that's a lot better!

Echo89 9 Web Developer

However you would need this after the while loop so that it picks up the rest of the string:

if(inputstring.length() > 0)
{
    explodes.push_back(inputstring);
    str.erase(0, inputstring.length());
}

EDIT: I just realised that you fixed that.

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

Neither of those are an equivalent to PHP's explode(). To do it thoroughly you'd need to include all of the logic for the limit and any edge cases that affect the result. I hacked this up pretty quickly from the PHP manual's definition, but it should be close:

#include <cstdlib>
#include <limits>
#include <stdexcept>
#include <string>
#include <vector>

std::vector<std::string> explode(
    std::string delimiter, 
    std::string source, 
    int limit = std::numeric_limits<int>::max())
{
    // PHP returns FALSE in this case, but C++ doesn't handle variant types well, and a
    // reasonable facsimile of FALSE is tricky with std::vector<>, so we'll just throw.
    if (delimiter.empty())
        throw std::invalid_argument("Empty delimiter in explode()");

    // Sanitize the limit to something meaningful
    if (limit == 0)
        limit = 1;

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

    // Handle the simple case of zero delimiter matches
    if (source.find(delimiter) == std::string::npos) {
        // PHP returns array() if limit is negative, array(source) if limit is positive
        if (limit > 0)
            result.push_back(source);

        return result;
    }

    std::vector<std::string>::size_type begin = 0;
    std::vector<std::string>::size_type end = 0;

    // Explode up to any positive limit, exclusive
    while (end != std::string::npos) {
        if (limit > 0 && result.size() == limit - 1) {
            // PHP populates the last element (ie. result[limit - 1]) with the remaining 
            // string when limit is positive and less than the number of total tokens.
            result.push_back(source.substr(begin));
            break;
        }

        /*
            Conventional C++ manual string tokenization.
        */
        std::vector<std::string>::size_type substr_len = std::string::npos;
        std::vector<std::string>::size_type next_tok = std::string::npos;

        end = source.find_first_of(delimiter, begin);

        if (end != std::string::npos) {
            substr_len = end - begin;
            next_tok = end + delimiter.size();
        }

        result.push_back(source.substr(begin, substr_len));
        begin = next_tok;
    }

    // Negative limits trim that amount from the right side of the result. It's
    // easier to do this after the explode loop because we don't need to retain
    // unexploded parts of the string like with a positive limit.
    if (limit < 0) {
        limit = abs(limit);

        if (limit < result.size())
            result.resize(result.size() - limit);
        else {
            // PHP returns array() if all items or more would be trimed
            result.clear();
        }
    }

    return result;
}
vijayan121 1,152 Posting Virtuoso

deleted

Echo89 9 Web Developer

Good one, thanks! That's even better once again.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.