¿Cómo invierte una cadena en su lugar en C o C ++?


Respuestas:


123

El algoritmo estándar es usar punteros al inicio / final, y caminar hacia adentro hasta que se encuentren o se crucen en el medio. Intercambia a medida que avanzas.


Cadena ASCII inversa, es decir, una matriz terminada en 0 donde cada carácter cabe en 1 char. (U otros conjuntos de caracteres no multibyte).

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

El mismo algoritmo funciona para matrices de enteros con longitud conocida, solo use en tail = start + length - 1lugar del ciclo de búsqueda final.

(Nota del editor: esta respuesta originalmente también usó XOR-swap para esta versión simple. Se corrigió para el beneficio de los futuros lectores de esta pregunta popular. XOR-swap no es muy recomendable ; difícil de leer y hacer que su código se compile de manera menos eficiente. Usted puede ver en el explorador del compilador Godbolt lo mucho más complicado que es el cuerpo del bucle asm cuando se compila xor-swap para x86-64 con gcc -O3).


Ok, bien, arreglemos los caracteres UTF-8 ...

(Esto es algo de intercambio XOR. Tenga en cuenta que debe evitar el intercambio con uno mismo, porque si *py *qes la misma ubicación, lo pondrá a cero con un ^ a == 0. El intercambio XOR depende de tener dos ubicaciones distintas, usándolos cada uno como almacenamiento temporal).

Nota del editor: puede reemplazar SWP con una función en línea segura utilizando una variable 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;
}
  • Por qué, sí, si la entrada se descorcha, esto cambiará alegremente fuera del lugar.
  • Enlace útil al destrozar en UNICODE: http://www.macchiato.com/unicode/chart/
  • Además, UTF-8 sobre 0x10000 no se ha probado (ya que parece que no tengo ninguna fuente, ni la paciencia para usar un editor hexadecimal)

Ejemplos:

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

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

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

./strrev verrts/.

162
No hay una buena razón para usar el intercambio XOR fuera de una competencia de código ofuscado.
Chris Conway

28
¿Crees que "en el lugar" significa "sin memoria extra", ni siquiera O (1) memoria para temporales? ¿Qué pasa con el espacio en la pila para str y la dirección de retorno?
Chris Conway

55
@Bill, eso no es lo que significa la definición común de "en el lugar". Los algoritmos in situ pueden usar memoria adicional. Sin embargo, la cantidad de esta memoria adicional no debe depender de la entrada, es decir, debe ser constante. Por lo tanto, el intercambio de valores con almacenamiento adicional está completamente en su lugar.
Konrad Rudolph el

19
No votar a favor de esto hasta que el intercambio xor desaparezca.
Adam Rosenfield el

34
El intercambio de XOR es más lento que el intercambio mediante el registro en procesadores modernos fuera de servicio.
Patrick Schlüter

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

Esta es la forma más simple en C ++.


66
En C ++, una cadena está representada por la clase de cadena. No pidió "char star" o "char brackets".
Mantén la

10
@fredsbend, la versión "ridículamente larga" de la respuesta seleccionada maneja un caso que esta respuesta simple no tiene: entrada UTF-8. Muestra la importancia de especificar completamente el problema. Además, la pregunta era sobre el código que también funcionaría en C.
Mark Ransom

55
Esta respuesta maneja el caso si usa una clase de cadena compatible con UTF-8 (o posiblemente una clase de caracteres utf-8 con std :: basic_string). Además, la pregunta decía "C o C ++", no "C y C ++". C ++ solo es "C o C ++".
Taywee

161

Leer Kernighan y 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;
    }
}

8
Probado en mi iPhone, esto es más lento que usar direcciones de puntero sin procesar en aproximadamente un 15%
jjxtra

3
¿No debería la variable "c" ser un char en lugar de un int?
Lesswire

17
Es importante tener en cuenta en este ejemplo que la cadena sdebe declararse en forma de matriz. En otras palabras, en char s[] = "this is ok"lugar de char *s="cannot do this"porque esto último resulta en una constante de cadena que no se puede modificar
usuario1527227

