読者です 読者をやめる 読者になる 読者になる

【C++】マジックインクリメント

PHPには文字列のインクリメントがあるらしく、C++で実装してみた

マジックインクリメントとは

(以下はネットで調べて理解したことです。間違ったら指摘していただければ幸いです)

英数字の文字列をインクリメントする

++"a" = "b"
++"0" = "1"

桁上げも可能です

++"az" = "ba"
++"19" = "20"

英数字だけの文字列だと

++"z9" = "aa0"
++"Z9" = "AA0"
++"9z" = "10a"
先頭の桁上げは最初の文字種類によって変わります。

英数字以外の文字を含む場合

++"Z!9" = "Z!0"
英数字以外の桁上げはしない

実装

#include <cctype>
#include <string>

std::string& operator++(std::string& s)
{
  if(s.empty()) {
    s = "1";
    return s;
  }
  auto begin = s.rbegin();
  auto end = s.rend();
  while(begin != end) {
    if(*begin == '9') {
      *begin = '0';
    } else if(*begin == 'z') {
      *begin = 'a';
    } else if(*begin == 'Z') {
      *begin = 'A';
    } else if(std::isalnum(*begin)) {
      ++(*begin);
      return s; // 桁上げの必要ありません
    } else {
      return s; // 英数字以外は終了する
    }
    ++begin;
  }
  // 桁上げ
  if(std::isdigit(s.front())) {
    s = "1" + s;
  } else if(std::islower(s.front())) {
    s = "a" + s;
  } else if(std::isupper(s.front())) {
    s = "A" + s;
  }
  return s;
}
std::string operator++(std::string& s,int)
{
  std::string tmp = s;
  ++s;
  return tmp;
}

使い方

#include <iostream>
int main()
{
  std::string s = "a";
  for(int i = 0 ; i < 26 ; i++) {
    std::cout << s++ << " ";
  }
}
// 出力
a b c d e f g h i j k l m n o p q r s t u v w x y z 

何かうれしいの?

連続の名前をアクセスしたいとき

#include <iostream>
int main()
{
  for(std::string s = "IMG_001a" ; s <= "IMG_001e" ; s++) {
    std::cout << s << std::endl;
  }
// 出力
IMG_001a
IMG_001b
IMG_001c
IMG_001d
IMG_001e

C++11のstd::iotaを使うとき(使うかしら...)

#include <iostream>
#include <numeric>
#include <vector>
int main()
{
  std::vector<std::string> v(5);
  std::iota(std::begin(v), std::end(v),std::string("IMG_001a"));
  for(const auto& s : v) {
    std::cout << s << std::endl;
  }
}
// 出力
IMG_001a
IMG_001b
IMG_001c
IMG_001d
IMG_001e