Comment inverser une chaîne en C ou C++?

comment inverser une chaîne en c/" class="blnk">C ou C++ sans avoir besoin d'un tampon séparé pour maintenir la chaîne inversée?

160
demandé sur Coding Mash 2008-10-13 20:36:21

30 réponses

Evil C:

#include <stdio.h>

void strrev(char *p)
{
  char *q = p;
  while(q && *q) ++q;
  for(--q; p < q; ++p, --q)
    *p = *p ^ *q,
    *q = *p ^ *q,
    *p = *p ^ *q;
}

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

(c'est le truc de XOR-swap. Prenez soin de noter que vous doit éviter échange avec soi-même, parce que a^a=0.)


Ok, très bien, fixons les caractères UTF-8...

#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;
}
  • pourquoi, Oui, si l'entrée est bornée, cela va joyeusement échanger à l'extérieur de l'endroit.
  • lien utile lors du vandalisme en UNICODE: http://www.macchiato.com/unicode/chart /
  • en outre, UTF-8 Plus de 0x10000 n'est pas testé (comme je ne semble pas avoir de police pour elle, ni la patience d'utiliser un hexeditor)

exemples:

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

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

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

./strrev verrts/.
120
répondu Anders Eurenius 2014-05-08 10:31:31
#include <algorithm>
std::reverse(str.begin(), str.end());

C'est la manière la plus simple en C++.

443
répondu Greg Rogers 2012-07-22 03:51:05

Lire Kernighan et Ritchie

#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;
    }
}
156
répondu Eric Leschinski 2015-04-16 19:16:28

Inverser une chaîne de caractères en place (visualisation):

Reverse a string in place

52
répondu slashdottir 2014-11-11 21:12:20

Non-evil C, en supposant le cas commun où la chaîne est un tableau char sans fin:

#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--;
  }
}
40
répondu Chris Conway 2008-10-13 19:56:40

vous utilisez std::reverse algorithme de la bibliothèque Standard C++.

32
répondu Nemanja Trifunovic 2013-04-23 19:25:06

Cela fait longtemps et je ne me souviens pas quel livre m'a appris cet algorithme, mais je pensais qu'il était assez ingénieux et simple à comprendre:

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);
25
répondu karlphillip 2011-07-03 00:16:19

utiliser la méthode std::reverse de STL :

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

vous devrez inclure la bibliothèque" algorithme", #include<algorithm> .

19
répondu user2628229 2014-11-11 21:14:57

notez que la beauté de std:: reverse est qu'il fonctionne avec char * cordes et std::wstring s aussi bien que std::string s

void strrev(char *str)
{
    if (str == NULL)
        return;
    std::reverse(str, str + strlen(str));
}
18
répondu Eclipse 2008-10-13 19:03:25

si vous cherchez à inverser les tampons NULS, la plupart des solutions affichées ici sont correctes. Mais, comme Tim Farley l'a déjà souligné, ces algorithmes ne fonctionneront que s'il est valide de supposer qu'une chaîne est sémantiquement un tableau d'octets (c.-à-d. des chaînes à un octet), ce qui est une hypothèse fausse, je pense.

Prenez par exemple la chaîne" año " (année en espagnol).

les points de code Unicode sont 0x61, 0xf1, 0x6f.

Considérons quelques-uns des encodages les plus utilisés:

Latin1 / iso-8859-1 (codage d'un octet, 1 caractère est 1 octet et vice versa):

Origine:

0x61, 0xf1, 0x6f, 0x00

Reverse:

0x6f, 0xf1, 0x61, 0x00

le résultat est OK

UTF-8:

Origine:

0x61, 0xc3, 0xb1, 0x6f, 0x00

Reverse:

0x6f, 0xb1, 0xc3, 0x61, 0x00

le résultat est du charabia et une séquence illégale UTF-8

UTF-16 Big Endian:

Original:

0x00, 0x61, 0x00, 0xf1, 0x00, 0x6f, 0x00, 0x00

le premier octet sera traité comme un NUL-terminator. Pas d'inversion de aura lieu.

UTF-16 Little Endian:

Origine:

0x61, 0x00, 0xf1, 0x00, 0x6f, 0x00, 0x00, 0x00

le le second octet sera traité comme un NUL-terminator. Le résultat sera 0x61, 0x00, une chaîne contenant le caractère'.

11
répondu Juan Pablo Califano 2008-10-13 18:55:29

par souci d'exhaustivité, il convient de souligner qu'il existe des représentations de chaînes sur diverses plateformes dans lesquelles le nombre d'octets par caractère varie selon le caractère. Les programmeurs de la vieille école l'appelleraient DBCS (double Byte Character Set) . Les programmeurs modernes rencontrent plus souvent cela dans UTF-8 (ainsi que UTF-16 et d'autres). Il y a d'autres encodages.

dans l'un de ces schémas d'encodage à largeur variable, les algorithmes simples affichés ici ( evil , non-evil ou sinon ) ne fonctionneraient pas correctement du tout! En fait, ils pourraient même rendre la chaîne illisible ou même une chaîne illégale dans ce schéma d'encodage. Voir la réponse de Juan Pablo Califano pour une bonne exemple.

std:: reverse () fonctionnerait encore potentiellement dans ce cas, à condition que l'implémentation de votre plate-forme de la bibliothèque Standard C++ (en particulier, les itérateurs de chaîne) en tienne dûment compte.

10
répondu Tim Farley 2017-05-23 10:31:32
#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;
}

ce code produit cette sortie:

gnitset
a
cba
4
répondu 2008-10-13 16:36:32

dans le cas où vous utilisez GLib, il a deux fonctions pour cela, g_strreverse () et g_utf8_streverse ()

3
répondu dmityugov 2008-10-14 05:24:47

une autre façon C++ (bien que j'utiliserais probablement std:: reverse () myself:) comme étant plus expressive et plus rapide)

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

la voie C (plus ou moins :) ) et s'il vous plaît, faites attention à XOR trick pour échanger, les compilateurs ne peuvent généralement pas optimiser.

dans ce cas, il est généralement beaucoup plus lent.

char* reverse(char* s)
{
    char* beg = s-1, *end = s, tmp;
    while (*++end);
    while (end-- > ++beg)
    { 
        tmp  = *beg; 
        *beg = *end;  
        *end =  tmp;  
    }
    return s;
}
3
répondu pprzemek 2012-09-28 13:10:54

j'aime la réponse K&R D'Evgeny. Cependant, il est agréable de voir une version utilisant des pointeurs. Sinon, c'est essentiellement la même chose:

#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;
}
2
répondu Rob 2011-03-17 16:06:40