3
Con se disculpa con "El Padrino" .... "Deja las armas, trae el K&R". Como un intolerante C, que haría uso de punteros, ya que son más simples y más recta hacia adelante para este problema, pero el código sería menos portátiles a C #, Java, etc.

2
@Eric Esto no se ejecuta en tiempo O (log (n)). Se ejecuta en O (n) si se refiere al número de intercambios de caracteres que realiza el código, para n de longitud de cadena, entonces se realizan n intercambios. Si estamos hablando de la cantidad de bucles realizados, sigue siendo O (n), aunque O (n / 2), pero elimina las constantes en la notación Big O.
Stephen Fox

62

Invierta una cadena en su lugar (visualización):

Invierta una cuerda en su lugar


¡Frio! ¿Qué usaste para crear esto? Creo que la respuesta mejoraría al incluir un enlace.
Pryftan

La implementación de este algoritmo está realmente en esta respuesta .
karlphillip

¿Puedes explicar esto un poco, así que si el enlace de la imagen muere, la respuesta no será inútil?
SS Anne

41

C no malvada, suponiendo el caso común donde la cadena es una charmatriz terminada en nulo :

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

En lugar de usar un ciclo while para encontrar el puntero final, ¿no puedes usar algo como end_ptr = str + strlen (str); Sé que hará prácticamente lo mismo, pero lo encuentro más claro.
Peter Kühne

Lo suficientemente justo. Intenté (y no pude) evitar el error off-by-one en la respuesta de @ uvote.
Chris Conway

Además de una posible mejora del rendimiento con quizás int temp, esta solución se ve mejor. +1
chux - Restablecer Monica

@ chux-ReinstateMonica Sí. Es bonito. Personalmente, eliminaría los () s del !(*str)sin embargo.
Pryftan

@ PeterKühne Sí o strchr()buscando '\0'. Pensé en ambos. No es necesario un bucle.
Pryftan

35

Utiliza el std::reversealgoritmo de la biblioteca estándar de C ++.


14
Standard Template Library es un término pre-estándar. El estándar C ++ no lo menciona, y los componentes STL anteriores se encuentran en la Biblioteca Estándar C ++.
Nemanja Trifunovic

16
Derecha. Siempre me pregunto por qué tanta gente todavía lo llama "STL" a pesar de que solo sirve para confundir el asunto. sería mejor si más personas son como tú y lo llaman simplemente "Biblioteca estándar de C ++" o STL y dicen "Biblioteca estándar" :)
Johannes Schaub - litb

27

Ha pasado un tiempo y no recuerdo qué libro me enseñó este algoritmo, pero pensé que era bastante ingenioso y fácil de entender:

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

Es una variación interesante sí. Técnicamente debería ser un size_tpensamiento.
Pryftan

24

Utilice el método std :: reverse de STL :

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

Usted tendrá que incluir la librería "algoritmo", #include<algorithm>.


1
¿Qué biblioteca necesita ser incluida?
Don Cruickshank

#include <algorithm> Olvidé escribirlo y luego edité la respuesta pero no se guardó, por eso faltaba el nombre ..
user2628229

Aunque esta habría sido mi respuesta también, solo curioso, porque el OP preguntó "sin un búfer para contener la cadena invertida" (básicamente, intercambio en el lugar), ¿cómo se prueba que esto se está haciendo? ¿Se explica que usa internamente std :: iter_swap <>, iterando hasta el punto medio del búfer desde ambos puntos finales? Además, OP solicitó tanto C como C ++, esto es solo para C ++ (¿podemos esperar que <string.h> tenga el método strrev ()?)
HidekiAI

21

Tenga en cuenta que la belleza de std :: reverse es que funciona con char *cadenas y std::wstrings tan bien como std::strings

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

