CまたはC ++で文字列を元に戻すにはどうしますか?


回答:


123

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


逆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-swapを使用していました。この人気のある質問の将来の読者のために修正されました 。XOR-swapは強くお勧めしません。コードを読んだり、効率よくコンパイルしたりすることできません。xor-swapがgcc -O3を使用してx86-64向けにコンパイルされている場合は、godboltコンパイラーエクスプローラーで asmループ本体がどれほど複雑かを確認できます。)


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

(これはXORスワップ事です。あなたがいることをノートに注意してください避けなければならない場合ので、自己とのスワップ*p*q同じ場所ですあなたは^ == 0。XOR・スワップは、二つの異なる位置を有するに依存して、それをゼロますそれぞれを一時的なストレージとして使用します。)

編集者注: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/.

162
難読化されたコードの競合以外でXORスワップを使用する理由はありません。
Chris Conway、

28
「インプレース」とは「追加のメモリがない」ことを意味すると思いますか?スタック上のstrと戻りアドレスのスペースはどうですか?
Chris Conway、

55
@ビル、それは「インプレース」の一般的な定義が意味するものではありません。インプレースアルゴリズム追加のメモリを使用する場合があります。ただし、この追加メモリの量は入力に依存してはなりません。つまり、一定でなければなりません。したがって、追加のストレージを使用した値の交換は完全に行われます。
Konrad Rudolph、

19
XORスワップがなくなるまでこれを支持しません。
Adam Rosenfield、2010年

34
XORスワッピングは、最新のアウトオブオーダープロセッサのレジスタを介したスワッピングよりも低速です。
PatrickSchlüter、2011

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

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


6
C ++では、文字列は文字列クラスによって表されます。彼は「チャースター」や「チャーブラケット」を要求しませんでした。C.上品な滞在
jokoon

10
@fredsbend、選択された回答の「途方もなく長い」バージョンは、この単純な回答では対応できないケース-UTF-8入力を処理します。問題を完全に特定することの重要性を示しています。さらに、Cでも機能するコードについての質問もありました。
Mark Ransom 2013

5
この答えは、UTF-8対応の文字列クラス(またはstd :: basic_stringを含むutf-8文字クラス)を使用する場合に対処します。さらに、質問は「CおよびC ++」ではなく、「CまたはC ++」と述べました。C ++のみは「CまたはC ++」です。
Taywee

161

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

#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;
    }
}

8
私のiphoneでテストすると、生のポインターアドレスを使用するよりも約15%遅くなります
jjxtra 2013

3
変数 "c"をintではなくcharにすべきではありませんか?
Lesswire

17
この例では、文字列sは配列形式で宣言する必要があることに注意してください。換言すれば、char s[] = "this is ok"なくchar *s="cannot do this"変更することができない文字列定数内の後者の結果なぜなら
user1527227

3
「ゴッドファーザー」への謝罪で... ...「銃を残して、K&Rを持参してください」。Cの偏見として、私はポインタを使用します。ポインタは、この問題に対してより単純で

2
@EricこれはO(log(n))時間では実行されません。コードが実行する文字スワップの数を参照している場合は、O(n)で実行されます。文字列の長さがnの場合、n回のスワップが実行されます。実行されるループの量について話している場合は、O(n / 2)ですが、それでもO(n)ですが、定数をBig O表記で削除します。
スティーブンフォックス

62

文字列を元に戻す(視覚化):

文字列を元に戻す


涼しい!これを作成するために何を使用しましたか?それへのリンクを含めることで答えが改善されると思います。
プリフタン

このアルゴリズムの実装は、実際にはこの答えにあります。
karlphillip

これについて少し説明してもらえますか?画像リンクが切れた場合、答えは役に立たないでしょう?
SSアン

41

文字列がnullで終了するchar配列である一般的なケースを想定した非悪質なC :

#include <stddef.h>
#include <string.h>

