首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >不能用迭代器遍历字符串:但是,我的索引版本确实有效

不能用迭代器遍历字符串:但是,我的索引版本确实有效
EN

Stack Overflow用户
提问于 2014-10-06 19:17:20
回答 2查看 157关注 0票数 0

我正在编写一个小程序,它将所有正整数的出现转换为二进制整数。那么我该如何写这个:

我有一个函数numbersToBinary,它接受一个字符串并对其进行修改,因此它将包含二进制形式的数字,而不是十进制数字。

代码语言:javascript
复制
void numbersToBinary(string &src)
{
   for (string::iterator iter = src.begin(); iter != src.end(); iter++)
    {
        if (isdigit(*iter))
        {
           string::iterator numberStart = iter++; //numberStart = iter;
            while ((iter != src.end()) && (isdigit(*iter)))
            {
                iter++;
            }
            string ins = decimalToBinary(string(numberStart, iter));
            src.replace(numberStart, iter, ins);
        }
    }

}

问题是,当使用以数字结尾的字符串调用替换方法时,此函数会捕获异常。

下面是一个要旨:有代码,您也可以在这里看到:github。单元测试是可用的

MWE:

代码语言:javascript
复制
using namespace std;

int main() {
    string example = "String123Primer";
    numbersToBinary(example);
    cout << example << endl;  //"String1111011Primer
    return 0;
}

实际工作的函数:

代码语言:javascript
复制
void numbersToBinary(string &src)
{
    for (int i = 0; i < src.length(); ++i)
      {
         if (isdigit(src[i]))
           {
              int numberStart = i++; //numberStart = iter;
              while (src.length() != i && (isdigit(src[i])))
              { 
                  ++i;
              }
              string ins = decimalToBinary(src.substr(numberStart, i-numberStart));
              src.replace(numberStart, i-numberStart, ins);
          }
         }

      }

编辑:我创建了这个函数的新版本:

代码语言:javascript
复制
void numbersToBinary(string &src) {
    string newString;
    for (string::iterator iter = src.begin(); iter != src.end(); iter++) {
        if (isdigit(*iter)) {
            string::iterator numberStart = iter++; //numberStart = iter;
            while ((iter != src.end()) && (isdigit(*iter))) {
                iter++;
            }
            string ins = decimalToBinary(string(numberStart, iter));
            newString.append(ins);
        }
        else
            newString.push_back(*iter);

    }
    src = newString;
}

但是事实证明,条件(iter != src.end())从来都不是假的,即使在字符串结束时也是如此:

代码语言:javascript
复制
    Breakpoint 2, numbersToBinary (src="My favourite number is13and nevermind 13") at /home/pasha/projects/miem/Replacer/func.cpp:58
    58                  newString.append(ins);
    (gdb) print ins
    $40 = "1101"
    (gdb) s
    51          for (string::iterator iter = src.begin(); iter != src.end(); iter++) {
    (gdb) print iter
    $41 = 0 '\000'
    (gdb) s
    __gnu_cxx::__normal_iterator<char*, std::string>::operator++ (this=0x7fffffffd7d0) at /usr/include/c++/4.9.1/bits/stl_iterator.h:757
    757           { return __normal_iterator(_M_current++); }
    (gdb) s
    __gnu_cxx::__normal_iterator<char*, std::string>::__normal_iterator (this=0x7fffffffd780, __i=@0x7fffffffd788: 0x6a1a10 "") at /usr/include/c++/4.9.1/bits/stl_iterator.h:729
    729           : _M_current(__i) { }
    (gdb) s
    __gnu_cxx::operator!=<char*, std::string> (__lhs=16 '\020', __rhs=0 '\000') at /usr/include/c++/4.9.1/bits/stl_iterator.h:832
    832         { return __lhs.base() != __rhs.base(); }
    (gdb) s
    __gnu_cxx::__normal_iterator<char*, std::string>::base (this=0x7fffffffd7d0) at /usr/include/c++/4.9.1/bits/stl_iterator.h:794
    794           { return _M_current; }
    (gdb) s
    __gnu_cxx::__normal_iterator<char*, std::string>::base (this=0x7fffffffd810) at /usr/include/c++/4.9.1/bits/stl_iterator.h:794
    794           { return _M_current; }
    (gdb) s
    numbersToBinary (src="My favourite number is13and nevermind 13") at /home/pasha/projects/miem/Replacer/func.cpp:52
    52              if (isdigit(*iter)) {
    (gdb) print iter
    $42 = 16 '\020'
    (gdb) print src.end()
    $43 = 0 '\000'

编辑:难以置信,如果我加上这个

代码语言:javascript
复制
if (iter == src.end()) break;

在for循环结束之前,它可以工作!这是什么?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-10-06 21:22:52

关于最新的(和.(更新)密码..。

编辑:难以置信,如果我加上这个 若(iter == src.end())断裂; 在for循环结束之前,它可以工作!这是什么?

这并不难以置信。这就是循环的工作原理。您需要了解for-循环的增量步骤是何时执行的,而条件步骤是何时计算的。

在输入循环主体(Re)之前,在之前执行条件eval。增量步骤是在完成循环主体之后,在返回到下一个条件评估的循环顶部之前执行的。

简而言之,如果内部数字循环将迭代器运行到src.end(),则您的for循环增量步骤将增加一个已经位于序列末尾的迭代器。记住,for循环增量是在每次迭代完成之后,但在下一个条件测试之前完成的。

因此,

代码语言:javascript
复制
void numbersToBinary(string &src)
{
    string newString;
    string::iterator iter = src.begin();
    while (iter != src.end())
    {
        if (isdigit(*iter))
        {
            string::iterator numberStart = iter++; //numberStart = iter;
            while ((iter != src.end()) && (isdigit(*iter))) {
                ++iter;
            }
            string ins = decimalToBinary(string(numberStart, iter));
            newString.append(ins);
        }
        else
        {
            newString.push_back(*iter++);
        }

    }
    src = newString;
}

是你尝试的几种方法之一。如果iter已经到达src.end(),您也可以在循环的末尾设置一个硬中断(尽管在那里检查似乎有些多余,因为我们已经知道它被设置为src.end():数字循环)。

票数 1
EN

Stack Overflow用户

发布于 2014-10-06 21:22:41

调用replace后,原始字符串值不再存在。所以它的部分迭代器不再有效。当您再次循环时,iter是一个迭代器,它是一个不再存在的值的一部分,因此将它与完全不同的值的结尾end进行比较是毫无意义的。调用replace之后,在将iterend进行比较之前,需要将它设置为新字符串中正确的新值。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26223242

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档