How do you reverse a string in place in C or C++?

前端 未结 30 1883
长发绾君心
长发绾君心 2020-11-22 00:37

How do you reverse a string in C or C++ without requiring a separate buffer to hold the reversed string?

相关标签:
30条回答
  • 2020-11-22 01:38

    Here is the cleanest, safest, easiest way to reverse a string in C++ (in my opinion):

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

    An alternative is to use std::swap, but I like defining my own functions - it's an interesting exercise and you don't need to include anything extra.

    0 讨论(0)
  • 2020-11-22 01:39

    The standard algorithm is to use pointers to the start / end, and walk them inward until they meet or cross in the middle. Swap as you go.


    Reverse ASCII string, i.e. a 0-terminated array where every character fits in 1 char. (Or other non-multibyte character sets).

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

    The same algorithm works for integer arrays with known length, just use tail = start + length - 1 instead of the end-finding loop.

    (Editor's note: this answer originally used XOR-swap for this simple version, too. Fixed for the benefit of future readers of this popular question. XOR-swap is highly not recommended; hard to read and making your code compile less efficiently. You can see on the Godbolt compiler explorer how much more complicated the asm loop body is when xor-swap is compiled for x86-64 with gcc -O3.)


    Ok, fine, let's fix the UTF-8 chars...

    (This is XOR-swap thing. Take care to note that you must avoid swapping with self, because if *p and *q are the same location you'll zero it with a^a==0. XOR-swap depends on having two distinct locations, using them each as temporary storage.)

    Editor's note: you can replace SWP with a safe inline function using a tmp variable.

    #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;
    }
    
    • Why, yes, if the input is borked, this will cheerfully swap outside the place.
    • Useful link when vandalising in the UNICODE: http://www.macchiato.com/unicode/chart/
    • Also, UTF-8 over 0x10000 is untested (as I don't seem to have any font for it, nor the patience to use a hexeditor)

    Examples:

    $ ./strrev Räksmörgås ░▒▓○◔◑◕●
    
    ░▒▓○◔◑◕● ●◕◑◔○▓▒░
    
    Räksmörgås sågrömskäR
    
    ./strrev verrts/.
    
    0 讨论(0)
  • 2020-11-22 01:39

    Use the std::reverse method from STL:

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

    You will have to include the "algorithm" library, #include<algorithm>.

    0 讨论(0)
  • 2020-11-22 01:39

    Yet another:

    #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);
    
    }
    
    0 讨论(0)
  • 2020-11-22 01:40

    I think there is another way to reverse the string. get the input from user and reverse it.

    void Rev() {
        char ch;
        cin.get(ch);
        if(ch != '\n') {
            Rev();
            cout.put(ch);
        }
    }
    
    0 讨论(0)
  • 2020-11-22 01:40

    Here's my take on it in C. Did it for practice and tried to be as concise as possible! You enter a string via the command line, i.e ./program_name "enter string here"

    #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);
    }
    
    0 讨论(0)
提交回复
热议问题