/* PRE: str must be either NULL or a pointer to a 
 * (possibly empty) null-terminated string. */
void strrev(char *str) {
  char temp, *end_ptr;

  /* If str is NULL or empty, do nothing */
  if( str == NULL || !(*str) )
    return;

  end_ptr = str + strlen(str) - 1;

  /* Swap the chars */
  while( end_ptr > str ) {
    temp = *str;
    *str = *end_ptr;
    *end_ptr = temp;
    str++;
    end_ptr--;
  }
}

whileループを使用して終了ポインタを見つけるのではなく、end_ptr = str + strlen(str);のようなものを使用することはできません。私はそれが実質的に同じことを行うことを知っていますが、私はそれをより明確に見つけます。
PeterKühne、

けっこうだ。私は@uvoteの回答の1つずれたエラーを回避しようとしました(失敗しました)。
Chris Conway、

多分でパフォーマンスが向上する可能性があることを除けばint temp、このソリューションが最適です。+1
chux-モニカを2014年

@ chux-ReinstateMonicaはい。美しい。個人的には()を削除し!(*str)ます。
プリフタン

@PeterKühneはいまたはstrchr()検索'\0'。私は両方を考えました。ループは必要ありません。
プリフタン

35

std::reverseC ++標準ライブラリのアルゴリズムを使用します。


14
標準テンプレートライブラリは、先行標準の用語です。C ++標準では言及されておらず、以前のSTLコンポーネントはC ++標準ライブラリにあります。
Nemanja Trifunovic

16
正しい。問題を混乱させるだけの役目を果たしているにもかかわらず、なぜ多くの人がまだ「STL」と呼んでいるのか疑問に思います。より多くの人があなたのようになり、それを単に「C ++標準ライブラリ」またはSTLと呼んで、「標準ライブラリ」と言うと、より良いでしょう:)
Johannes Schaub-litb

27

久しぶりで、どのアルゴリズムがこのアルゴリズムを教えてくれたのか覚えていませんが、非常に独創的で理解しやすいと思いました。

char input[] = "moc.wolfrevokcats";

int length = strlen(input);
int last_pos = length-1;
for(int i = 0; i < length/2; i++)
{
    char tmp = input[i];
    input[i] = input[last_pos - i];
    input[last_pos - i] = tmp;
}

printf("%s\n", input);

はい、面白いバリエーションです。技術的にはsize_tそうすべきです。
プリフタン

24

STLのstd :: reverseメソッドを使用します

std::reverse(str.begin(), str.end());

「アルゴリズム」ライブラリを含める必要があります#include<algorithm>


1
どのライブラリを含める必要がありますか?
Don Cruickshank 2013

書式#include <アルゴリズム>私はそれを書くのを忘れて、次に答えを編集したが、それは、名前が欠落していた理由のthatsを保存波平...
user2628229

これは私の答えでもありましたが、好奇心が強いのですが、OPは「逆ストリングを保持するためのバッファーなしで」(基本的にはインプレーススワップ)と尋ねたので、これがそうであることをどのように証明しますか?内部でstd :: iter_swap <>を使用し、両方のエンドポイントからバッファーの中間点まで反復することを説明しますか?また、OPはCとC ++の両方を要求しましたが、これはC ++専用です(<string.h>にstrrev()メソッドがあることを願っていますか?)
HidekiAI

21

std :: reverseの美点は、char *文字列とstd::wstringsだけでなくstd::stringsでも機能することです。

void strrev(char *str)
{
    if (str == NULL)
        return;
    std::reverse(str, str + strlen(str));
}

1
一方でC ++を使用していたので吐きたいですが、もう一方では*、型ではなく名前でC ++を使用している人を見ると、美しく、美しく、絶対に美しいものです。素晴らしい。私は純粋主義者だと認めますが、のようなコードを見るたびにうんざりしますchar* str;
プリフタン

11

NULLで終了するバッファを元に戻す方法を探している場合、ここに掲載されているほとんどのソリューションは問題ありません。しかし、Tim Farleyがすでに指摘したように、これらのアルゴリズムは、文字列が意味的にバイトの配列(つまり、1バイト文字列)であると仮定することが有効である場合にのみ機能します。これは誤った仮定です。

たとえば、文字列 "año"(スペイン語では年)を考えます。

Unicodeコードポイントは0x61、0xf1、0x6fです。

最もよく使われるエンコーディングをいくつか考えてみましょう:

Latin1 / iso-8859-1(1バイトエンコーディング、1文字は1バイト、およびその逆):

元の:

0x61、0xf1、0x6f、0x00

逆行する:

0x6f、0xf1、0x61、0x00

結果はOKです

UTF-8:

元の:

0x61、0xc3、0xb1、0x6f、0x00

逆行する:

0x6f、0xb1、0xc3、0x61、0x00

結果は意味不明で、不正なUTF-8シーケンスです

UTF-16ビッグエンディアン:

元の:

0x00、0x61、0x00、0xf1、0x00、0x6f、0x00、0x00

最初のバイトはNULターミネーターとして扱われます。反転は行われません。

UTF-16リトルエンディアン:

元の:

0x61、0x00、0xf1、0x00、0x6f、0x00、0x00、0x00

2番目のバイトはNULターミネーターとして扱われます。結果は0x61、0x00、「a」文字を含む文字列になります。


std :: reverseは、wstringを使用している限り、2バイトのUnicodeタイプで機能します。
Eclipseの

私はC ++にはあまり詳しくありませんが、文字列を処理する標準ライブラリ関数は、さまざまなエンコーディングを処理できるので、私はあなたに同意します。「これらのアルゴリズム」とは、ここに掲載された臨時のリバース関数を意味しました。
ファンパブロカリファノ

残念ながら、標準のC ++には「文字列を処理する立派な関数」のようなものはありません。
Jem

@Eclipseサロゲートペアを逆にすると、結果は正しくなくなります。Unicodeは実際には固定幅の文字セットではありません
phuclv 2014年

この答えについて私が気に入っているのは、バイトの実際の順序(エンディアンは何かあるかもしれませんが、ああ、あなたは実際にそれを考慮したと思います)と、それがどのように正しいか正しくないかを示すことです。しかし、これを示すコードを組み込むと、答えは改善されると思います。
プリフタン

11

完全を期すために、文字ごとのバイト数が文字によって異なるさまざまなプラットフォームで文字列の表現があることを指摘しておく必要があります。古い学校のプログラマーはこれをDBCS(2バイト文字セット)と呼びます。最近のプログラマーは、UTF-8(およびUTF-16など)でこれに遭遇することが一般的です。他にもそのようなエンコーディングがあります。

これらの可変幅符号化方式のいずれにおいても、簡単なアルゴリズムは、(ここに掲載非悪か、そうでない場合は)すべてで正常に動作しません!実際、それらは文字列を判読不能にしたり、そのエンコードスキームで不正な文字列にしたりすることさえあります。いくつかの良い例については、ファンパブロカリファノの回答を参照してください。

std :: reverse()は、プラットフォームの標準C ++ライブラリの実装(特に文字列イテレータ)がこれを適切に考慮している限り、この場合でも機能する可能性があります。


6
std :: reverseはこれを考慮しません。value_typeを逆にします。std :: stringの場合、charを逆にします。文字ではありません。
MSalters 2008年

古い学校のプログラマーはDBCSを知っているだけでなく、UTF-8も知っていると言ってください。プログラマーが「もう1行書くとやめます!」一部のプログラマーはやがてやめると確信していますが、率直に言ってプログラミングは本当に中毒のようです。私はプログラミングをしないことから撤退します。ここに追加するのは良い点です。私はC ++が好きではありません(かなりの量を書いたとしても、本当に一生懸命頑張ってみましたが、控えめに言っても見た目は魅力的ではありません)。 +1があります。
プリフタン

5

別のC ++の方法(私はおそらくstd :: reverse()自分自身をより表現的で高速なものとして使用します)

str = std::string(str.rbegin(), str.rend());

Cの方法(多かれ少なかれ:))そして、スワップのためのXORトリックに注意してください。コンパイラーはそれを最適化できないことがあります。

このような場合、通常はかなり遅くなります。

char* reverse(char* s)
{
    char* beg = s, *end = s, tmp;
    while (*end) end++;
    while (end-- > beg)
    { 
        tmp  = *beg; 
        *beg++ = *end;  
        *end =  tmp;
    }
    return s;
} // fixed: check history for details, as those are interesting ones

strlen文字列が潜在的に長い場合は、文字列の終わりを見つけるために使用します。優れたライブラリ実装は、SIMDベクトルを使用して、反復ごとに1バイトよりも速く検索します。ただし、非常に短い文字列の場合while (*++end);は、ライブラリ関数呼び出しが検索を開始する前に行われます。
Peter Cordes

@PeterCordesは、まあ、同意された、とにかく読みやすさのためにstrlenを使用すべきです。長い文字列の場合は、とにかく常にvarialbeの長さを維持する必要があります。通常、SIMDのstrlenは、この免責事項の例として示されています。これは実際のアプリケーションではありません。または、少なくとも5年前にコードが記述されたときのことです。;)
pprzemek 2017

1
これを実際のCPUで高速に実行したい場合は、SIMDシャッフルを使用して16Bチャンクで逆を行います。:P例えばx86では、_mm_shuffle_epi8(PSHUFB)は、正しいシャッフル制御ベクトルが与えられた場合、16Bベクトルの順序を逆にすることができます。特にAVX2の場合、慎重に最適化することで、ほぼmemcpyの速度で実行できます。
Peter Cordes

char* beg = s-1未定義の動作があります(少なくともs、配列の最初の要素を指している場合、これが最も一般的なケースです)。while (*++end);s空の文字列の場合、動作は未定義です。
メルポメン

@pprzemekさて、あなたは配列の最初の要素を指していてs-1も動作を定義した主張をしているsので、サポートで標準を引用することができるのはあなたです。
メルポメン

4
#include <cstdio>
#include <cstdlib>
#include <string>

void strrev(char *str)
{
        if( str == NULL )
                return;

        char *end_ptr = &str[strlen(str) - 1];
        char temp;
        while( end_ptr > str )
        {
                temp = *str;
                *str++ = *end_ptr;
                *end_ptr-- = temp;
        }
}

int main(int argc, char *argv[])
{
        char buffer[32];

        strcpy(buffer, "testing");
        strrev(buffer);
        printf("%s\n", buffer);

        strcpy(buffer, "a");
        strrev(buffer);
        printf("%s\n", buffer);

        strcpy(buffer, "abc");
        strrev(buffer);
        printf("%s\n", buffer);

        strcpy(buffer, "");
        strrev(buffer);
        printf("%s\n", buffer);

        strrev(NULL);

        return 0;
}

このコードは次の出力を生成します。

gnitset
a
cba

2
@ uvote、strcpyは使用しないでください。ずっと。strcpyなどを使用する必要がある場合は、strncpyを使用します。strcpyは危険です。ちなみに、CとC ++は、別々の機能を持つ2つの別々の言語です。C ++でのみ利用可能なヘッダーファイルを使用していると思うので、本当にCで回答が必要ですか?
Onorio Catenacci

6
プログラマーが配列のサイズを追跡できれば、strcpyは完全に安全です。多くの場合、strncpyは、結果の文字列がnullで終了することを保証しないため、安全性が低いと主張します。いずれにしても、ここでのuvoteのstrcpyの使用に問題はありません。
Robert Gamble

