2010-02-26 27 views
10

Sé que esto se ha preguntado miles de veces, pero no puedo encontrar el error en mi código. ¿Podría alguien decir amablemente lo que estoy haciendo mal?Invertir una cadena en C

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

void reverseString(char *myString){ 
    char temp; 
    int len = strlen(myString); 

    char *left = myString; 
    // char *right = &myString[len-1];                       
    char *right = myString + strlen(myString) - 1; 

    while(left < right){ 
    temp = *left; 
    *left = *right; // this line seems to be causing a segfault                
    *right = temp; 
    left++; 
    right--; 
    } 
} 

int main(void){ 
    char *somestring = "hello"; 
    printf("%s\n", somestring); 
    reverseString(somestring); 

    printf("%s", somestring); 

} 
+1

a pesar de que las personas que responden a su pregunta averigüé, Nunca se dice qué error que estaba recibiendo, o lo que no estaba funcionando! Siempre debe describir lo que esperaba y lo que realmente vio. (Salida incorrecta? Seg-fault/error GPF? Ciclo infinito/¿colgar?) – abelenky

+0

Fue una segfault. Debería haberlo mencionado, gracias por el recordatorio. – qwer

Respuesta

13

el problema es que aquí

char *somestring = "hello"; 

puntos someString a la cadena literal "hola". el estándar C++ no garantiza esto, pero en la mayoría de las máquinas, esto será solo de lectura, por lo que no podrá modificarlo.

declaran de esta manera en lugar

char somestring[] = "hello"; 
+0

Lo que no me gusta de este enfoque es que la función modificará su parámetro de entrada. YMMV. – dirkgently

+1

dirkgently: Sí, pero también es aproximadamente el doble de rápido que la alternativa y usa menos memoria. Algunos programadores trabajan en tareas donde el rendimiento importa. –

+3

Si la parte crítica del rendimiento de su aplicación está invirtiendo cadenas en un ciclo cerrado, creo que debería reconsiderar su diseño. –

6

está invocando un comportamiento indefinido al tratar de modificar un área de memoria de sólo lectura potencialmente (literales de cadena son implícitamente const - está bien para leerlos, pero no escribirlas). Cree una nueva cadena y devuélvala, o pase un búfer lo suficientemente grande y escriba la cadena invertida en él.

-1

Su lógica parece correcta. En lugar de utilizar punteros, es más limpio tratar con char[].

13

En última instancia, sería más limpio para invertir en su lugar, así:

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

void 
reverse(char *s) 
{ 
    int a, b, c; 
    for (b = 0, c = strlen(s) - 1; b < c; b++, c--) { 
     a = s[b]; 
     s[b] = s[c]; 
     s[c] = a; 
    } 

    return; 
} 

int main(void) 
{ 
    char string[] = "hello"; 
    printf("%s\n", string); 
    reverse(string); 
    printf("%s\n", string); 

    return 0; 
} 

Su solución es esencialmente una versión semánticamente más grande de éste. Comprenda la diferencia entre un puntero y una matriz. El estándar establece explícitamente que el comportamiento de tal operación (modificación del contenido de un literal de cadena) no está definido. También debe ver this extracto de esquimal:

Al inicializar una matriz de caracteres con una constante de cadena:

char string[] = "Hello, world!"; 

se termina con una matriz que contiene la cadena, y se puede modificar el contenido de la matriz a su el contenido del corazón:

string[0] = 'J'; 

Sin embargo, es posible utilizar las constantes de cadena (el término formal es literales de cadena) en otros lugares en el código. Como son matrices, el compilador genera punteros a sus primeros elementos cuando se usan en expresiones, como de costumbre. Es decir, si usted dice

char *p1 = "Hello"; 
int len = strlen("world"); 

Es casi como si hubiera dicho

char internal_string_1[] = "Hello"; 
char internal_string_2[] = "world"; 
char *p1 = &internal_string_1[0]; 
int len = strlen(&internal_string_2[0]); 

En este caso, las matrices nombrado internal_string_1 y internal_string_2 se supone que sugieren el hecho de que el compilador es en realidad la generación poca temporal arrays cada vez que use una constante de cadena en su código. Sin embargo, el hecho sutil es que las matrices que están `` detrás '' de las constantes de cadena no son necesariamente modificables. En particular, el compilador puede almacenarlos en memoria de solo lectura. Por lo tanto, si se escribe

char *p3 = "Hello, world!"; 
p3[0] = 'J'; 

su programa puede bloquearse, ya que puede tratar de almacenar un valor (en este caso, el carácter 'J') en la memoria nonwritable.

La moraleja es que cada vez que esté creando o modificando cadenas, debe asegurarse de que la memoria que está creando o modificando es editable.Esa memoria debe ser una matriz que haya asignado o alguna memoria que haya asignado dinámicamente mediante las técnicas que veremos en el próximo capítulo. Asegúrese de que ninguna parte de su programa intente alguna vez modificar una cadena que en realidad es una de las matrices no identificables y no nombradas que el compilador generó para usted en respuesta a una de sus constantes de cadena. (La única excepción es la inicialización de matriz, porque si escribe en dicha matriz, está escribiendo en la matriz, no en la cadena literal que utilizó para inicializar la matriz.) "

+1

¡Gracias por el código y el enlace a la explicación! Aprendí mucho más de esta experiencia de lo que me gustaría imaginar: P – qwer

+0

@qwer: Me alegra ayudar. –

+1

Respuesta de Kickass. –

0

Puede usar el siguiente código

#include<stdio.h> 
#include<string.h> 
#include<malloc.h> 
char * reverse(char*); 

int main() 
{ 
     char* string = "hello"; 
     printf("The reverse string is : %s", reverse(string)); 
     return 0; 
} 

char * reverse(char* string) 
{ 

    int var=strlen(string)-1; 
    int i,k; 
    char *array; 
    array=malloc(100); 
    for(i=var,k=0;i>=0;i--) 
    { 
      array[k]=string[i]; 
      k++; 
    } 
    return array; 
} 
0

lo llevo llamando strrev() está fuera de la cuestión?

+0

Sí, el punto era intentar escribirlo yo mismo. – qwer