Как я могу разделить строку разделителем в массив? - PullRequest
8 голосов
/ 21 мая 2009

Я новичок в программировании. Я пытался написать функцию в C ++, которая разбивает содержимое строки в массив строк с заданным параметром, например:

string str = "___this_ is__ th_e str__ing we__ will use__";

должен возвращать строковый массив:

cout << stringArray[0]; // 'this'
cout << stringArray[1]; // ' is'
cout << stringArray[2]; // ' th'
cout << stringArray[3]; // 'e str'
cout << stringArray[4]; // 'ing we'
cout << stringArray[5]; // ' will use'

Я могу отлично разбить строку на строки, но самое сложное для меня - как я могу указать количество элементов в stringArray перед назначением ему текущей строки токена, а также как вернуть stringArray из функции.

Кто-нибудь покажет мне, как написать функцию?

Edit1: Мне не обязательно, чтобы результаты были в массиве строк, просто в любом контейнере, который я могу вызывать как обычную переменную с некоторой индексацией.

Ответы [ 12 ]

11 голосов
/ 21 мая 2009

Вот моя первая попытка сделать это с использованием векторов и строк:

vector<string> explode(const string& str, const char& ch) {
    string next;
    vector<string> result;

    // For each character in the string
    for (string::const_iterator it = str.begin(); it != str.end(); it++) {
        // If we've hit the terminal character
        if (*it == ch) {
            // If we have some characters accumulated
            if (!next.empty()) {
                // Add them to the result vector
                result.push_back(next);
                next.clear();
            }
        } else {
            // Accumulate the next character into the sequence
            next += *it;
        }
    }
    if (!next.empty())
         result.push_back(next);
    return result;
}

Надеюсь, это даст вам какое-то представление о том, как это сделать. В вашем примере строки она возвращает правильные результаты с этим тестовым кодом:

int main (int, char const **) {
    std::string blah = "___this_ is__ th_e str__ing we__ will use__";
    std::vector<std::string> result = explode(blah, '_');

    for (size_t i = 0; i < result.size(); i++) {
        cout << "\"" << result[i] << "\"" << endl;
    }
    return 0;
}
9 голосов
/ 21 мая 2009

Использование STL (извините, компилятор не тестировался)

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

int main()
{
    std::vector<std::string>   result;

    std::string str = "___this_ is__ th_e str__ing we__ will use__";

    std::stringstream  data(str);

    std::string line;
    while(std::getline(data,line,'_'))
    {
        result.push_back(line); // Note: You may get a couple of blank lines
                                // When multiple underscores are beside each other.
    }
}

// или определить токен

#include <vector>
#include <string>
#include <iterator>
#include <algorithm>
#include <sstream>

struct Token: public std::string  // Yes I know this is nasty.
{                                 // But it is just to demosntrate the principle.    
};

std::istream& operator>>(std::istream& s,Token& t)
{
    std::getline(s,t,'_');

    // *** 
    // Remove extra '_' characters from the stream.
    char c;
    while(s && ((c = s.get()) != '_')) {/*Do Nothing*/}
    if (s)
    {
        s.unget(); // Put back the last char as it is not '_'
    }
    return s;
}

int main()
{   
    std::vector<std::string>   result;

    std::string str = "___this_ is__ th_e str__ing we__ will use__";

    std::stringstream  data(str);

    std::copy(std::istream_iterator<Token>(data),
              std::istream_iterator<Token>()
              std::back_inserter(result)
             );
}
3 голосов
/ 26 ноября 2012

у меня работает:

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

using namespace std;

vector<string> explode( const string &delimiter, const string &explodeme);

int main(int argc, char *argv[])
{
    string str = "I have a lovely bunch of cocoa nuts";
    cout<<str<<endl;
    vector<string> v = explode(" ", str);
    for(int i=0; i<v.size(); i++)
        cout <<i << " ["<< v[i] <<"] " <<endl;
}