1
@Onorio Catenacci、上記のコードの場合のように、ソース文字列が宛先バッファ内に収まることがわかっている場合、strcpyは危険ではありません。また、余計な余地がある場合、strncpyはsizeパラメータで指定された文字数までゼロで埋めますが、これは望ましくない場合があります。
クリス・ヤング

3
適切にstrcpyを使用することはできません誰もがCでプログラミングをしてはならない
ロバートギャンブル

2
@ロバート・ギャンブル、同意する。しかし、私は人々が彼らの能力に関係なくCでプログラミングするのを防ぐ方法を知らないので、私は通常これに反対することを勧めます。
Onorio Catenacci


3

エフゲニーのK&Rの答えが好きです。ただし、ポインターを使用してバージョンを表示するのは良いことです。それ以外は基本的に同じです。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

char *reverse(char *str) {
    if( str == NULL || !(*str) ) return NULL;
    int i, j = strlen(str)-1;
    char *sallocd;
    sallocd = malloc(sizeof(char) * (j+1));
    for(i=0; j>=0; i++, j--) {
        *(sallocd+i) = *(str+j);
    }
    return sallocd;
}

int main(void) {
    char *s = "a man a plan a canal panama";
    char *sret = reverse(s);
    printf("%s\n", reverse(sret));
    free(sret);
    return 0;
}

3

文字列を元に戻す再帰関数(追加のバッファーなし、malloc)。

短くてセクシーなコード。悪い、悪いスタック使用法。

#include <stdio.h>

/* Store the each value and move to next char going down
 * the stack. Assign value to start ptr and increment 
 * when coming back up the stack (return).
 * Neat code, horrible stack usage.
 *
 * val - value of current pointer.
 * s - start pointer
 * n - next char pointer in string.
 */
char *reverse_r(char val, char *s, char *n)
{
    if (*n)
        s = reverse_r(*n, s, n+1);
   *s = val;
   return s+1;
}

/*
 * expect the string to be passed as argv[1]
 */
int main(int argc, char *argv[])
{
    char *aString;

    if (argc < 2)
    {
        printf("Usage: RSIP <string>\n");
        return 0;
    }

    aString = argv[1];
    printf("String to reverse: %s\n", aString );

    reverse_r(*aString, aString, aString+1); 
    printf("Reversed String:   %s\n", aString );

    return 0;
}

1
これは非常に楽しいソリューションです。printf( "%* s> [%d] reverse_r( '%c'、%p = \"%s \ "、%p = \"%s \ ")のようなトレースを追加する必要があります\ n "、深さ、" "、深さ、値、s、(s?s:" null ")、n、(n?n:" null ")); 開始時、<終了時。
2013年

それぞれcharをスタックにプッシュしても、「所定の場所」としてカウントされません。特に、実際に1文字あたり4 * 8Bをプッシュしている場合はそうではありません(64ビットマシンでは、3つの引数+戻りアドレス)。
Peter Cordes

元の質問は、「CまたはC ++で文字列を反転するには、反転した文字列を保持するために別のバッファーを必要としないのですか」です。-「その場で」交換する必要はありませんでした。また、このソリューションは、最初からスタックの使用状況が悪いことを示しています。他の人の読解力の低さのために私は反対票を投じられていますか?
Simon Peverett、2017年

1
私はそれを「セクシー」とは言いませんが、それは実証的で教育的であると言います。再帰が適切に使用されている場合、それは非常に価値があります。ただし、Cはスタック自体も必要としないことを指摘しておく必要があります。ただし、再帰は行います。いずれにせよ、それは再帰の例であり、適切に使用されれば非常に有用で価値があります。私はそれが文字列を逆転させるために使用されるのを見たことがないと思います。
プリフタン


1

コードを共有してください。C ++の学習者として、swap()を使用するためのオプションとして、私は謙虚にコメントを求めています。

