B - camel_case Editorial by hanyu

ユーザ解説

入力で与えられる文字列を \(S\) とします。

先頭と末尾のアンダースコアを処理する

\(S\) の先頭と末尾に連続しているアンダースコアを別途保存します。 ここで \(S\) がアンダースコアしか含まないと判明した場合、 \(S\) を出力してプログラムを終了します。

また、先頭と末尾のアンダースコアを取り除いた文字列を \(T\) とし、以降は \(T\) を相互変換することを考えます。

実装例 (C++) :

string front_ = "", back_ = ""; // 先頭、末尾のアンダースコアを保存

for (int i = 0; i < S.size(); i++) {
  if (S[i] == '_') front_ += "_";
  else break;
}
for (int i = S.size() - 1; i >= 0; i--) {
  if (S[i] == '_') back_ += "_";
  else break;
}

if (front_ == S) { // Sがアンダースコアのみからなる場合
  cout << S << endl;
  return 0;
}

string T = S.substr(front_.size(), S.size() - front_.size() - back_.size());

\(T\) をどう変換すべきか

結局、以下のようになります。

  • \(T\) がキャメルケースであり、アンダースコア区切りではないとき、 \(T\) をアンダースコア区切りに変換する
  • \(T\) がアンダースコア区切りであり、キャメルケースではないとき、 \(T\) をキャメルケースに変換する
  • 上記のどちらにも当てはまらないとき、\(T\) は変換しなくてよい

したがって

  • \(T\) がキャメルケースかどうか判断する関数 (isCamel)
  • \(T\) がアンダースコア区切りかどうか判断する関数 (is_snake)
  • キャメルケースをアンダースコア区切りに変換する関数 (camel2snake)
  • アンダースコア区切りをキャメルケースに変換する関数 (snake2camel)

を作成すればよいです。

関数の作成

isCamel

\(T\) の先頭が英小文字であり、かつ \(T\) にアンダースコアが含まれなければ、 \(T\) はキャメルケースです。

is_snake

\(T\) の先頭およびアンダースコアの直後は英小文字、その他は英小文字か数字であれば、 \(T\) はアンダースコア区切りです。

camel2snake

引数の文字列の英大文字を (アンダースコア + 英小文字) に置き換えます。

snake2camel

引数の文字列のアンダースコアを除外し、直後の英小文字を英大文字に置き換えます。

C++であれば、あらかじめ用意されている islower, isupper, tolower, toupper 関数が役立ちます。

実装例 (C++) :

bool isCamel(string T) {
  if (!islower(T[0])) return false;
  for (int i = 1; i < (int) T.size(); i++) {
    if (T[i] == '_') return false;
  }
  return true;
}

bool is_snake(string T) {
  for (int i = 0; i < T.size(); i++) {
    if (i == 0) {
      if (!islower(T[i])) return false;
    }
    else if (T[i] == '_') {
      i++;
      if (!islower(T[i])) return false;
    }
    else {
      if (isupper(T[i])) return false;
    }
  }
  return true;
}

string camel2snake(string T) {
  string res = "";
  for (int i = 0; i < T.size(); i++) {
    if (isupper(T[i])) {
      res += "_";
      res += tolower(T[i]);
    }
    else {
      res += T[i];
    }
  }
  return res;
}

string snake2camel(string T) {
  string res = "";
  for (int i = 0; i < T.size(); i++) {
    if (T[i] == '_') {
      i++;
      res += toupper(T[i]);
    }
    else {
      res += T[i];
    }
  }
  return res;
}

全体の実装例 (C++)

posted:
last update: