【问题标题】:How to generate 'consecutive' c++ strings?如何生成“连续的”C++ 字符串?
【发布时间】:2012-02-01 13:46:27
【问题描述】:

我想生成连续的 C++ 字符串,例如在相机中:IMG001、IMG002 等可以指示前缀和字符串长度。

我找到了一个可以从具体字符集生成随机字符串的解决方案:link

但我找不到我想要实现的目标。

【问题讨论】:

    标签: c++ string random


    【解决方案1】:

    一个可能的解决方案:

    #include <iostream>
    #include <string>
    #include <sstream>
    #include <iomanip>
    
    std::string make_string(const std::string& a_prefix,
                            size_t a_suffix,
                            size_t a_max_length)
    {
        std::ostringstream result;
        result << a_prefix <<
                  std::setfill('0') <<
                  std::setw(a_max_length - a_prefix.length()) <<
                  a_suffix;
        return result.str();
    }
    
    int main()
    {
        for (size_t i = 0; i < 100; i++)
        {
            std::cout << make_string("IMG", i, 6) << "\n";
        }
        return 0;
    }
    

    通过http://ideone.com/HZWmtI查看在线演示。

    【讨论】:

    • +1 用于使用字符串流,这比 sprintf 方法类型安全且安全。
    【解决方案2】:

    这样的事情会起作用

    #include <string>
    #include <iomanip>
    #include <sstream>
    
    
    std::string GetNextNumber( int &lastNum )
    {
        std::stringstream ss;
        ss << "IMG";
        ss << std::setfill('0') << std::setw(3) << lastNum++;
    
        return ss.str();
    }
    
    int main()
    {
        int x = 1;
    
        std::string s = GetNextNumber( x );
        s = GetNextNumber( x );
    
    
        return 0;
    }
    

    您可以使用 int 引用重复调用 GetNextNumber 以生成新的图像编号。您始终可以使用sprintf,但它不会是 c++ 方式:)

    【讨论】:

      【解决方案3】:
       const int max_size = 7 + 1; // maximum size of the name plus one 
       char buf[max_size];
       for (int i = 0 ; i < 1000; ++i) {
         sprintf(buf, "IMG%.04d", i);
         printf("The next name is %s\n", buf);
       }
      

      【讨论】:

        【解决方案4】:
        char * seq_gen(char * prefix) {
            static int counter;
            char * result;
            sprintf(result, "%s%03d", prefix, counter++);
            return result;
        }
        

        这将使用 3 位填充字符串打印您的前缀。如果你想要一个长字符串,你所要做的就是尽可能多地提供前缀,并将上面代码中的 %03d 更改为你想要的任何长度的数字填充。

        【讨论】:

          【解决方案5】:

          嗯,这个想法很简单。只需存储当前数字并在每次生成新字符串时将其递增。您可以实现它来对迭代器进行建模以减少使用它的麻烦(然后您可以使用标准算法)。使用 Boost.Iterator(它也适用于任何字符串类型):

          #include <boost/iterator/iterator_facade.hpp>
          #include <sstream>
          #include <iomanip>
          
          // can't come up with a better name
          template <typename StringT, typename OrdT>
          struct ordinal_id_generator : boost::iterator_facade<
              ordinal_id_generator<StringT, OrdT>, StringT,
              boost::forward_traversal_tag, StringT
          > {
              ordinal_id_generator(
                  const StringT& prefix = StringT(),
                  typename StringT::size_type suffix_length = 5, OrdT initial = 0
              ) : prefix(prefix), suffix_length(suffix_length), ordinal(initial)
              {}
          private:
              StringT prefix;
              typename StringT::size_type suffix_length;
              OrdT ordinal;
          
              friend class boost::iterator_core_access;
          
              void increment() {
                  ++ordinal;
              }
          
              bool equal(const ordinal_id_generator& other) const {
                  return (
                         ordinal == other.ordinal
                      && prefix == other.prefix
                      && suffix_length == other.suffix_length
                  );
              }
          
              StringT dereference() const {
                  std::basic_ostringstream<typename StringT::value_type> ss;
                  ss << prefix << std::setfill('0')
                     << std::setw(suffix_length) << ordinal;
                  return ss.str();
              }
          };
          

          以及示例代码:

          #include <string>
          #include <iostream>
          #include <iterator>
          #include <algorithm>
          
          typedef ordinal_id_generator<std::string, unsigned> generator;
          
          int main() {
              std::ostream_iterator<std::string> out(std::cout, "\n");
          
              std::copy_n(generator("IMG"), 5, out);
              // can even behave as a range
              std::copy(generator("foo", 1, 2), generator("foo", 1, 4), out);
          
              return 0;
          }
          

          【讨论】:

            【解决方案6】:

            看看标准库的字符串流。有一个您递增的整数,并在每次递增后插入到字符串流中。控制字符串长度,有填充字符的概念,还有width()成员函数。

            【讨论】:

              【解决方案7】:

              你有很多方法可以做到这一点。

              一般来说,就像您展示的链接一样,有一组可能的字符。然后在每次迭代之后,从最右边的字符开始,递增它(即,将其更改为可能字符列表中的下一个字符),如果溢出,将其设置为第一个字符(索引 0)并转到第一个字符在左边。这就像在基数中增加一个数字,比如 62。

              在您的具体示例中,您最好从另一个字符串和一个数字创建字符串。

              如果你喜欢*printf,你可以用"IMG%04d"写一个字符串,并让参数从0变为任何值。

              如果你喜欢stringstream,你也可以这样做。

              【讨论】:

                【解决方案8】:

                你所说的连续字符串到底是什么意思?

                既然您提到您使用的是 C++ 字符串,请尝试使用 .string::append 方法。

                string str, str2;
                str.append("A");
                str.append(str2);
                

                查找 http://www.cplusplus.com/reference/string/string/append/ 以获取附加函数的更多重载调用。

                【讨论】:

                • 在问题的主标题下方,有一小部分包含更多详细信息。你的浏览器没有显示吗?
                【解决方案9】:

                这是伪代码。你会明白我的意思:D

                int counter = 0, retval;
                do
                {
                char filename[MAX_PATH];
                sprintf(filename, "IMG00%d", counter++);
                if(retval = CreateFile(...))
                //ok, return
                }while(!retval);
                

                【讨论】:

                  【解决方案10】:

                  您必须保留一个计数器,每次获得新名称时都会增加。此计数器必须在您的应用程序结束时保存,并在您的应用程序启动时加载。

                  可能是这样的:

                  class NameGenerator
                  {
                  public:
                      NameGenerator()
                          : m_counter(0)
                          {
                              // Code to load the counter from a file
                          }
                  
                      ~NameGenerator()
                          {
                              // Code to save the counter to a file
                          }
                  
                      std::string get_next_name()
                          {
                              // Combine your preferred prefix with your counter
                              // Increase the counter
                              // Return the string
                          }
                  
                  private:
                      int m_counter;
                  }
                  
                  NameGenerator my_name_generator;
                  

                  然后像这样使用它:

                  std::string my_name = my_name_generator.get_next_name();
                  

                  【讨论】:

                  • 建议改进:我们只能在返回值改变之前调用函数get_name()一次。我们称它为 get_next_name() 以避免混淆。
                  猜你喜欢
                  • 2012-08-16
                  • 1970-01-01
                  • 1970-01-01
                  • 2021-09-23
                  • 2021-03-13
                  • 1970-01-01
                  • 2018-11-05
                  • 2013-02-03
                  • 2012-03-02
                  相关资源
                  最近更新 更多