Question

Après avoir lu la FAQ et tout ce que je peux trouver, je suis toujours confus. Si j'ai un pointeur de caractère qui est initialisé de cette façon:

char * s = "Bonjour le monde!"

La chaîne est en mémoire en lecture seule et je ne peux pas la changer comme ceci:

*s = 'W';

faire "Wello world!". Je comprends cela, mais je ne peux pas, pour ma vie, comprendre comment le rendre NON en lecture seule. Dois-je utiliser un tableau au lieu d'un pointeur? Comme ici ?

Ceci est mon code:

char *s = str;
char *e = s;
while (*e != '\0')
e++;
e--;
char *temp;
//Swop the string around
while (s <= e) {
    *temp = *s;
    *s = *e;
    *e = *temp;
    e--;
    s++;
}

Le message d'erreur est simplement une faute de segmentation. Excuses à l'avance si c'est une question vraiment stupide.

Merci beaucoup pour votre aide. Après avoir pris tous vos conseils, je reçois ceci:

void something(char * str) {
    char *store = str;
    char *s = new char[strlen(str) + 1]; //Allocate memory. Nice one.
    strcpy(s, str);
    char *e = new char[strlen(str) + 1];
    strcpy(e, str);
    while (*e != '\0')
        e++;
    e--;
    char temp; //no longer a pointer
    while (s <= e) {
        cout << *e;
        temp = *s;
        *s = *e;
        *e = temp;
        e--;
        s++;

    }
    delete [] e;
    delete [] s;        
}

Cependant, les suppressions à la fin de la fonction semblent causer leurs propres erreurs de segmentation. Pourquoi?

Par souci d’intérêt: Les erreurs sont dues à l’accès aux pointeurs e et s après leur incrémentation. Une solution beaucoup plus simple en a résulté:

void something(char * str) {
    char *s = new char[strlen(str) + 1];
    strcpy(s, str);
    char temp;
    int j = strlen(str) - 1;
    for (int i = 0; i <= strlen(str)/2; i++) {
        cout << s << endl;
        temp = s[i];
        s[i] = s[j];
        s[j] = temp;
        j--;
    }
    delete [] s;
}
Était-ce utile?

La solution

Le moyen le plus simple de le modifier consiste à créer un tableau pour votre stockage, puis à y copier la chaîne.

Par exemple:

char buf[128];
const char *src = "Hello World";
strncpy(buf, src, 127); // one less - we always 0-terminate
buf[127] = '\0';

// you can now modify buf
buf[0] = 'W';

La raison pour laquelle votre code ne fonctionne pas, c'est que vous n'avez alloué aucune mémoire à la copie de la chaîne. Vous venez de créer un deuxième pointeur sur la même mémoire en lecture seule. (Et ensuite essayé de le copier? Je ne sais pas trop ce que fait le reste du code.) Vous devez obtenir une mémoire non-en lecture seule quelque part, et il est beaucoup plus facile d'utiliser la bibliothèque standard pour le copier dans cette nouvelle mémoire, plutôt que d’écrire vous-même la boucle.

Si vous ne connaissez pas la longueur de la chaîne à l'avance, vous pouvez également utiliser malloc (ou, mieux encore, faire ce que drschnz répond et utiliser new char [] ]:

const char *src = "Hello world";
char *buf = malloc(strlen(src) + 1);   // or = new char[strlen(src) + 1];
strcpy(buf, src);
// you can now modify buf
// later, you need to free it
free(buf);                             // or delete [] buf;

De plus, si vous utilisez C ++, vous pouvez simplement utiliser un std :: string:

std::string myString("Hello world");
myString[0] = "W";

L’espoir que cela aide.

Autres conseils

Essayez:

char src[] = "Hello world";
src[6]     = 'W';

-- // or

char   buffer[] = "Hello world";
char*  src      = buffer;
src[6]          = 'W';

Si vous souhaitez copier une chaîne dans un tampon, utilisez strcpy () ou strncpy ()

char   buffer[20];
char const* s = "Hello World"

strcpy(s,buffer);

Si vous devez écrire votre propre copie de chaîne, elle devrait ressembler à ceci:

char   buffer[20];
char const* s = "Hello World";

// OK this is not the perfect solution but it is easy to read.
for(int loop = 0;s[loop] != '\0';++loop)
{
    buffer[loop] = s[loop];
}
buffer[loop] = '\0';

Le pointeur n'est pas en lecture seule. (les données de chaîne elles-mêmes sont, mais un pointeur pointant dessus peut être modifié librement) Cependant, l'attribution d'un caractère à un pointeur ne fait pas ce que vous attendez.

En général, la seule chose que vous puissiez affecter à un point est une adresse. Vous ne pouvez pas affecter de valeurs, uniquement l'adresse de valeurs.

