C または C++ で文字列を元の位置に戻すにはどうすればよいですか?

#include <algorithm>
std::reverse(str.begin(), str.end());

これは C++ での最も簡単な方法です。


カーニハンとリッチーを読む

#include <string.h>

void reverse(char s[])
{
    int length = strlen(s) ;
    int c, i, j;

    for (i = 0, j = length - 1; i < j; i++, j--)
    {
        c = s[i];
        s[i] = s[j];
        s[j] = c;
    }
}

標準的なアルゴリズムは、始点/終点へのポインターを使用し、それらが途中で出会うか交差するまで内側に向かって歩きます。好きなように交換してください。

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

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-swap を使用していました。この人気のある質問の将来の読者のために修正されました。XOR-swap は 非常に 推奨されません。読みにくく、コードのコンパイル効率が低下します。 xor-swap を x86-64 用に gcc -O3 でコンパイルすると、asm ループ本体がどれほど複雑になるか、Godbolt コンパイラ エクスプローラで確認できます。)

それでは、UTF-8 文字を修正しましょう...

(これは XOR スワップです。避ける必要があることに注意してください。 *p の場合、self と交換します。 と *q a^a==0 でゼロにするのと同じ場所です。 XOR スワップは、2 つの異なる場所があり、それぞれを一時的なストレージとして使用することに依存します。)

編集者注:tmp 変数を使用して、SWP を安全なインライン関数に置き換えることができます。

#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 はテストされていません (そのためのフォントがなく、hexeditor を使用する忍耐力もないようです)

例:

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

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

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

./strrev verrts/.