void reverse(char* str) {
    int length = strlen(str);
    char* str_head = str;
    char* str_tail = &str[length-1];
    while (str_head < str_tail) 
        swap(*str_head++, *str_tail--);
}


0

さらに別の:

#include <stdio.h>
#include <strings.h>

int main(int argc, char **argv) {

  char *reverse = argv[argc-1];
  char *left = reverse;
  int length = strlen(reverse);
  char *right = reverse+length-1;
  char temp;

  while(right-left>=1){

    temp=*left;
    *left=*right;
    *right=temp;
    ++left;
    --right;

  }

  printf("%s\n", reverse);

}

これは、私の答えによく似たポインタ演算を示していますが、それをスワップと組み合わせています。この答えは実際に多くを追加すると思います。単純なテキストボックスを取得するために依存関係として10億のライブラリーを追加する前に、このタイプのコードを理解できるはずです(私が使用する現代のアプリケーションではあまりにも頻繁に表示されるもの)
Stephen J

0
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>

unsigned char * utf8_reverse(const unsigned char *, int);
void assert_true(bool);

int main(void)
{
    unsigned char str[] = "mañana mañana";
    unsigned char *ret = utf8_reverse(str,  strlen((const char *) str) + 1);

    printf("%s\n", ret);
    assert_true(0 == strncmp((const char *) ret, "anãnam anañam", strlen("anãnam anañam") + 1));

    free(ret);

    return EXIT_SUCCESS;
}

unsigned char * utf8_reverse(const unsigned char *str, int size)
{
    unsigned char *ret = calloc(size, sizeof(unsigned char*));
    int ret_size = 0;
    int pos = size - 2;
    int char_size = 0;

    if (str ==  NULL) {
        fprintf(stderr, "failed to allocate memory.\n");
        exit(EXIT_FAILURE);
    }

    while (pos > -1) {

        if (str[pos] < 0x80) {
            char_size = 1;
        } else if (pos > 0 && str[pos - 1] > 0xC1 && str[pos - 1] < 0xE0) {
            char_size = 2;
        } else if (pos > 1 && str[pos - 2] > 0xDF && str[pos - 2] < 0xF0) {
            char_size = 3;
        } else if (pos > 2 && str[pos - 3] > 0xEF && str[pos - 3] < 0xF5) {
            char_size = 4;
        } else {
            char_size = 1;
        }

        pos -= char_size;
        memcpy(ret + ret_size, str + pos + 1, char_size);
        ret_size += char_size;
    }    

    ret[ret_size] = '\0';

    return ret;
}

void assert_true(bool boolean)
{
    puts(boolean == true ? "true" : "false");
}

0

C ++ラムダの場合:

 auto reverse = [](std::string& s) -> std::string {
        size_t start = 0, end = s.length() -1;
        char temp;

        while (start < end) {
          temp = s[start];
          s[start++] = s[end];
          s[end--] = temp;
        } 

        return s;
   };

0

私の答えはそれらのほとんどに似ていますが、ここに私のコードを見つけてください。

//Method signature to reverse string
string reverseString(string str);

int main(void){
    string str;
    getline(cin, str);
    str =  reverseString(str);
    cout << "The reveresed string is : " << str;
    return 0;
}

/// <summary>
///     Reverses the input string.
/// </summary>
/// <param name="str">
///    This is the input string which needs to be reversed.
/// </param>
/// <return datatype = string>
///     This method would return the reversed string
/// </return datatype>

string reverseString(string str){
    int length = str.size()-1;
    char temp;
    for( int i=0 ;i<(length/2);i++)
    {
        temp = str[i];
        str[i] = str[length-i];
        str[length-i] = temp;
    }
    return str;
}

0

文字列を逆にする別の方法があると思います。ユーザーから入力を受け取り、それを逆にします。

void Rev() {
    char ch;
    cin.get(ch);
    if(ch != '\n') {
        Rev();
        cout.put(ch);
    }
}

