【问题标题】:Removing starting characters from string using std::string::erase使用 std::string::erase 从字符串中删除起始字符
【发布时间】:2020-09-02 05:58:09
【问题描述】:

我正在尝试从字符串中截断开头的零,所以我使用了序列擦除功能

string& erase (size_t pos = 0, size_t len = npos);

这是我的实现:

    string str="000010557";
            for(char c:str){
            cout<<c<<" "<<str<<" "<<"\n";// for debug purpose
            if(c=='0')
                str.erase(0,1);
            else
                break;

        }
        cout<<str;

我得到的输出字符串是0010557 而不是10557 并且调试语句打印:

0 000010557 
0 00010557 
1 0010557 

我阅读了 erasethis 的文档后认为可能存在一些迭代器失效,但实施已接受答案中推荐的代码 sn-p 也给出了相同的输出,请帮助我了解问题出在哪里。

我是stl库函数的新手,如有疏忽请见谅,谢谢。

【问题讨论】:

    标签: c++ string stl


    【解决方案1】:

    您的for 循环正在递增提取c 的位置,即使您删除了前导零。因此,在循环运行两次之后,您已经删除了前导零的第一个第三个​​,那么c 的值将是第一个1

    以下是尝试跟踪代码中发生的情况:

    Start of first loop:
        "000010557"
         ^
         c is '0', so erase is called, making the string:
        "00010557"
    
    At the end of this first loop, the position is incremented, so...
    
    Start of second loop:
        "00010557"
          ^  (Note that we've skipped a zero!)
          c is '0', so erase is called, making the string:
        "0010557"
    
    End of loop, position increment, and we skip another zero, so...
    
    Start of third loop:
        "0010557"
           ^
           c is not '0', so we break out of the loop.
    

    相反,您应该使用while 循环,只测试第一个字符:

    int main()
    {
        string str = "000010557";
        char c;
        while ((c = str.at(0)) == '0') {
           cout << c << " " << str << " " << "\n";// for debug purpose
           str.erase(0, 1);
        }
        cout << str;
    }
    

    输出:

    0 000010557
    0 00010557
    0 0010557
    0 010557
    10557
    

    当然,您的“调试”行只需要 c 变量,因此,没有它,您只需:

    int main()
    {
        string str = "000010557";
        while (str.at(0) == '0') str.erase(0, 1);
        cout << str;
    }
    

    【讨论】:

    • 好的,这就是我所理解的,这个for循环的行为就像位置增量而不是字符增量(我在实现过程中的想法),在删除char c之后,位置增加了,但是位置增加导致char 增量大于 1。我走对了吗?有没有一种方法可以在擦除的同时遍历字符串,例如,如果我需要在随机位置擦除但仍继续进行进一步擦除。
    【解决方案2】:

    即使您让这段代码工作,它也不是一个好的解决方案。从字符串的前面删除单个字符意味着将所有后续字符向下移动一个位置,并且代码对每个前导零都执行此操作。相反,计算前导零并立即将它们全部删除:

    std::string::size_type non_zero_pos = 0;
    while (non_zero_pos < str.size() && str[non_zero_pos] == '0')
        ++non_zero_pos;
    str.erase(0, non_zero_pos);
    

    这样,(昂贵的)擦除操作只进行一次。

    或者使用迭代器:

    auto non_zero_it = std::find_first_not_of(std::begin(str), std::end(str), "0");
    str.erase(std::begin(str), non_zero_it);
    

    编辑:固定搜索非 0 迭代器。

    【讨论】:

      猜你喜欢
      • 2022-10-19
      • 2019-10-21
      • 2021-06-15
      • 1970-01-01
      • 2014-01-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多