【问题标题】:I'm having difficulties splitting a string into a vector我很难将字符串拆分为向量
【发布时间】:2020-01-26 01:46:53
【问题描述】:

我正在尝试编写代码,通过在每个空格字符处拆分字符串来将字符串初始化为向量。不知何故,临时向量不会占据位置,也不会正确拆分字符串。

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

std::vector<std::string> splitStr(std::string s, char cut = 32) {
    std::string temp = s;
    int begin = 0;
    std::vector<std::string> v;
    for (int i = 0; i < temp.length() - 1; ++i) {
        if ((int) cut == (int) temp[i]) {
            v.push_back(temp.substr(begin, i));
            begin = i + 1;
        }
    }
    return v;
}


using namespace std;


int main() {

    for (string e : splitStr("Hello this is a test!", ' ')) {
        cout << e << endl;
    }

}

我认为附加到向量时会出错,但我不明白为什么会这样。 谁能告诉我我做错了什么?

【问题讨论】:

  • 查看this了解如何用空格分割字符串
  • 感谢您的帮助,但我仍然希望我的代码能够正常工作。
  • std::string::substr 的第二个参数是长度。这意味着您需要将v.push_back(temp.substr(begin, i)); 更改为v.push_back(temp.substr(begin, i - begin));,然后您当然需要处理最后一句话。
  • 我完全错了,非常感谢!
  • 我马上看到 2 个问题:如果有相邻空格,您的代码会将空字符串推送到向量中 + 最后一个单词永远不会添加到向量中

标签: c++ string vector split push-back


【解决方案1】:

substr 的第二个参数是你想从原始字符串中选择的字符数,如果没有传递,它将取所有字符直到字符串结尾。这是您的更正代码:

  std::vector<std::string> splitStr(std::string s, char cut = 32) {
    std::string temp = s;
    int begin = 0;
    // Remove multiple spaces based on logic described here : https://stackoverflow.com/questions/8362094/replace-multiple-spaces-with-one-space-in-a-string
    std::string::iterator new_end = std::unique(temp.begin(), temp.end(), [](char one,char two) { return (one == two) && (one == ' '); } );
    temp.erase(new_end, temp.end());
    std::vector<std::string> v;
    for (int i = 0; i < temp.length() - 1; ++i) {
        if ((int) cut == (int) temp[i]) {
            v.push_back(temp.substr(begin, i-begin));
            begin = i + 1;
        }
    }
    v.push_back(temp.substr(begin));
    return v;
}
    using namespace std;


    int main() {

        for (string e : splitStr("Hello this is a test!", ' ')) {
            cout << e << endl;
        }

    }

【讨论】:

  • 如果有两个或多个相邻空格,这将不会给出预期的结果。
  • 我在原始评论部分询问了 OP,如果遇到两个或更多空格,他们希望将什么显示为输出。
  • @PaulMcKenzie 感谢您的评论,实施了您建议的更改
【解决方案2】:

对于初学者来说,不要使用像 32 这样的幻数。

其次,制表符也可以视为空白分隔符。第一个参数应该是对字符串的 const 引用。

无需在函数内创建参数的副本。

这个循环

for (int i = 0; i < temp.length() - 1; ++i) {
    if ((int) cut == (int) temp[i]) {
        v.push_back(temp.substr(begin, i));
        begin = i + 1;
    }
}

没有意义。例如,一个字符串可以包含两个连续的空格。其次,调用 substr temp.substr(begin, i) 的第二个参数无效。它应指定子字符串的长度,

使用std::string类的标准搜索成员函数代替循环。

这是一个演示程序,展示了如何实现该功能。

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

std::vector<std::string> splitStr( const std::string &s, 
                                   const std::string &delim = " \t" )
{
    std::vector<std::string> v;

    for ( std::string::size_type pos = 0, n = 0;
          ( pos = s.find_first_not_of( delim, pos ) ) != std::string::npos; 
          pos += n )
    {
        n = s.find_first_of( delim, pos );

        n = ( n == std::string::npos ? s.size() : n ) - pos;

        v.push_back( s.substr( pos, n ) );
    }

    return v;
}

int main() 
{
    for ( const auto &s : splitStr( "Hello this is a test!" ) )
    {
        std::cout << s << std::endl;
    }

    return 0;
}

它的输出是

Hello
this
is
a
test!

【讨论】:

    【解决方案3】:

    在每个空格字符处分割它

    这将在 每个 空格字符处拆分它。我已经评论了代码的变化。

    #include <iostream>
    #include <string>
    #include <vector>
    
    // don't use magic numbers like 32 for space. Use a literal space: ' '
    
    // Instead of copying the string (potentially twice), use a reference to
    // your input parameter and make it const if you are not going to change it.
    
    std::vector<std::string> splitStr(const std::string& temp, char cut = ' ') {
        // Use types designed for the task to avoid casting, like
        // size_t for most indexing tasks.
        size_t begin = 0;
        std::vector<std::string> v;
    
        // with temp.length()-1 you won't capture a space at the very end
        for(size_t i = 0; i < temp.length(); ++i) {
            if(cut == temp[i]) {
                // the second argument to substr is the length of the sub string
                v.push_back(temp.substr(begin, i - begin));
                begin = i + 1;
            }
        }
        // add the remaining part of the string
        v.push_back(temp.substr(begin));
        return v;
    }
    
    // using namespace std; // don't do this globally
    
    int main() {
        // added double spaces between words and one at the end for effect
        for(const std::string& e : splitStr("Hello  this  is  a  test! ", ' ')) {
            // added > and < around the words to see what you captured
            std::cout << '>' << e << '<' << std::endl;
        }
    }
    

    输出:

    >Hello<
    ><
    >this<
    ><
    >is<
    ><
    >a<
    ><
    >test!<
    ><
    

    【讨论】:

    • 这让我成为了一个更好的程序员,感谢我所付出的努力。
    猜你喜欢
    • 2020-11-08
    • 2014-01-16
    • 1970-01-01
    • 2014-10-21
    • 2015-11-30
    • 1970-01-01
    • 2014-09-16
    • 2014-09-27
    • 2016-04-18
    相关资源
    最近更新 更多