本当ですが、これは逆の順序を出力するだけですよね?(私はC ++を使用しないので、おそらく.put()は私が思っていることを実行しません)。
プリフタン

-1

保存する必要がない場合は、次のように時間を短縮できます。

void showReverse(char s[], int length)
{
    printf("Reversed String without storing is ");
    //could use another variable to test for length, keeping length whole.
    //assumes contiguous memory
    for (; length > 0; length--)
    {
        printf("%c", *(s+ length-1) );
    }
    printf("\n");
}

バッファまたは一時変数がない唯一の答えのようです。私は文字列の長さを使用しますが、これを行う他のものは、ヘッド(テールに対して)をもう1つ追加します。標準のリバース関数がスワップなどを介して変数を格納すると想定しています。したがって、私は、ポインターの数学とUTFのタイプが揃っていると仮定して、これが実際に質問に答える唯一の答えである可能性があるという印象を受けています。追加されたprintf()は取り出すことができますが、結果をより見栄えよくするために実行しました。私はスピードのためにこれを書きました。余分な割り当てや変数はありません。おそらく、逆str()を表示するための最速のアルゴリズム
Stephen J

-3

これがCでの私の見解です。練習のためにやったので、できるだけ簡潔にしてみました。コマンドラインから文字列を入力します。つまり、。/ program_name "ここに文字列を入力します"

#include <stdio.h>
#include <string.h>

void reverse(int s,int e,int len,char t,char* arg) {
   for(;s<len/2;t=arg[s],arg[s++]=arg[e],arg[e--]=t);
}

int main(int argc,char* argv[]) {
  int s=0,len=strlen(argv[1]),e=len-1; char t,*arg=argv[1];
  reverse(s,e,len,t,arg);
  for(s=0,e=0;e<=len;arg[e]==' '||arg[e]=='\0'?reverse(s,e-1,e+s,t,arg),s=++e:e++);
  printf("%s\n",arg);
}

1
それは判読不能な混乱ですが、一部の変数名は複数の文字であるため、可能な限り最短のコード(コードゴルフ)を使用するつもりはないようです。
Peter Cordes

-4

しかし、XORスワップアルゴリズムが最適だと思います...

char str[]= {"I am doing reverse string"};
char* pStr = str;

for(int i = 0; i != ((int)strlen(str)-1)/2; i++)
{
    char b = *(pStr+i);
    *(pStr+i) = *(pStr+strlen(str)-1-i);
    *(pStr+strlen(str)-1-i) = b;
}

strlen()ループ条件およびループ本体での呼び出しは最適化されない場合があります。
Peter Cordes

-5

これは、C ++で文字列を逆にする最もクリーンで安全な最も簡単な方法です(私の意見では)。

#include <string>

void swap(std::string& str, int index1, int index2) {

    char temp = str[index1];
    str[index1] = str[index2];
    str[index2] = temp;

}

void reverse(std::string& str) {

    for (int i = 0; i < str.size() / 2; i++)
        swap(str, i, str.size() - i - 1);

}

代わりにを使用することもできますがstd::swap、私は自分の関数を定義するのが好きです。これは興味深い演習であり、include特別なことは必要ありません。


-5
#include<stdio.h>
#include<conio.h>

int main()
{
    char *my_string = "THIS_IS_MY_STRING";
    char *rev_my_string = my_string;

    while (*++rev_my_string != '\0')
        ;

    while (rev_my_string-- != (my_string-1))
    {
        printf("%c", *rev_my_string);
    }

    getchar();
    return 0;
}

これは文字列を逆にするためにC言語で最適化されたコードです...そしてそれは簡単です。単純なポインタを使用して仕事をします...


これは、文字列を一度に1文字ずつ出力します。インプレースで元に戻すことはありません。また、理由もなくユーザー入力を待機します。
Peter Cordes
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.