2010-02-26 6 views
10

Je sais que cela a été demandé des milliers de fois, mais je ne peux pas trouver l'erreur dans mon code. Est-ce que quelqu'un pourrait indiquer gentiment ce que je fais mal?Inverser une chaîne 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

Même si les gens répondre à votre question figured it out, on ne dit quelle erreur vous obtenez, ou ce qui ne fonctionnait pas ! Vous devez toujours décrire ce que vous attendiez et ce que vous avez réellement vu (sortie incorrecte? Erreur de seg/erreur GPF? Boucle infinie/se bloquer?) – abelenky

+0

C'était une erreur de segmentation. J'aurais dû le mentionner, merci pour le rappel. – qwer

Répondre

13

le problème est ici

char *somestring = "hello"; 

points de SomeString à la chaîne "bonjour". la norme C de ne gurantee pas, mais sur la plupart des machines, ce seront des données en lecture seule, de sorte que vous ne serez pas autorisé à le modifier.

déclare cette façon au lieu

char somestring[] = "hello"; 
+0

La chose que je n'aime pas à propos de cette approche est que la fonction va modifier son paramètre d'entrée. YMMV. – dirkgently

+1

dirkgently: Oui, mais c'est aussi deux fois plus rapide que l'alternative et utilise moins de mémoire. Certains programmeurs travaillent sur des tâches où les performances sont importantes. –

+3

Si la partie critique de votre application consiste à inverser les chaînes dans une boucle étroite, je pense que vous devriez repenser votre conception. –

6

Vous invoquez un comportement non défini en essayant de modifier une zone de mémoire en lecture seule potentiellement (chaînes littérales sont implicitement const - il est autorisé à les lire, mais ne pas les écrire). Créez une nouvelle chaîne et renvoyez-la, ou passez un tampon suffisamment grand et écrivez la chaîne inversée.

-1

Votre logique semble correcte. Au lieu d'utiliser des pointeurs, il est plus propre à traiter char[].

13

En fin de compte, il serait plus propre de le renverser en place, comme ceci:

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

Votre solution est essentiellement une version sémantiquement plus grande de celle-ci. Comprendre la différence entre un pointeur et un tableau. La norme stipule explicitement que le comportement d'une telle opération (modification du contenu d'un littéral de chaîne) n'est pas défini. Vous devriez également voir un extrait this de eskimo:

Lorsque vous initialisez un tableau de caractères avec une constante chaîne:

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

vous vous retrouvez avec un tableau contenant la chaîne, et vous pouvez modifier le contenu du tableau à votre cœur joie:

string[0] = 'J'; 

Cependant, il est possible d'utiliser des constantes de chaîne (le terme officiel est littéraux de chaîne) à d'autres endroits dans votre code. Comme ce sont des tableaux, le compilateur génère des pointeurs sur leurs premiers éléments lorsqu'ils sont utilisés dans les expressions, comme d'habitude. Autrement dit, si vous dites

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

il est presque comme si vous avait dit

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

Ici, les tableaux nommés internal_string_1 et internal_string_2 sont censés suggérer le fait que le compilateur génère effectivement peu temporaire tableaux chaque fois que vous utilisez une constante de chaîne dans votre code. Cependant, le fait subtil est que les tableaux qui sont `` derrière '' les constantes de chaîne ne sont pas nécessairement modifiables. En particulier, le compilateur peut les stocker en lecture seule. Par conséquent, si vous écrivez

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

votre programme peut se bloquer, car il peut essayer de stocker une valeur (dans ce cas, le caractère « J ») dans la mémoire non inscriptible.

La morale est que chaque fois que vous construisez ou de modifier les chaînes, vous devez vous assurer que la mémoire vous construisez ou les modifier en est inscriptible.Cette mémoire doit être soit un tableau que vous avez alloué, soit de la mémoire que vous avez dynamiquement allouée par les techniques que nous verrons dans le chapitre suivant. Assurez-vous qu'aucune partie de votre programme n'essaiera jamais de modifier une chaîne qui est en fait l'un des tableaux non nommés et non-éditables que le compilateur a générés pour vous en réponse à l'une de vos constantes de chaîne. (La seule exception est l'initialisation du tableau, car si vous écrivez dans un tableau, vous écrivez dans le tableau, pas dans le littéral que vous avez utilisé pour initialiser le tableau.) "

+1

Merci pour le code et le lien vers l'explication! J'ai appris beaucoup plus de cette expérience que je ne l'aurais imaginé: P – qwer

+0

@qwer: Content de t'aider. –

+1

Réponse de Kickass. –

0

Vous pouvez utiliser le code suivant

#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

Je prends l'appel strrev() est hors de question?

+0

Oui, le but était d'essayer de l'écrire moi-même. – qwer