質問

文字列 ..... ZZ..ZZ ..... または .Z.1.Z.23Z.4.Z55 がある場合、

文字列内のすべての Z 文字を現在の位置の1スペース右にシフトする簡単な方法はありますか?

追加のテスト文字列は次のとおりです。

  • .Z
  • Z。
  • ZZ。
  • .ZZ
  • Z
  • ZZ
  • ZZZ

この質問に対する上位投票の回答のいくつか(現在受け入れられているものを含む)は、これらのテストでは機能しません。

役に立ちましたか?

解決

テキストを繰り返し、文字を交換します:

int main ()
{
    char text[] = "...Z.Z.Z...", temp;
    int text_len = strlen (text), i;
    for (i = text_len - 1; i >= 0; i--)
    {
        if (text[i] == 'Z')
        {
                temp = text[i+1];
                text[i+1] = text[i];
                text[i] = temp;
        }
    }
    printf ("%s\n", text);
    return 0;
}

プロデュース:

[~]$ gcc zshift.c && ./a.out
....Z.Z.Z..

上記のコードで考えられるoff-by-1エラーに関するコメントには、多くの議論があります。ただし、そうではないことを示すには、簡単なテスト/ステップスルーで十分です。

zshift "Z." -> ".Z"
zshift ".Z" -> "."
zshift "Z" -> ""

「ドロップ」の動作は文字列の末尾からシフトアウトするときのZの末尾が適切です。結局、整数のビットをシフトすると、整数の境界の外側にあるビットはドロップされます。

別の動作が必要な場合(たとえば、文字列内でのみシフトする場合)、アルゴリズムへの変更は最小限です。

temp = text[i+1];
if (temp == 0) continue;
text[i+1] = text[i];
text[i] = temp;

他のヒント

以前に投稿されたコードの構築はこちら。関数はstrとstrlenを取得し、strを上書きします。後続のZでも機能します。後続のZで速度を改善するために前進します。

void move_z_right (char* str, int strlen) {
    for (unsigned int i = 0; i < strlen - 1; ++i)
    {
        if (str[i] == 'Z')
        {
            unsigned int j = i+1;
            while (str[j] == 'Z' && j < strlen - 1) ++j;
            if (j == strlen) break; // we are at the end, done
            char tmp = str[j];
            str[j] = str[i];
            str[i] = tmp;
            i = j; // continue after new Z next run
        }
    }
}

John Millikinのソリューションは読みやすく、修正にも優れていることに注意してください。

前の回答のわずかな修正(右にシフトし、「。」が「ここに移動できる」ことを意味すると仮定):

  char text[] = "...Z.Z.Z...";

  for (int i = strlen(text) - 2); i > 0; --i) {
    if (text[i] == 'Z' && text[i + 1] == '.') {
      text[i] = '.';
      text[i + 1] = 'Z';
    }
  }
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top