【问题标题】:Unable to have concatenated string in vector of strings when tried to concat using dereferenced iterator尝试使用取消引用的迭代器连接时,无法在字符串向量中连接字符串
【发布时间】:2018-04-09 06:16:26
【问题描述】:

我的意图是拥有一个包含给定字符串的所有子字符串的向量。我试图通过将向量中的当前字符串与 str

的迭代字符连接来推送元素

下面的代码出了什么问题。

void Substring(string str)
{
    vector<string> vec={""};
    for(auto i =0; i<str.length(); i++)
    {
        auto end = vec.end();
        string s(1,str[i]);
        for (auto iter = vec.begin(); iter!=end; iter++)
        {
            vec.push_back(s+ static_cast<string>(*iter)); // --> what is the problem here in concatenation
        }
    }
    for (auto iter = vec.begin(); iter!=vec.end(); iter++)
    {
        cout <<"iter_val:"<<*iter <<endl; //--> does not print concated element
    }
}

【问题讨论】:

  • 您的预期输出和输入 str 格式是什么?
  • 如果向量的存储被重新分配(当您push_back 时可能会经常发生这种情况),那么 所有 迭代器将失效。
  • 在一个不相关的注释上:*iter 已经是 std::string,你不需要转换它。
  • @codekaizer :我只想将 str 的子字符串放入向量中并显示它。
  • 对于可能的解决方案,请改用 size,并使用索引进行迭代。

标签: c++ c++11 stl iterator


【解决方案1】:

vec.push_back invalidates existing iterators。您可能想更改算法以避免这种情况,例如:

std::vector<std::string> substrings(std::string const& s) {
    std::vector<std::string> result;
    for(size_t i = 0, j = s.size(); i < j; ++i)
        for(size_t k = 1, l = j - i - !i; k <= l; ++k)
            result.push_back(s.substr(i, k));
    return result;
}

int main() {
    for(auto const& s : substrings("abc"))
        std::cout << s << '\n';
}

【讨论】:

  • 如果您分享会有所帮助,push_back如何使迭代器无效。我对我得到的输出感到很困惑。我的代码提供的是未定义的输出吗?输出->我发现它每次都与“”连接,但保持迭代次数,否则我会期望无限迭代
  • 哈哈。起初我以为有一个错误,因为它不会在子字符串中打印字符串本身。然后!我看到了,而不是错误,功能。
  • @ceasif 它通过设计使迭代器无效。阅读std::vector::push_back
  • 很好,但我不认为像 l = j - i - !i 这样的构造是“可维护的好代码”;)
  • @JHBonarius 好的设计不是没有什么可添加的,而是没有什么可删除的。
【解决方案2】:

这是一个按长度递减顺序列出子字符串的方法。

#include <vector>
#include <string>

static
std::vector<std::string> 
substrings(const std::string &str) {
    std::vector<std::string> subs;
    const auto m = str.length();
    for (size_t N = m; N > 0; --N) {
        for (size_t i = 0; i <= m-N; ++i) {
            subs.push_back(str.substr(i, N));
        }
    }
    return subs;
}

int main() {
    for(const auto &s : substrings("foobar"))
        std::cout << s << ' ';
}

大声说出来:

foobar 富巴 欧巴 傻瓜 大叶 奥巴尔 富 oob 欧巴 酒吧 佛 哦 ob 巴 阿尔 F ○ ○ b 一种 r

即将推出您附近的编译器... 没有向量,没有 std::strings,没有复制!

#include <generator>
#include <string_view>

std::generator<std::string_view>
substrings(std::string_view const s) {
    const auto m = s.length();
    for (size_t N = m; N > 0; --N) {
        for (size_t i = 0; i <= m-N; ++i) {
             co_yield s.substr(i, N);
        }
    }
}

int main() {
    for (auto const s : substrings("foobar")) {
        std::cout << s << ' ';
    }
}

【讨论】:

    【解决方案3】:

    使用 size() 代替迭代器

    void Substring(string str)
    {
        vector<string> vec={""};
        for(auto i =0; i<str.length(); i++)
        {
            auto size = vec.size();
            string s(1,str[i]);
            for (auto iter = 0; iter<size; iter++)
            {
                vec.push_back(vec[iter]+s);
            }
        }
        for (auto iter = vec.begin(); iter!=vec.end(); iter++)
        {
            cout <<"iter_val:"<<*iter <<endl; 
        }
    }
    

    【讨论】:

    • 不要使用using namespace std。并且不要忽略编译器警告:iint 类型,而 str.length() 返回 size_t 类型,因此比较它们将返回警告。你确定你也想考虑一个空字符串吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-01-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多