【问题标题】:C++ String insert iterationC++ 字符串插入迭代
【发布时间】:2017-12-15 08:19:15
【问题描述】:

我有字符串:

string str = "1234567890";

//Magic code

cout<<str<<endl;

我要输出:12 34 56 78 90

我认为 std 有一些简洁的特性/功能来帮助解决这个问题。我如何以最方便的方式做到这一点?

【问题讨论】:

  • 没有神奇的解决方案,我会说使用简单的 for 循环很方便。
  • 那些重复的5s 是有意的吗?那可能会大大改变正确答案。即,您是否只想在每 2 个字符之间插入空格,或者您是否想在某个神奇的连接处插入空格,在这种情况下,在相邻的奇数和偶数之间,同时还去除重复的字符......大概答案是前者.
  • 如果str 包含奇数位数会怎样?非数字?非图形字符?空间?
  • 然后你开始怀疑 Unicode 字符并意识到 C++ 仍然没有官方的 Unicode 字符串类:| (提示:与此同时,使用glibmm中的ustring)
  • 你有什么尝试吗?

标签: c++ string


【解决方案1】:

带有for 循环的std::string::insert 可以帮助您非常轻松地将空格插入std::string:

#include <iostream>
#include <string>
#include <algorithm>

using namespace std;

int main() {
    string str = "1234567890";

    for(auto it = str.begin(); it != str.end(); it += min<int>(str.end() - it, 2))
        it = (it != str.begin() ? str.insert(it, ' ') + 1 : it);

    cout << str << endl;
}

std::string::insert 返回一个指向插入字符的迭代器,因此它必须递增才能越过插入的字符。

因为std::string 有一个random-access iterator,所以它可以增加或减少超过一。 min&lt;int&gt;(str.end() - it, 2) 确保下一步不会越界。

【讨论】:

    【解决方案2】:

    更通用的方法。定义一个函数,将给定字符 char_to_insert 插入给定字符串 s 每 interval 个字符,不包括字符串的开头和结尾:

    std::string insert_char(const std::string& s, char char_to_insert, size_t interval)
    {
        // corner cases
        if (!interval || !s.length()) return s;
    
        // compute number of characters to insert
        auto number_of_chars_to_insert = (s.length()-1)/interval;
    
        // compute total length
        auto output_length = s.length() + number_of_chars_to_insert;
    
        // pre-allocate output string with all characters equal to char_to_insert
        std::string retval(output_length, char_to_insert);
    
        // cycle input string, keeping track of position in input and output strings
        size_t pos = 0, pos_in_input = 0;
        for (const auto& c : s)
        {
            // copy from input to output
            retval[pos++] = c;
    
            // advance in output every interval chars
            if ((++pos_in_input) % interval == 0)
                ++pos;
        }
        return retval;
    }
    

    然后:

    int main()
    {
        std::string s = "1234567890";
        for (size_t i = 1; i != 5; ++i)
            std::cout << insert_char(s, ' ', i) << std::endl;
        return 0;
    }
    

    输出:

    1 2 3 4 5 6 7 8 9 0
    12 34 56 78 90
    123 456 789 0
    1234 5678 90
    

    【讨论】:

      【解决方案3】:

      没有内置的东西可以做你想做的事。 相反,最方便的解决方案可能是遍历字符串并输出成对的数字:

      string str = "1234567890";
      for (auto it = str.begin(); it != str.end(); ++it){
          std::cout << *(it);
          if (++it != str.end()){
              std::cout << *it << " ";
          }
      }
      std::cout << std::endl;
      

      或非迭代器版本:

      string str = "1234567890";
      for (idx = 0; idx < str.length(); idx += 2){
          std::cout << str.substr(idx, 2) << " ";
      }
      std::cout << std::endl;
      

      这两个示例的行尾都有一个空格,但我将其保留以使示例更简单。

      【讨论】:

      • *(it) 中不需要括号; *it 就足够了。
      • @PeteBecker 啊,是的,我打算“聪明一点”,在同一行的第二个字符中混合迭代器增量,然后再考虑一下。
      • 当您流式传输长度为 1 的字符串时,这是一种浪费。请改用char。
      猜你喜欢
      • 1970-01-01
      • 2011-07-22
      • 2023-04-10
      • 2013-02-20
      • 1970-01-01
      • 2018-05-02
      • 2015-07-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多