1. ホーム
  2. c++

[解決済み] CやC++で文字列を定位置で反転させるにはどうしたらいいですか?

2022-04-15 21:54:09

質問

CまたはC++で、反転した文字列を保持するために別のバッファを必要とせずに文字列を反転するにはどうすればよいですか?

どのように解決するのですか?

標準的なアルゴリズムは、開始と終了のポインタを使い、それらが中央で出会うか交差するまで内側に歩くことである。 その都度、入れ替えを行う。


逆ASCII文字列、すなわち、すべての文字が1に収まる0終端の配列。 char . (または他の非マルチバイト文字セット)。

void strrev(char *head)
{
  if (!head) return;
  char *tail = head;
  while(*tail) ++tail;    // find the 0 terminator, like head+strlen
  --tail;               // tail points to the last real char
                        // head still points to the first
  for( ; head < tail; ++head, --tail) {
      // walk pointers inwards until they meet or cross in the middle
      char h = *head, t = *tail;
      *head = t;           // swapping as we go
      *tail = h;
  }
}

// test program that reverses its args
#include <stdio.h>

int main(int argc, char **argv)
{
  do {
    printf("%s ",  argv[argc-1]);
    strrev(argv[argc-1]);
    printf("%s\n", argv[argc-1]);
  } while(--argc);

  return 0;
}

長さが既知の整数配列の場合も同じアルゴリズムが使えます。 tail = start + length - 1 終端探索ループの代わりに

(編集部注:この回答も、当初はこのシンプルなバージョンにXORスワップを使っていました。 今後、この人気のある質問を読む人のために修正しました。 XOR-swapは なかなか 推奨しない 読みにくく、コードのコンパイル効率が悪くなります。 ご覧の通りです。 ゴッドボルトコンパイラエクスプローラで xor-swapをgcc -O3でx86-64用にコンパイルした場合、asmのループ本体がどれだけ複雑になるか)。


よし、わかった、UTF-8文字を直そう...。

(これはXORスワップのことです。注意することは を避けなければなりません。 は self とスワップします。 *p*q XORスワップは、2つの異なるロケーションを持ち、それぞれを一時的なストレージとして使用することに依存します)。

編集部注:SWPをtmp変数を使った安全なインライン関数に置き換えることができます。

#include <bits/types.h>
#include <stdio.h>

#define SWP(x,y) (x^=y, y^=x, x^=y)

void strrev(char *p)
{
  char *q = p;
  while(q && *q) ++q; /* find eos */
  for(--q; p < q; ++p, --q) SWP(*p, *q);
}

void strrev_utf8(char *p)
{
  char *q = p;
  strrev(p); /* call base case */

  /* Ok, now fix bass-ackwards UTF chars. */
  while(q && *q) ++q; /* find eos */
  while(p < --q)
    switch( (*q & 0xF0) >> 4 ) {
    case 0xF: /* U+010000-U+10FFFF: four bytes. */
      SWP(*(q-0), *(q-3));
      SWP(*(q-1), *(q-2));
      q -= 3;
      break;
    case 0xE: /* U+000800-U+00FFFF: three bytes. */
      SWP(*(q-0), *(q-2));
      q -= 2;
      break;
    case 0xC: /* fall-through */
    case 0xD: /* U+000080-U+0007FF: two bytes. */
      SWP(*(q-0), *(q-1));
      q--;
      break;
    }
}

int main(int argc, char **argv)
{
  do {
    printf("%s ",  argv[argc-1]);
    strrev_utf8(argv[argc-1]);
    printf("%s\n", argv[argc-1]);
  } while(--argc);

  return 0;
}

  • なぜかというと、そうなんです、入力がボロボロになると、これは元気よくその場の外にスワップしてくれるんです。
  • UNICODEで荒らすときに便利なリンクです。 http://www.macchiato.com/unicode/chart/
  • また、0x10000以上のUTF-8は未検証です(そのためのフォントは持っていないようですし、ヘキサエディタを使う忍耐力もありませんから)。

$ ./strrev Räksmörgås ░▒▓○◔◑◕●

░▒▓○◔◑◕● ●◕◑◔○▓▒░

Räksmörgås sågrömskäR

./strrev verrts/.