Les littéraux de chaîne (comme "hello world") constituent l'exception, car les chaînes sont spéciales. Si vous assignez l'un de ceux-ci à un pointeur, vous obtenez un pointeur sur cette chaîne. Mais en général, vous attribuez des adresses à des pointeurs.

L’autre aspect est que les caractères en C ++ sont des types de données intégrés. Ils peuvent être traités comme des entiers, sans casting requis. Je peux faire int i = 'W' et le compilateur ne se plaindra pas.

Que se passe-t-il si vous assignez un "W" à un pointeur? Il prend 'W' comme valeur entière et suppose qu'il s'agit d'une adresse. 'W' a la valeur ASCII 127, vous définissez donc votre pointeur de manière à pointer sur l'adresse 127, ce qui n'a pas de sens.

Cependant, je ne vois pas en quoi cela a beaucoup à faire avec votre code. Le problème semble être que temp ne pointe pas sur des données valides. Vous déclarez un pointeur qui pointe vers une adresse non définie. Et ensuite, vous dites "où qu’il pointe, je veux écrire la valeur indiquée par s . Les éléments suivants devraient fonctionner un peu mieux:

char temp; // not a pointer. We want a character to store our temporary value in
while (s <= e) {
    temp = *s; // note, no * on temp.
    *s = *e;
    *e = temp; // note, no * on temp.
    e--;
    s++;
}

Toutefois, si str pointe sur un littéral de chaîne, tel que "hello world", ce ne sera pas légal, car les données de chaîne sont en lecture seule. Le compilateur peut ne pas l'appliquer, mais vous vous êtes ensuite aventuré dans des terres à comportement indéfini. Si vous souhaitez modifier la chaîne, copiez-la dans un tampon local, comme l’a montré l’une des autres réponses.

Vous semblez un peu confus quant à la sémantique des pointeurs. Assigner une adresse (ou quelque chose qui peut être converti en une adresse, comme un entier) à un pointeur fait en sorte que le pointeur se dirige vers cette adresse. Cela ne modifie pas les données pointées. Déclarer un pointeur ne signifie pas qu'il indiquera quelque chose de significatif. Si vous souhaitez stocker un caractère, déclarez une variable de caractère. Un pointeur ne stocke pas de données, il pointe simplement sur des données allouées ailleurs.

modifier Commentaires et corrections sur votre code mis à jour:

void something(const char * str) { // let the function take a pointer to a non-modifiable string, so add the const. Now it's clear that we're not allowed to modify the string itself, so we have to make a copy.
    char *s = new char[strlen(str) + 1]; // Since the original string is const, we have to allocate a copy if we want to modify it - in C, you'd use malloc(strlen(str)) instead
    strcpy(s, str);
    char *e = s; // make e point to the start of the copied string (don't allocate two copies, since e and s are supposed to work on the same string
    while (*e != '\0') { // add braces so it's clear where the loop starts and ends.
        e++;
    }
    e--;

    while (s <= e) { // the loop condition wouldn't work if s and e pointed to separate copies of the string
        cout << *e; // why? I thought you just wanted to reverse the string in memory. Alternatively, if you just want to print out the string reversed, you don't need to do most of the rest of the loop body. In C, you'd use printf instead of *e
        char temp = *s; // might as well declare the temp variable when you need it, and not before
        *s = *e;
        *e = temp;
        e--;
        s++;

    }
}

Juste pour référence, et en réponse aux commentaires sur C vs C ++, voici comment écrire une fonction pour inverser une chaîne en C ++:

std::string revert_string(const std::string& str) {
  return std::string(str.rbegin(), str.rend());
}

Ou pour rétablir la chaîne in-situ:

std::string revert_string(const std::string& str) {
  std::reverse(str.begin(), str.end());
}

Techniquement, ce que vous avez est plus correctement écrit comme ça:

const char *s = "Hello world!"

Ce que vous voulez réellement, c'est quelque chose comme ça:

char s[] = "Hello world!"

Le fait de suivre quelques lignes peut vous aider à mieux comprendre:

const char *p = "Hello World";
char q[] = "Hello World";
printf("%d %d", sizeof(p), sizeof(q));
// p[0] = 'W' // INVALID
q[0] = 'W'; // valid

Vos suppressions génèrent des erreurs, car vous avez modifié le pointeur. Vous devez enregistrer l'emplacement d'origine du nouveau et le supprimer []. Vous essayez de supprimer un emplacement qui ne se trouve pas dans la table d'allocation. Si vous souhaitez modifier la valeur du pointeur, créez un autre caractère * temp = t; et l'utiliser pour parcourir la chaîne.

Il y a une fonction "strdup ()". faire une copie d'une chaîne ... cela vous permet de ne pas oublier les mots clés "+ 1". dans votre malloc.

char* source = "Hello World";
char* dest = strdup(source);
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top