1
Por un lado, quiero vomitar porque usaste C ++ pero, por otro, es algo hermoso, hermoso, absolutamente hermoso ver a alguien usar C ++ que no pone *el tipo y lo pone por el nombre. Maravilloso. Admito que soy algo purista, pero me estremezco cada vez que veo un código similar char* str;.
Pryftan

11

Si está buscando revertir los búferes terminados en NULL, la mayoría de las soluciones publicadas aquí están bien. Pero, como Tim Farley ya señaló, estos algoritmos funcionarán solo si es válido suponer que una cadena es semánticamente una matriz de bytes (es decir, cadenas de un solo byte), lo cual es una suposición incorrecta, creo.

Tomemos, por ejemplo, la cadena "año".

Los puntos de código Unicode son 0x61, 0xf1, 0x6f.

Considere algunas de las codificaciones más utilizadas:

Latin1 / iso-8859-1 (codificación de un solo byte, 1 carácter es 1 byte y viceversa):

Original:

0x61, 0xf1, 0x6f, 0x00

Contrarrestar:

0x6f, 0xf1, 0x61, 0x00

El resultado está bien

UTF-8:

Original:

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

Contrarrestar:

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

El resultado es galimatías y una secuencia ilegal UTF-8

UTF-16 Big Endian:

Original:

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

El primer byte se tratará como un terminador NUL. No se realizará ninguna inversión.

UTF-16 Little Endian:

Original:

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

El segundo byte se tratará como un terminador NUL. El resultado será 0x61, 0x00, una cadena que contiene el carácter 'a'.


std :: reverse funcionará para los tipos unicode de dos bytes, siempre que esté utilizando wstring.
Eclipse

No estoy muy familiarizado con C ++, pero supongo que cualquier función de biblioteca estándar respetable que trate con cadenas podrá manejar diferentes codificaciones, por lo que estoy de acuerdo con usted. Por "estos algoritmos", me refería a las funciones inversas ad-hoc publicadas aquí.
Juan Pablo Califano

Desafortunadamente, no hay tal cosa como "función respetable que se ocupe de cadenas" en C ++ estándar.
Jem

@Eclipse Si invierte un par sustituto, el resultado ya no será correcto. Unicode no es realmente un
juego de

Lo que me gusta de esta respuesta es que muestra el orden real de los bytes (aunque la endianidad podría ser algo, ah, veo que realmente lo consideró) y cómo es correcto o incorrecto. Pero creo que la respuesta mejoraría si incorporas algún código que demuestre esto.
Pryftan

11

En aras de la exhaustividad, debe señalarse que hay representaciones de cadenas en varias plataformas en las que el número de bytes por carácter varía según el carácter. Los programadores de la vieja escuela se referirían a esto como DBCS (Conjunto de caracteres de doble byte) . Los programadores modernos suelen encontrar esto en UTF-8 (así como en UTF-16 y otros). También hay otras codificaciones de este tipo.

¡En cualquiera de estos esquemas de codificación de ancho variable, los algoritmos simples publicados aquí ( malvados , no malvados u otros ) no funcionarían correctamente! De hecho, incluso podrían hacer que la cadena se vuelva ilegible o incluso una cadena ilegal en ese esquema de codificación. Vea la respuesta de Juan Pablo Califano para algunos buenos ejemplos.

std :: reverse () podría funcionar en este caso, siempre y cuando la implementación de su plataforma de la Biblioteca estándar de C ++ (en particular, los iteradores de cadenas) lo tenga en cuenta correctamente.


66
std :: reverse NO tiene esto en cuenta. Invierte value_type's. En el caso de std :: string, invierte los caracteres. No personajes
MSalters

Digamos más bien que nosotros, los programadores de la vieja escuela, sabemos de DBCS pero también de UTF-8: ¡porque todos sabemos que los programadores son como adictos cuando dicen 'una línea más y renunciaré'! Estoy seguro de que algunos programadores eventualmente renuncian, pero francamente la programación realmente es como una adicción para mí; Recibo retiros por no programar. Es un buen punto que agregue aquí. No me gusta C ++ (traté realmente de que me gustara incluso escribir un poco, pero aún así es estéticamente poco atractivo para decir lo menos), así que no puedo comentar allí, pero de todos modos haces un buen punto. tener un +1.
Pryftan

