【问题标题】:Get a non-const iterator from a const string parameter从 const 字符串参数获取非常量迭代器
【发布时间】:2020-11-28 09:25:26
【问题描述】:

我正在使用以下语法读取字符串:

string example {"firstList:[element1:value1,element2:value2];secondList:[elementA:valueA,elementB:valueB]"};

因为一个真正的列表可以有数百个元素,而我只需要读取操作(检查value1 == "something"elementA 是否存在),我实现了一个基于std::string::iterator 的函数来查找给定字符串中的列表。这是一个简化的版本:

bool findList(
    const std::string &input,
    const std::string &listName,
    std::string::iterator globalStart,
    std::string::iterator globalEnd,
    std::string::iterator &listStart,
    std::string::iterator &listEnd
    )
{
    if (input.empty() || listName.empty()) return false;

    size_t inicio = input.find(listName);
    if (inicio == string::npos) return false;

    size_t fin = input.find("]", inicio);
    if (fin == string::npos) return false;

    listStart = globalStart + inicio + listName.length() + 2;
    listEnd = globalStart + fin;
    if (listEnd >= globalEnd) return false;

    string::iterator badList = std::find(listStart, listEnd, ';');
    if (badList != listEnd) return false;

    return true;
}

该函数有效,但我必须传递字符串inputinput.begin()input.end() 来为列表迭代器分配值。是否有其他选项可以将input.begin() 分配给listStartlistEnd 也是如此)?

写作:

    listStart = input.begin() + inicio + listName.length() + 2;
    listEnd = input.begin() + fin;

尝试将 const 迭代器分配给非 const 迭代器会产生编译器错误:

error: no match for ‘operator=’ (operand types are ‘std::__cxx11::basic_string<char>::iterator {aka __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >}’ and ‘__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >’)
  listStart = input.begin() + inicio + listName.length() + 2;

我知道仅将input 传递为std::string &amp;input 可以解决问题,但我想保留const 所需的检查。

这是一个最小的例子:


#include <iostream>
#include <string>
#include <algorithm>
#include <assert.h>

using std::cout;
using std::endl;
using std::string;
using std::size_t;

bool findList(
    const std::string &input,
    const std::string &listName,
    std::string::iterator globalStart,
    std::string::iterator globalEnd,
    std::string::iterator &listStart,
    std::string::iterator &listEnd
    )
{
    if (input.empty() || listName.empty()) return false;

    size_t inicio = input.find(listName);
    if (inicio == string::npos) return false;

    size_t fin = input.find("]", inicio);
    if (fin == string::npos) return false;

    listStart = globalStart + inicio + listName.length() + 2;
    listEnd = globalStart + fin;
    if (listEnd >= globalEnd) return false;

    string::iterator badList = std::find(listStart, listEnd, ';');
    if (badList != listEnd) return false;

    return true;
}

int main() {
    string example {"firstList:[element1:value1,element2:value2];secondList:[elementA:valueA,elementB:valueB]"};
    string::iterator listStart, listEnd;
    bool answer = false;

    // Test the findList function
    answer = findList(example, "firstList", example.begin(), example.end(), listStart, listEnd);
    assert(answer == true);
    assert(string(listStart, listEnd) == "element1:value1,element2:value2");
    cout << "Test firstList passed" << endl;

    answer = findList(example, "secondList", example.begin(), example.end(), listStart, listEnd);
    assert(answer == true);
    assert(string(listStart, listEnd) == "elementA:valueA,elementB:valueB");
    cout << "Test secondList passed" << endl;

    answer = findList(example, "thirdList", example.begin(), example.end(), listStart, listEnd);
    assert(answer == false);
    assert(string(listStart, listEnd) == "elementA:valueA,elementB:valueB"); // iterators remain unchanged
    cout << "Test thirdList passed" << endl;

    return 0;
}

*这是我的第一个问题,请随时指出我可以对帖子做出的任何改进。

【问题讨论】:

  • 我无法重现编译器错误。好像是work
  • 我贴出编译的版本,this重现编译错误。

标签: c++ c++11 stdstring const-iterator


【解决方案1】:

const std::string::iterator 表示“字符串的迭代器,通过它可以改变字符串;迭代器不能指向其他任何地方。”

std::string::const_iterator 表示“字符串的迭代器,通过它不能改变字符串;迭代器可以指向其他地方。”

看起来你混淆了这两个。当inputconst 时,input.begin() 返回一个const_iterator,并且您不能将const_iterator 分配给iterator——这会破坏常量正确性。

你在这个函数中的所有迭代器都应该是const_iterator。将您的函数签名更改为:

bool findList(
    const std::string &input,
    const std::string &listName,
    std::string::const_iterator globalStart,
    std::string::const_iterator globalEnd,
    std::string::const_iterator &listStart,
    std::string::const_iterator &listEnd
) {
    // ...
}

然后调用者应该使用str.cbegin()str.cend()。同样,main() 中的 listStartlistEnd 应更改为 const_iterator

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-20
    • 2013-09-13
    • 1970-01-01
    相关资源
    最近更新 更多