C++ 如何通过分隔符将字符串拆分为数组?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/890164/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 17:48:16  来源:igfitidea点击:

How can I split a string by a delimiter into an array?

c++functionstring

提问by Babiker

I am new to programming. I have been trying to write a function in C++ that explodes the contents of a string into a string array at a given parameter, example:

我是编程新手。我一直在尝试用 C++ 编写一个函数,它将字符串的内容分解为给定参数的字符串数组,例如:

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

should return string array:

应该返回字符串数组:

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'

I can tokenize the string just fine, but the hardest part for me is how can i specify the number of elements in stringArray before assigning it the current string toke and also how to return stringArray from the function.

我可以很好地标记字符串,但对我来说最困难的部分是如何在将 stringArray 分配给当前字符串标记之前指定 stringArray 中的元素数量以及如何从函数返回 stringArray。

Would someone show me how to write the function?

有人会告诉我如何编写函数吗?

Edit1:I don't necessarily need the results to been in string array just any container that i can call as a regular variable with some sort of indexing.

Edit1:我不一定需要将结果放在字符串数组中,只是我可以将其作为具有某种索引的常规变量调用的任何容器。

回答by Eric Scrivner

Here's my first attempt at this using vectors and strings:

这是我第一次尝试使用向量和字符串:

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;
}

Hopefully this gives you some sort of idea of how to go about this. On your example string it returns the correct results with this test code:

希望这能给你一些关于如何去做的想法。在您的示例字符串中,它使用以下测试代码返回正确的结果:

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;
}

回答by Martin York

Using STL (sorry no compiler not tested)

使用 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.
    }
}

// or define a token

// 或定义一个令牌

#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)
             );
}

回答by Ouadie

It works for me :

这个对我有用 :

#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;
}

source :http://www.zedwood.com/article/106/cpp-explode-function

来源:http : //www.zedwood.com/article/106/cpp-explode-function

回答by dmckee --- ex-moderator kitten

If you insist on making stringArrayan array as oppossed to a std::vector<>(which would be the right thing to do) you have to either:

如果您坚持要制作stringArray一个与 a 相对的数组std::vector<>(这是正确的做法),您必须:

  1. Make two passes (one to count, you see)
  2. Implement a dynamic array yourself.
  1. 进行两次传球(一次计数,你看)
  2. 自己实现一个动态数组。

Using a vector is easier vector::push_back()appends new stuff to the end. So:

使用向量更容易vector::push_back()将新内容附加到末尾。所以:

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


Not needed after allLeft in for completeness.

毕竟不需要为了完整起见。

To return the array of strings you use char **.

要返回您使用的字符串数组char **

As in

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

}

BTW-- How will the calling function know how many elements are in the returned array? You'll have to solve that too. Use std::vector<>unless you are constrained by outside forces...

顺便说一句——调用函数如何知道返回数组中有多少元素?你也必须解决这个问题。std::vector<>除非您受到外力约束,否则请使用...

回答by Jem

You can use a vector of string (std::vector<std::string>), append each token to it with push_back, and then return it from your tokenize function.

您可以使用 string (std::vector<std::string>)向量,使用 push_back 将每个标记附加到它,然后从您的标记化函数返回它。

回答by workmad3

Use std::vector as a dynamic array and return that as your result.

使用 std::vector 作为动态数组并将其作为结果返回。

回答by user79755

Perhaps you should use a list instead of an array. That way you would not need to know the number of elements ahead of time. You may also consider using the STL containers.

也许您应该使用列表而不是数组。这样你就不需要提前知道元素的数量。您也可以考虑使用 STL 容器。

回答by JasonRShaver

Wait until your data structures class and then code it with a linked list. If it is for homework though, you may be able to get away with just initing the array be very large.

等到您的数据结构类,然后使用链表对其进行编码。但是,如果是为了作业,您可能只需将数组初始化为非常大就可以逃脱。

回答by Paulo Lellis

The code below:

下面的代码:

template <typename OutputIterator>
int explode(const string &s, const char c, OutputIterator output) {
    stringstream  data(s);
    string line;
    int i=0;
    while(std::getline(data,line,c)) { *output++ = line; i++; }
    return i;
}

int main(...) {
  string test="H:AMBV4:2:182.45:182.45:182.45:182.45:182.41:32:17700:3229365:201008121711:0";
  cout << test << endl; 
  vector<string> event;
**This is the main call**
  int evts = explode(test,':', back_inserter(event));
  for (int k=0; k<evts; k++) 
    cout << event[k] << "~";
  cout << endl;
}

Outputs

输出

H:AMBV4:2:182.45:182.45:182.45:182.45:182.41:32:17700:3229365:201008121711:0
H~AMBV4~2~182.45~182.45~182.45~182.45~182.41~32~17700~3229365~201008121711~0~

回答by Vivek

Here is my cooked up code (complete). May be it's useful for some with the same need.

这是我编写的代码(完整)。可能对一些有相同需求的人有用。

#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";
}

Cheers!!

干杯!!