5

Otra forma de C ++ (aunque probablemente usaría std :: reverse () mismo :) como más expresivo y más rápido)

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

La forma C (más o menos :)) y, por favor, tenga cuidado con el truco XOR para el intercambio, los compiladores a veces no pueden optimizar eso.

En tal caso, suele ser mucho más lento.

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

Solía strlenencontrar el final de la cadena, si es potencialmente larga. Una buena implementación de la biblioteca utilizará vectores SIMD para buscar más rápido que 1 byte por iteración. Pero para cadenas muy cortas, while (*++end);se realizará antes de que se inicie una búsqueda de función de biblioteca.
Peter Cordes

@PeterCordes bien, de acuerdo, strlen debe usarse de todos modos para facilitar la lectura. Para cadenas más largas, siempre debe mantener la longitud en un varialbe de todos modos. Strlen en SIMD generalmente se da como un ejemplo con este descargo de responsabilidad, que no es una aplicación de la vida real, o al menos fue hace 5 años, cuando se escribió el código. ;)
pprzemek

1
Si quisieras que esto se ejecute rápidamente en CPU reales, usarías barajas SIMD para hacer lo contrario en trozos de 16B. : P por ejemplo, en x86, _mm_shuffle_epi8(PSHUFB) puede invertir el orden de un vector 16B, dado el vector de control aleatorio correcto. Probablemente puede ejecutarse a una velocidad casi de memoria con una optimización cuidadosa, especialmente con AVX2.
Peter Cordes

char* beg = s-1tiene un comportamiento indefinido (al menos si sapunta al primer elemento de una matriz, que es el caso más común). while (*++end);tiene un comportamiento indefinido si ses una cadena vacía.
melpomene

@pprzemek Bueno, está haciendo la afirmación de que s-1tiene un comportamiento definido, incluso si sapunta al primer elemento de una matriz, por lo que es usted quien debería poder citar el estándar como soporte.
melpomene

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

Este código produce esta salida:

gnitset
a
cba

2
@uvote, no uses strcpy. Nunca. Si tiene que usar algo como strcpy, use strncpy. Strcpy es peligroso. Por cierto, C y C ++ son dos lenguajes separados con instalaciones separadas. Creo que está utilizando archivos de encabezado solo disponibles en C ++, ¿realmente necesita una respuesta en C?
Onorio Catenacci

66
strcpy es perfectamente seguro si el programador puede realizar un seguimiento del tamaño de sus matrices, muchos argumentarán que strncpy es menos seguro ya que no garantiza que la cadena resultante sea nula. En cualquier caso, no hay nada de malo con el uso que hace uvote de strcpy aquí.
Robert Gamble

1
@Onorio Catenacci, strcpy no es peligroso si sabe que la cadena de origen se ajustará dentro del búfer de destino, como en los casos indicados en el código anterior. Además, strncpy cero-llena hasta el número de caracteres especificados en el parámetro de tamaño si hay espacio sobrante, que puede no ser deseado.
Chris Young

3
Cualquiera que no pueda usar strcpy correctamente no debería programar en C.
Robert Gamble

2
@Robert Gamble, estoy de acuerdo. Sin embargo, dado que no conozco ninguna forma de evitar que las personas programen en C sin importar su competencia, generalmente recomiendo no hacerlo.
Onorio Catenacci


3

Me gusta la respuesta de Evgeny K&R. Sin embargo, es bueno ver una versión con punteros. De lo contrario, es esencialmente lo mismo:

#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

Función recursiva para invertir una cadena en su lugar (sin búfer adicional, malloc).

Código corto y sexy. Mal, mal uso de la pila.

#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
Esa es una solución bastante divertida, debe agregar algo de rastreo como printf ("% * s> [% d] reverse_r ('% c',% p = \"% s \ ",% p = \"% s \ ") \ n ", profundidad," ", profundidad, val, s, (s? s:" nulo "), n, (n? n:" nulo ")); al inicio y <al final.
Benoît

