0

我正在尝试创建一个函数将字符串“Split At Spaces”拆分为一个包含“Split”“At”“Spaces”的向量。到目前为止,这是我得到的代码。

#include <iostream>
#include <utility>
#include <algorithm>

using namespace std;

std::vector<std::string> split(std::string * s, char * tosplit) 
{
    size_t i = 0;
    int count = 0;
    size_t contain;
    std::vector<std::string> split;

    std::cout << "Start" << std::endl;
    std::cout << *s << std::endl;
    std::cout << *tosplit << std::endl;

    while((contain = s->find(*tosplit,i)) != std::string::npos)
    {
        count++;
        i = contain + 1;
    }

    std::cout << "Contains " << count << std::endl;

    if (count == 0)
    {
        std::cout << "Equals 0" << std::endl;
        split = std::vector<std::string>(1);
        split.at(0) = s->c_str();
        return split;
    }

    split = std::vector<std::string>(count + 1);
    split.begin();

    int lasti;
    i = s->find_first_of(*tosplit);
    split.at(0) = s->substr(0, i);
    lasti = i;
    int runs = 1;

    while (runs <= count) 
    {
        i = s->find(*tosplit, lasti + 1);
        std::cout << i << " " << lasti << std::endl;
        split.at(runs) = s->substr(lasti, --i);
        runs++;
        lasti = i;
    }

    split.at(runs) = s->substr(lasti, s->size());

    std::cout << "done, result is" << std::endl;
    i = 0;
    while (i < split.capacity()) 
    {
        std::cout << split.at(i) << std::endl;
        i++;
    }

    return split;
}

它抛出一个 out_of_range 异常。您可以提供的任何帮助将不胜感激。这就像我在函数中使用指针的第一部分,所以我在这里有点猜测。
谢谢!

请不要建议使用 x 或 y 方法,我想写我自己的,因为我这样做是为了体验。

4

5 回答 5

1

这实际上很容易使用例如std::istringstreamand以及来自标准迭代器库std::copy的一些帮助来完成。

对于那些想要查看工作代码的人,可以在这里找到。

对于链接中的代码,整个程序18行,其中实际拆分为3行但那是因为我将其拆分为使其更具可读性(实际上是单个函数调用)。


对于更通用的解决方案,如果 C++11正则表达式可用(或Boost regex或其他一些可用的正则表达式库),则可以使用。

于 2013-02-01T21:47:09.167 回答
1

以下是我发现的一些问题:

  1. s在检查 NULL 指针之前取消引用。
  2. tosplit在检查 NULL 之前取消引用。
  3. 不要计算字符串的数量,然后拆分字符串(需要 2 次搜索),而是在搜索时计算。
  4. 当您将其传递给循环中的表达式时,该位置i = contain + 1可能超出范围。while
  5. 尝试使用该方法std::vector::push_back,而不是在特定的(可能未分配的)位置进行分配。
  6. 该语句return split返回字符串数组的副本。你真的要返回一个大的数据结构吗?
  7. 该语句split.begin()将一个迭代器返回到向量的开头;你不使用的。
  8. split.size()不使用split.capacity。它们是两个不同的概念。
于 2013-02-01T22:02:20.927 回答
0

与其尝试为您的向量预先分配空间,不如使用 push_back 在您找到它们时附加这些部分。

于 2013-02-01T21:47:14.217 回答
0

对不起,但我不禁认为您的功能过于复杂。如果你想自己编写逻辑来学习而不是使用一些预先打包的功能,那很好,但这并不意味着你不应该保持你的逻辑简单

我相信您的算法应该看起来更像这样:

// Note that the delimiter can be a string as well, not just a char
vector<string> split(string const& s, string const& delimiter)
{
    vector<string> result;

    string::size_type startPos = 0;
    string::size_typepos = s.find(delimiter);
    while (pos != string::npos)
    {
        // Extract token and save it...
        string token = s.substr(startPos, pos - startPos);
        result.push_back(token);

        // Step to next token...
        startPos = pos + 1;
        pos = s.find(delimiter, pos + 1);
    }

    // Parse last token (in case the string is not terminated
    // by the delimiter).
    if (startPos < s.length())
    {
        string lastToken = s.substr(startPos);
        result.push_back(lastToken);
    }

    return result;
}
于 2013-02-01T21:48:57.853 回答
0

单定界符:

你写了太多的代码来做到这一点。您可以在几行内完成。你变得非常复杂。并且没有理由为此真正使用指针做任何事情。

vector<string> Split(string s, char delim)
{
    vector<string> strings;
    for(istringstream ss(s); getline(ss, s, delim); strings.push_back(move(s)));
    return strings;
}

多个分隔符:

使用多个分隔符的解决方案更加复杂。您不能再利用 of getline,这意味着您基本上是在getline自己编写 's 的部分功能。但是,它仍然可以很短。

vector<string> Split(const string& s, const char* delims)
{
    vector<string> strings;

    for(string::size_type start = 0, end; end != string::npos && start < s.size(); start = end+1)
    {
        end = s.find_first_of(delims, start);
        strings.push_back(s.substr(start, end-start));
    }

    return strings;
}

当分隔符彼此相邻时,这将添加空白字符串。如果这不是相邻分隔符的期望行为,则可以通过保护push_backwith轻松避免这种情况if(start != end)

结论:

当您开始编写像这样的低级算法时,请在广义上对其进行伪代码,然后在编写任何代码之前检查 C++ 标准库可以提供哪些内容来删除部分或全部工作。您最终会得到更小、更不容易出错且更易于理解的代码。例如,没有人希望看到手动实现find_first_of。看字就清楚多了find_first_of。很清楚该功能将要做什么,并且它没有错误(希望如此)。

于 2013-02-01T22:23:29.883 回答