C++中的分割函数

Posted

技术标签:

【中文标题】C++中的分割函数【英文标题】:Splitting function in C++ 【发布时间】:2017-07-26 04:27:28 【问题描述】:

我正在尝试编写一个函数,它将一个字符串和一个分隔符作为输入并返回一个字符串数组。由于某种原因,以下代码遇到分段错误。我想知道可能是什么问题?

char** split(string thing, char delimiter)

    thing+='\0';//add null to signal end of string
    char**split_string = new char*[100];

    int i=0,j=0,l=0; //indexes- i is the ith letter in the string
                    // j is the jth letter in the lth string of the new array
    int length = thing.length();
    while (i < length)
            if ((thing[i]!=delimiter && thing[i]!='\0'))
                    split_string[l][j]=thing[i];
                    j++;
            
            else 
                    j=0; //reset j-value
                    l++;
            
            i++;
    

    return split_string;

【问题讨论】:

为什么不将源字符串“拆分”成字符串向量?为什么要为指针和动态分配而烦恼(特别是如果源字符串中没有 100 个“令牌”)? split_string[l] 是一个未初始化的指针,其中包含一些随机垃圾,指向内存中的某个随机位置。 split_string[l][j]=thing[i] 然后尝试写入该随机内存位置。 你试过用谷歌搜索错误信息吗?了解它的确切含义?然后很容易找到你哪里出错了。 至于“拆分”字符串的一种可能(和 IMO 更简单)方式,请记住 std::getline 可以与任意 分隔符 字符一起使用。 最后,关于您的问题,您分配了一个包含 100 个 指针 的数组,但是您如何让所有这些指针实际指向? 【参考方案1】:

做完之后 char**split_string = new char*[100];

您仍然需要初始化您创建的 100 个 char * 指针中的每一个。

static const size_t str_len = 50; //assuming length will not exceed 
for( size_t ix = 0 ; ix < 100 ; ++ix)
    split_string[ix] = new char[str_len];

您还需要确保在写入 split_string 时不会超过分配的内存,在这种情况下它是 50 并且您没有超过 100 的拆分字符串。

【讨论】:

【参考方案2】:

最好将std::string 拆分为std::vector&lt;std::string&gt;。使用下面的函数

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

std::vector<std::string> split(std::string str, char delim) 
    std::vector<std::string> result;
    std::stringstream ss(str);
    std::string token;
    while (getline(ss, token, delim))
        result.push_back(token);
    return result;

【讨论】:

我猜 OP 正在为 split 函数编写一个实现,而 getline 在内部进行所有检查。【参考方案3】:

1) 当您找到新的子字符串时,请为每个子字符串分配内存(类似于 char[l] = new char[100])。

由于您不知道开头本身的子串数量,请考虑使用向量。考虑使用向量 split_string。在循环中,当您找到一个新的子字符串时,您只需将该字符串推入向量中。最后,您将拥有向量中的所有拆分字符串。

【讨论】:

【参考方案4】:

每个char * 都必须像这样单独初始化。

int len = 100;

char**split_string = new char*[len];  // len holds the number of pointers

for(int k = 0; k < len; k++) 
    split_string[k] = new char[500]; // holds len of string (here Max word size is considered 500)

在 C++ 中,更建议坚持使用 std::string 以降低复杂性并提高可读性。

在找到\0 之前,当您跳出while-loop 时,您的代码将无法 抓住最后一个子字符串。要解决此问题,您需要将 while (i &lt; length) 更改为 while (i &lt;= length)

使用向量

vector<string> split(string thing, char delimiter)
    int len = 100;
    vector<string> v;
    char c[500];
    int i=0,j=0; 
    int length = thing.length();
    while (i <= length)
        if ( thing[i] != delimiter && thing[i] != '\0') 
            c[j]=thing[i];
            j++;
        
        else 
            c[j] = '\0';
            v.push_back(c);
            memset(c, 0, sizeof c);
            j = 0;
        
        i++;
    
    return v;

Demo.

【讨论】:

以上是关于C++中的分割函数的主要内容,如果未能解决你的问题,请参考以下文章

C++实现按指定子串分割母串(split)函数 按空格分割string字符串

C++中的 istringstream 的用法

C++中String类的字符串分割实现

基于 OpenCV C++ 光流的分割代码抛出异常

C++ 分割在 vector.erase() 上失败

C++ 逐行读取文件,然后使用分隔符分割每一行