Empujar cada uno charen la pila no cuenta como "en su lugar". Especialmente no cuando estás presionando 4 * 8B por personaje (en una máquina de 64 bits: 3 args + una dirección de retorno).
Peter Cordes

La pregunta original es "¿Cómo se invierte una cadena en C o C ++ sin requerir un búfer separado para contener la cadena invertida?" - no había ningún requisito para intercambiar 'en el lugar'. Además, esta solución menciona el uso incorrecto de la pila desde el principio. ¿Estoy siendo rechazado por la pobre comprensión de lectura de otras personas?
Simon Peverett

1
No lo llamaría 'sexy', pero diría que es demostrativo e instructivo. Si la recursión se usa correctamente, puede ser muy valiosa. Sin embargo, debe señalarse que, por último que sabía, C ni siquiera requiere una pila per se; Sin embargo hace recursión. De cualquier manera, es un ejemplo de recursión que, si se usa correctamente, puede ser muy útil y valioso. Sin embargo, no creo que lo haya visto antes para invertir una cadena.
Pryftan


1

Comparte mi código Como estudiante de C ++, como una opción para usar swap (), estoy pidiendo humildemente comentarios.

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

Aún otra:

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

}

Esto demuestra la aritmética del puntero, como mi respuesta, pero lo combina con Swap. Creo que esta respuesta agrega mucho, en realidad. Debería poder comprender este tipo de código antes de agregar mil millones de bibliotecas como dependencias solo para obtener un cuadro de texto simple (algo que veo con demasiada frecuencia en las aplicaciones modernas con las que trabajo)
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

Con 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

Mi respuesta sería similar a la mayoría de ellos, pero encuentre mi código aquí.

//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

Creo que hay otra forma de invertir la cadena. obtener la entrada del usuario y revertirla.

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

Es cierto, pero esto solo imprime el orden inverso, ¿verdad? (No uso C ++, así que tal vez .put () no hace lo que creo que hace).
Pryftan

-1

Si no necesita almacenarlo, puede reducir el tiempo que pasa así:

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

Parece que soy la única respuesta que no tiene un búfer o variable temporal. Yo uso la longitud de la cadena, pero los otros que hacen esto agregan otro para la cabeza (vs cola). Supongo que el func inverso estándar almacena la variable, mediante un intercambio o algo así. Por lo tanto, tengo la impresión, suponiendo que la matemática del puntero y el tipo de UTF se alinean, que esta es posiblemente la única respuesta que realmente responde a la pregunta. Los printf () añadidos se pueden quitar, simplemente lo hice para ver mejor el resultado. Escribí esto para la velocidad. No hay asignaciones adicionales ni vars. Probablemente el algoritmo más rápido para mostrar str inverso ()
Stephen J

-3

Aquí está mi opinión en C. ¡Lo hice para practicar y traté de ser lo más conciso posible! Usted ingresa una cadena a través de la línea de comando, es decir ./program_name "ingrese la cadena aquí"

#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
Es un lío ilegible, pero aparentemente no está buscando el código más corto posible ( código golf ) porque algunos nombres de variables son más de un carácter.
Peter Cordes

-4

Pero creo que el algoritmo de intercambio XOR es el mejor ...

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

Una llamada a strlen()en la condición de bucle y en el cuerpo del bucle podría no optimizarse.
Peter Cordes

-5

Aquí está la forma más limpia, segura y fácil de revertir una cadena en C ++ (en mi opinión):

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

}

Una alternativa es usarla std::swap, pero me gusta definir mis propias funciones: es un ejercicio interesante y no necesita includenada más.


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

Este es un código optimizado en el lenguaje C para invertir una cadena ... Y es simple; solo use un puntero simple para hacer el trabajo ...


Esto imprime la secuencia un carácter a la vez. No lo invierte en el lugar. También espera la entrada del usuario sin ningún motivo.
Peter Cordes
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.