Domanda

Dopo aver letto le domande frequenti e tutto ciò che riesco a trovare, sono ancora confuso. Se ho un puntatore a caratteri inizializzato in questo modo:

char * s = " Ciao mondo! "

La stringa è nella memoria di sola lettura e non posso cambiarla in questo modo:

*s = 'W';

per creare " Wello world! " ;. Questo lo capisco, ma non posso, per la mia vita, capire come renderlo NON di sola lettura. Devo usare un array anziché un puntatore? Come qui ?

Questo è il mio codice:

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

Il messaggio di errore è solo un errore di segmentazione. Ci scusiamo in anticipo se questa è una domanda davvero stupida.

Grazie mille per tutto l'aiuto. Dopo aver ricevuto tutti i tuoi consigli, ottengo questo:

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

tuttavia, le eliminazioni alla fine della funzione sembrano causare i propri errori di segmentazione. Perché?

Per interesse: i guasti erano dovuti all'accesso ai puntatori e e s dopo che erano stati incrementati. Ne è seguita una soluzione molto più semplice:

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;
}
È stato utile?

Soluzione

Il modo più semplice per modificarlo è creare un array per il tuo archivio, quindi copiare la stringa in esso.

Ad esempio:

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';

Il motivo per cui il tuo codice non funziona è che non hai allocato memoria per la copia della stringa: hai appena creato un secondo puntatore sulla stessa memoria di sola lettura. (E poi hai provato a copiarlo? Non sono del tutto sicuro di cosa stia facendo il resto del codice.) Devi ottenere un po 'di memoria di sola lettura da qualche parte, ed è molto più facile usare la libreria standard per copiarla quel nuovo ricordo, piuttosto che scrivere il ciclo da soli.

Nel caso in cui non si conosca in anticipo la lunghezza della stringa, è anche possibile utilizzare malloc (o, ancora meglio, fare ciò che dice la risposta di drschnz e utilizzare 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;

Inoltre, se stai usando C ++, puoi semplicemente usare uno std :: string:

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

Spero che sia d'aiuto.

Altri suggerimenti

Prova:

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

-- // or

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

Se vuoi copiare una stringa in un buffer, usa strcpy () o strncpy ()

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

strcpy(s,buffer);

Se devi scrivere la tua copia di stringa, dovrebbe apparire così:

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';

Il puntatore non è di sola lettura. (i dati della stringa stessa sono, ma un puntatore che punta ad esso può essere modificato liberamente) Tuttavia, assegnare un carattere a un puntatore non fa ciò che ti aspetti.

In generale, l'unica cosa che puoi assegnare a un punto è un indirizzo. Non puoi assegnare valori, solo l'indirizzo dei valori.

I letterali di stringa (come "ciao mondo") sono l'unica eccezione, perché le stringhe sono speciali. Se si assegna uno di questi a un puntatore, si ottiene un puntatore a quella stringa. Ma in generale, assegni gli indirizzi ai puntatori.

L'altro punto è che i caratteri in C ++ sono tipi di dati integrali. Possono essere trattati come numeri interi senza necessità di casting. Posso fare int i = 'W' e il compilatore non si lamenterà.

Quindi cosa succede se si assegna 'W' a un puntatore? Prende "W" come valore intero e presuppone che si tratti di un indirizzo. 'W' ha il valore ASCII 127, quindi stai impostando il puntatore in modo che punti all'indirizzo 127, il che non ha senso.

Non vedo come ciò abbia molto a che fare con il tuo codice. Il problema sembra essere che temp non punta a dati validi. Si dichiara un puntatore, che punta a un indirizzo indefinito. E poi dici " ovunque punti, voglio scrivere il valore a cui s punta. Quanto segue dovrebbe funzionare un po 'meglio:

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

Tuttavia, se str punta a una stringa letterale, come " ciao mondo " ;, questo non sarà legale, poiché i dati della stringa stessa sono di sola lettura. Il compilatore potrebbe non applicarlo, ma poi ti sei avventurato in una terra dal comportamento indefinito. Se si desidera modificare la stringa, copiarla in un buffer locale, come mostrato da una delle altre risposte.

Sembri un po 'confuso riguardo alla semantica dei puntatori. Assegnare un indirizzo (o qualcosa che può essere convertito in un indirizzo, come un numero intero) in un puntatore fa puntare il puntatore a quell'indirizzo. Non modifica i dati puntati. Dichiarare un puntatore non significa che punterà a qualcosa di significativo. Se si desidera archiviare un carattere, dichiarare una variabile carattere. Un puntatore non memorizza i dati, punta solo ai dati allocati altrove.

modifica Commenti e correzioni al codice aggiornato:

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++;

    }
}

Solo per riferimento, e in risposta ai commenti su C vs C ++, ecco come scriverei una funzione per invertire una stringa in C ++:

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

O per ripristinare la stringa sul posto:

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

Tecnicamente, quello che hai è scritto più correttamente in questo modo:

const char *s = "Hello world!"

Quello che vuoi davvero avere è qualcosa del genere:

char s[] = "Hello world!"

Seguire alcune righe può aiutarti a capire di più:

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

Le tue eliminazioni generano errori, perché hai cambiato il puntatore. È necessario salvare la posizione originale del nuovo ed eliminarlo []. Si tenta di eliminare una posizione che non si trova nella tabella di allocazione. Se vuoi cambiare il valore del puntatore, crea un altro carattere * temp = t; e usalo per scorrere la stringa.

Esiste una funzione " strdup () " per creare una copia di una stringa ... assicurati di non dimenticare il " + 1 " nel tuo malloc.

char* source = "Hello World";
char* dest = strdup(source);
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top