fonction récursive pour inverser une chaîne en place (pas de tampon supplémentaire, malloc).

code court et sexy. Mauvaise utilisation des piles.

#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
répondu Simon Peverett 2012-02-22 10:39:46

Partagez mon code. En tant qu'apprenant C++, en tant qu'option pour utiliser swap(), je demande humblement des commentaires.

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--);
}
1
répondu Pei 2014-11-11 21:13:49

si vous utilisez ATL/MFC CString , appelez simplement CString::MakeReverse() .

1
répondu Michael Haephrati 2017-07-27 17:47:57

encore un autre:

#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
répondu Mike Marrotte 2012-06-08 19:40:47
#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] = '"151900920"';

    return ret;
}

void assert_true(bool boolean)
{
    puts(boolean == true ? "true" : "false");
}
0
répondu masakielastic 2013-10-30 05:28:15

Si vous n'avez pas besoin de les stocker, vous pouvez réduire le temps passé comme ceci:

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");
}
0
répondu Stephen J 2014-05-17 01:46:58

avec C++ lambda:

 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
répondu adem 2017-09-09 18:19:11

ma réponse serait similaire à la plupart d'entre eux, mais s'il vous plaît trouver mon code ici.

//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
répondu GANESH B K 2018-01-11 19:06:23

Utilisation std::reverse()

reverse(begin(str), end(str));

Et c'est tout.

0
répondu Andreas DM 2018-03-12 01:05:14

je pense qu'il y a une autre façon d'inverser la chaîne. obtenir les saisies de l'utilisateur et de l'inverser.

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

}

0
répondu Alok 2018-05-05 12:22:53

Voici mon point de vue en C. Fait pour la pratique et essayé d'être aussi concis que possible! Vous entrez une chaîne de caractères via la ligne de commande, I. E./program_name "entrez la chaîne ici"

#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]=='"151900920"'?reverse(s,e-1,e+s,t,arg),s=++e:e++);
  printf("%s\n",arg);
}
-1
répondu Kevin Heffernan 2012-12-02 13:34:33

mais je pense que L'algorithme de swap XOR est le meilleur...

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;
}
-2
répondu Hasenbeck 2014-11-11 21:08:41
#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 != '"151900920"')
        ;

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

    getchar();
    return 0;
}

code optimisé en langage C pour inverser une chaîne... Et c'est simple; il suffit d'utiliser un simple pointeur pour faire le travail...

-3
répondu Nit kt 2014-11-11 21:10:53

voici le moyen le plus propre, le plus sûr, le plus facile d'inverser une chaîne en C++ (à mon avis):

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

}

une alternative est d'utiliser std::swap , mais j'aime définir mes propres fonctions - c'est un exercice intéressant et vous n'avez pas besoin de include rien de plus.

-4
répondu Oleksiy 2013-10-16 01:13:42
/**
   I am a boy -> boy a am I
*/
    int main()
    {
        int i, j, n, temp, temp_i, cnt;
        //char *array = "Samsung";
        char array[1000];
        char newarr[strlen(array)];
        printf("Enter The String: \n");
        gets(array);

        for(i = (strlen(array)-1), n = 0, j = 0; i >= 0; i--)
        {
         if( array[i] != ' ')
         {
             n++;
         }
         else
         {
             temp = n;
             temp_i = i;
             for(n = 0; n <= temp; n++)
             {
               //  i = i + 1;
                 newarr[j++] = array[i++];
             }
             i = temp_i;
             n = 0;
         }

         if(i == 0)
         {
             newarr[j++] = ' ';
             temp = n;
             temp_i = i;
             for(n = 0; n <= temp; n++)
             {
               //  i = i + 1;
                 newarr[j++] = array[i++];
             }
             i = temp_i;
             n = 0;
         }


         //newarr[j++] = array[i];
        }
        newarr[j] = '"151900920"';
        cnt = 0;
        for(j = 0; j <= (strlen(newarr)-1); j++)//This is not required just do some R n D
        {
            newarr[j] = newarr[++cnt];
        }
       //  printf("The first element is %c \n", newarr[1]);
        puts(newarr);
        return 0;
    }
-8
répondu Rasmi Ranjan Nayak 2012-06-12 10:37:21