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 firstfor(; head < tail;++head,--tail){// walk pointers inwards until they meet or cross in the middlechar 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);return0;}
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){case0xF:/* U+010000-U+10FFFF: four bytes. */
SWP(*(q-0),*(q-3));
SWP(*(q-1),*(q-2));
q -=3;break;case0xE:/* U+000800-U+00FFFF: three bytes. */
SWP(*(q-0),*(q-2));
q -=2;break;case0xC:/* fall-through */case0xD:/* 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);return0;}
Por qué, sí, si la entrada se descorcha, esto cambiará alegremente fuera del lugar.
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.
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;}}
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.
¡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 ++.
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:
#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
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.
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.
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.
@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.
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");return0;}
aString = argv[1];
printf("String to reverse: %s\n", aString );
reverse_r(*aString, aString, aString+1);
printf("Reversed String: %s\n", aString );return0;}
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.
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)
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 memoryfor(; 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í"
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;}
Respuestas:
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).El mismo algoritmo funciona para matrices de enteros con longitud conocida, solo use en
tail = start + length - 1
lugar 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
*p
y*q
es 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.
Ejemplos:
fuente
Esta es la forma más simple en C ++.
fuente
Leer Kernighan y Ritchie
fuente
s
debe declararse en forma de matriz. En otras palabras, enchar s[] = "this is ok"
lugar dechar *s="cannot do this"
porque esto último resulta en una constante de cadena que no se puede modificarInvierta una cadena en su lugar (visualización):
fuente
C no malvada, suponiendo el caso común donde la cadena es una
char
matriz terminada en nulo :fuente
int temp
, esta solución se ve mejor. +1!(*str)
sin embargo.strchr()
buscando'\0'
. Pensé en ambos. No es necesario un bucle.Utiliza el
std::reverse
algoritmo de la biblioteca estándar de C ++.fuente
Ha pasado un tiempo y no recuerdo qué libro me enseñó este algoritmo, pero pensé que era bastante ingenioso y fácil de entender:
fuente
size_t
pensamiento.Utilice el método std :: reverse de STL :
Usted tendrá que incluir la librería "algoritmo",
#include<algorithm>
.fuente
Tenga en cuenta que la belleza de std :: reverse es que funciona con
char *
cadenas ystd::wstring
s tan bien comostd::string
sfuente
*
el tipo y lo pone por el nombre. Maravilloso. Admito que soy algo purista, pero me estremezco cada vez que veo un código similarchar* str;
.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):
UTF-8:
UTF-16 Big Endian:
UTF-16 Little Endian:
fuente
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.
fuente
Otra forma de C ++ (aunque probablemente usaría std :: reverse () mismo :) como más expresivo y más rápido)
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.
fuente
strlen
encontrar 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._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.char* beg = s-1
tiene un comportamiento indefinido (al menos sis
apunta al primer elemento de una matriz, que es el caso más común).while (*++end);
tiene un comportamiento indefinido sis
es una cadena vacía.s-1
tiene un comportamiento definido, incluso sis
apunta al primer elemento de una matriz, por lo que es usted quien debería poder citar el estándar como soporte.Este código produce esta salida:
fuente
En caso de que esté utilizando GLib, tiene dos funciones para eso, g_strreverse () y g_utf8_strreverse ()
fuente
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:
fuente
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.
fuente
char
en 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).Utilizar
std::reverse()
reverse(begin(str), end(str));
Y eso es.
fuente
Comparte mi código Como estudiante de C ++, como una opción para usar swap (), estoy pidiendo humildemente comentarios.
fuente
Si está utilizando ATL / MFC
CString
, simplemente llameCString::MakeReverse()
.fuente
Aún otra:
fuente
fuente
Con C ++ lambda:
fuente
Mi respuesta sería similar a la mayoría de ellos, pero encuentre mi código aquí.
fuente
Creo que hay otra forma de invertir la cadena. obtener la entrada del usuario y revertirla.
fuente
Si no necesita almacenarlo, puede reducir el tiempo que pasa así:
fuente
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í"
fuente
Pero creo que el algoritmo de intercambio XOR es el mejor ...
fuente
strlen()
en la condición de bucle y en el cuerpo del bucle podría no optimizarse.Aquí está la forma más limpia, segura y fácil de revertir una cadena en C ++ (en mi opinión):
Una alternativa es usarla
std::swap
, pero me gusta definir mis propias funciones: es un ejercicio interesante y no necesitainclude
nada más.fuente
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 ...
fuente