Inverser une chaîne en C

je sais que cela a été demandé des milliers de fois mais je ne peux pas trouver l'erreur dans mon code. Quelqu'un pourrait-il gentiment signaler ce que je fais mal?

#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("%sn", somestring);
  reverseString(somestring);

  printf("%s", somestring);

}
10
demandé sur Lorenzo Donati 2010-02-27 02:51:28

6 réponses

le problème est ici

char *somestring = "hello";

somestring pointe vers la chaîne littérale "hello". le standard C++ ne garantit pas cela, mais sur la plupart des machines, ce sont des données en lecture seule, donc vous ne serez pas autorisé à les modifier.

déclarer cette façon, au lieu

char somestring[] = "hello";
13
répondu John Knoeller 2010-02-26 23:54:50

en fin de compte, il serait plus propre de l'inverser en place, comme suit:

#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'une chaîne littérale) n'est pas défini. Vous devriez également voir extrait de esquimau:

lorsque vous initialisez un tableau de caractères avec un chaîne de caractères:

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

vous finissez avec un tableau contenant la chaîne, et vous pouvez modifier le contenu du tableau au contenu de votre cœur:

string[0] = 'J';

cependant, il est possible d'utiliser des constantes de chaîne (le terme formel est string literals) à d'autres endroits dans votre code. Comme ce sont des tableaux, le compilateur génère des pointeurs vers leurs premiers éléments lorsqu'ils sont utilisés dans des expressions, comme d'habitude. C'est, si vous dites

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

c'est presque comme si vous aviez 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 en fait de petits tableaux temporaires 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 mémoire en lecture seule. Par conséquent, si vous écrivez

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

votre programme peut crash, parce qu'il peut essayer de stocker une valeur (dans ce cas, le caractère 'J') dans une mémoire non inscriptible.

la morale est que chaque fois que vous construisez ou modifiez des cordes, vous devez vous assurer que la mémoire dans laquelle vous construisez ou modifiez les cordes est accessible par écrit. Cette mémoire devrait être soit un tableau que vous avez alloué, soit une mémoire que vous avez affectée dynamiquement par les techniques que nous verrons dans le prochain chapitre. Assurez-vous qu'aucune partie de votre programme sera jamais essayer de modifier un string qui est en fait l'un des tableaux non nommés et non consignés que le compilateur a généré pour vous en réponse à l'une de vos constantes de string. (La seule exception est l'initialisation du tableau, parce que si vous écrivez à un tel tableau, vous écrivez au tableau, et non à la chaîne de caractères littérale que vous avez utilisée pour initialiser le tableau.) "

13
répondu Muhammed Abiola 2010-02-27 00:32:53

Vous invoquez un comportement non défini en essayant de modifier une zone mémoire potentiellement en lecture seule (les caractères littéraux des chaînes sont implicitement const -- c'est ok pour les lire mais pas écrire). Créez une nouvelle chaîne et retournez-la, ou passez un tampon assez grand et écrivez la chaîne inversée à elle.

6
répondu dirkgently 2010-02-26 23:54:01

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
répondu muruga 2010-03-01 09:43:55

je suppose qu'appeler strrev () est hors de question?

0
répondu Martin Milan 2010-03-01 09:47:54

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

-1
répondu fastcodejava 2010-02-27 00:00:57