vector<string> explode( const string &delimiter, const string &str)
{
    vector<string> arr;

    int strleng = str.length();
    int delleng = delimiter.length();
    if (delleng==0)
        return arr;//no change

    int i=0;
    int k=0;
    while( i<strleng )
    {
        int j=0;
        while (i+j<strleng && j<delleng && str[i+j]==delimiter[j])
            j++;
        if (j==delleng)//found delimiter
        {
            arr.push_back(  str.substr(k, i-k) );
            i+=delleng;
            k=i;
        }
        else
        {
            i++;
        }
    }
    arr.push_back(  str.substr(k, i-k) );
    return arr;
}

источник: http://www.zedwood.com/article/106/cpp-explode-function

1 голос
/ 21 мая 2009

Возможно, вам следует использовать список вместо массива. Таким образом, вам не нужно заранее знать количество элементов. Вы также можете рассмотреть возможность использования контейнеров STL.

1 голос
/ 21 мая 2009

Используйте std :: vector в качестве динамического массива и верните его в качестве результата.

1 голос
/ 21 мая 2009

Вы можете использовать вектор строки (std::vector<std::string>), добавлять каждый токен к нему с помощью push_back и затем возвращать его из функции токена.

1 голос
/ 21 мая 2009

Если вы настаиваете на создании stringArray массива в противоположность std::vector<> (что было бы правильно), вы должны либо:

  1. Сделайте два прохода (один на счет, видите ли)
  2. Реализуйте динамический массив самостоятельно.

Использовать вектор проще vector::push_back() добавляет новый материал в конец. Итак:

vector* explode(string s){
  vector<string> *v = new vector<string>
  //...
  // in a loop
    v->push_back(string_fragment);
  //...
  return v;
}

В конце концов, не требуется Оставлено для полноты.

Для возврата массива строк вы используете char **.

Как и в

char ** explode(const char *in){
  ...

}

Кстати: как вызывающая функция узнает, сколько элементов находится в возвращаемом массиве? Тебе тоже придется это решить. Используйте std::vector<>, если вы не ограничены внешними силами ...

0 голосов
/ 27 апреля 2017

Это сработало для меня:

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

using namespace std;

vector<string> split(string str, char delimiter) {
  vector<string> internal;
  stringstream ss(str); // Turn the string into a stream.
  string tok;

  while(getline(ss, tok, delimiter)) {
    internal.push_back(tok);
  }

  return internal;
}

int main(int argc, char **argv) {
  string myCSV = "one,two,three,four";
  vector<string> sep = split(myCSV, ',');

  // If using C++11 (which I recommend)
  /* for(string t : sep)
   *  cout << t << endl;
   */

  for(int i = 0; i < sep.size(); ++i)
    cout << sep[i] << endl;
}

Источник: http://code.runnable.com/VHb0hWMZp-ws1gAr/splitting-a-string-into-a-vector-for-c%2B%2B

0 голосов
/ 02 октября 2015

Я думаю, что написал гораздо более простое решение.

std::vector<std::string> explode(const std::string& string, const char delimiter) {

std::vector<std::string> result;
unsigned int start = 0, pos = 0;

while (pos != string.length()) {
    if (string.at(pos) == delimiter || pos + 1 == string.length()) {
        unsigned int size = (pos - start) + ((pos + 1) == string.length() ? 1 : 0);
        if (size != 0) { // Make this 'if' as a option? like a parameter with removeEmptyString?
            result.push_back(string.substr(start, size));
        }
        start = pos + 1;
    }
    pos++;
}

return std::move(result);

}

0 голосов
/ 21 ноября 2013

Вот мой готовый код (завершено). Может быть, это полезно для некоторых с такой же потребностью.

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

int main(){
        std::string s = "scott:tiger:mushroom";
        std::string delimiter = ":";

        std::vector<std::string> outputArr;
        size_t pos = 0;
        std::string token;
        while ((pos = s.find(delimiter)) != std::string::npos) {
            token = s.substr(0, pos);
            s.erase(0, pos + delimiter.length());
            outputArr.push_back(token);
        }
        outputArr.push_back(s);

        // Printing Array to see the results
        std::cout<<"====================================================================================\n";
        for ( int i=0;i<outputArr.size();i++){
                std::cout<<outputArr[i]<<"\n";
        }
        std::cout<<"====================================================================================\n";
}

Ура !! * * 1004

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...