1

I have a string of data that looks like

string line = "Number:Description:Price:Weight";

I want to separate the string into 4 different variables via the delimiter ":". I was trying this via the substring method

char delimiter = ':';
string number = line.substr(0, line.find(delimiter));

It works fine for the first variable. However, I am unable to figure out how to iterate to the next instance of the ":" for the other variables.

Jon
  • 77
  • 1
  • 1
  • 8

4 Answers4

1

std::string::find() takes a starting index as an optional parameter:

string line = "Number:Description:Price:Weight";
string::size_type start, end;
char delimiter = ':';

end = line.find(delimiter);
string number = line.substr(0, end);

start = end + 1;
end = line.find(delimiter, start);
string desc = line.substr(start, end-start);

start = end + 1;
end = line.find(delimiter, start);
string price = line.substr(start, end-start);

string weight = line.substr(end + 1);

Alternatively, you can split the string on delimiters by using std::istringstream with std::getline():

string line = "Number:Description:Price:Weight";
string number, desc, price, weight;
char delimiter = ':';

istringstream iss(line);
getline(iss, number, delimiter);
getline(iss, desc, delimiter);
getline(iss, price, delimiter);
getline(iss, weight);
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
0

It is much easier with a simple for loop:

#include <iostream>
#include <vector>

int main()
{
    std::string line = "Number:Description:Price:Weight";

    std::vector<std::string> vecStrings;
    std::string word;
    size_t count = 0;

    for (auto const& it : line)
    {
        if (it != ':') word += it;

        if ((it == ':') || (count + 1 == line.size()))
        {
             vecStrings.emplace_back(word);
             word.clear();
        }
        ++count;
    }

    for(const auto& it: vecStrings) 
        std::cout << it << "\n";

    return 0;
}

See live action: https://www.ideone.com/DiAvjO

Update: If you need something different, you can do the same thing with std::for_each() and a lambda:

#include <algorithm>

std::for_each(std::begin(line), std::end(line), [&](char &letter)
{
    if (letter != ':') word += letter;
    if ((letter == ':') || (count + 1 == line.size()))
    {
        vecStrings.emplace_back(word);
        word.clear();
    }
    ++count;
});

However, a much simpler solution to this would be to use std::istringstream. Thanks to RemyLebeau for pointing out this:

#include <sstream>

std::stringstream sstr(line);
std::string word;

while (std::getline(sstr, word, ':'))
{
    vecStrings.emplace_back(word);
} 
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
JeJo
  • 30,635
  • 6
  • 49
  • 88
0

you can make use of strtok like below

#include <string.h>
int main()
{
    char line[] = "Number:Description:Price:Weight";

    char * token = std::strtok (line,":");

    while (token != NULL)
    {
        cout << token << '\n';
        token = std::strtok(NULL, ":");
    }
    return 0;
}

Make necessary changes as per your need

Maddy
  • 774
  • 5
  • 14
-2

cstring has strtok that does exactly what you want.

Eric Yang
  • 2,678
  • 1
  • 12
  • 18