¿Es posible modificar una cadena de caracteres en C?

He estado luchando durante algunas horas con todo tipo de tutoriales en C y libros relacionados con punteros, pero lo que realmente quiero saber es si es posible cambiar un puntero de char una vez que se ha creado.

Esto es lo que he intentado:

char *a = "This is a string"; char *b = "new string"; a[2] = b[1]; // Causes a segment fault *b[2] = b[1]; // This almost seems like it would work but the compiler throws an error. 

Entonces, ¿hay alguna manera de cambiar los valores dentro de las cadenas en lugar de las direcciones del puntero?

Gracias

EDITAR:

Gracias a todos por sus respuestas. Tiene más sentido ahora. Tiene sentido especialmente por qué a veces funcionaba bien y otras veces no funcionaba. Porque a veces pasaba un puntero de char y otras veces una matriz de caracteres (la matriz de caracteres funcionaba bien).

Cuando escribe una “cadena” en su código fuente, se escribe directamente en el ejecutable porque ese valor debe conocerse en tiempo de comstackción (hay herramientas disponibles para separar el software y encontrar todas las cadenas de texto sin formato en ellas). Cuando escribe char *a = "This is a string" , la ubicación de “Esto es una cadena” está en el ejecutable, y la ubicación a apunta, está en el ejecutable. Los datos en la imagen ejecutable son de solo lectura.

Lo que debe hacer (como lo han señalado las otras respuestas) es crear esa memoria en una ubicación que no sea de solo lectura: en el montón o en el marco de la stack. Si declara una matriz local, se crea espacio en la stack para cada elemento de esa matriz, y la cadena literal (que se almacena en el ejecutable) se copia a ese espacio en la stack.

 char a[] = "This is a string"; 

también puede copiar esos datos manualmente asignando algo de memoria en el montón, y luego usando strcpy() para copiar un literal de cadena en ese espacio.

 char *a = malloc(256); strcpy(a, "This is a string"); 

Siempre que asigne espacio utilizando malloc() recuerde llamar a free() cuando haya terminado con él (léase: pérdida de memoria).

Básicamente, debe hacer un seguimiento de dónde están sus datos. Cada vez que escriba una cadena en su fuente, esa cadena es de solo lectura (de lo contrario, podría cambiar el comportamiento del ejecutable; imagínese si escribió char *a = "hello"; y luego cambió a[0] a 'c' . Luego, en otro lugar escribió printf("hello"); Si se le permitiera cambiar el primer carácter de "hello" , y su comstackdor solo lo almacenara una vez (debería), printf("hello"); cello !)

No, no puede modificarlo, ya que la cadena se puede almacenar en la memoria de solo lectura. Si desea modificarlo, puede usar una matriz, por ejemplo,

 char a[] = "This is a string"; 

O alternativamente, puede asignar memoria utilizando malloc, por ejemplo

 char *a = malloc(100); strcpy(a, "This is a string"); free(a); // deallocate memory once you've done 

Mucha gente se confunde con la diferencia entre char * y char [] junto con literales de cadena en C. Cuando escribes:

 char *foo = "hello world"; 

… en realidad estás apuntando a un bloque constante de memoria (de hecho, lo que el comstackdor hace con “hello world” en este caso depende de la implementación).

Usar char [] en su lugar le dice al comstackdor que desea crear una matriz y llenarla con los contenidos, “hello world”. foo es el puntero al primer índice de la matriz de caracteres. Ambos son punteros de char, pero solo char [] señalará un bloque de memoria asignado localmente y mutable.

La memoria para a & b no es asignada por usted. El comstackdor puede elegir libremente una ubicación de memoria de solo lectura para almacenar los caracteres. Por lo tanto, si intenta cambiarlo, puede provocar un error seg. Así que te sugiero que crees una matriz de personajes tú mismo. Algo como: char a[10]; strcpy(a, "Hello"); char a[10]; strcpy(a, "Hello");

Parece que tu pregunta ha sido respondida, pero ahora te preguntarás por qué char * a = “String” está almacenada en la memoria de solo lectura. Bueno, en realidad no está definido por el estándar c99, pero la mayoría de los comstackdores lo eligen de esta manera para instancias como:

 printf("Hello, World\n"); 

c99 estándar (pdf) [página 130, sección 6.7.8]:

La declaracion:

 char s[] = "abc", t[3] = "abc"; 

define objetos de matriz char “simples” s y t cuyos elementos se inicializan con literales de cadena de caracteres. Esta statement es idéntica a char

 s[] = { 'a', 'b', 'c', '\0' }, t[] = { 'a', 'b', 'c' }; 

El contenido de las matrices es modificable. Por otro lado, la statement

 char *p = "abc"; 

define p con el tipo “puntero a char” y lo inicializa para apuntar a un objeto con el tipo “array of char” con longitud 4 cuyos elementos se inicializan con un literal de cadena de caracteres. Si se intenta utilizar p para modificar el contenido de la matriz, el comportamiento no está definido.

También strdup usar strdup :

  The strdup() function returns a pointer to a new string which is a duplicate of the string s. Memory for the new string is obtained with malloc(3), and can be freed with free(3). 

Para tu ejemplo:

 char *a = strdup("stack overflow"); 

Todas son buenas respuestas que explican por qué no se pueden modificar los literales de cadena porque están ubicados en la memoria de solo lectura. Sin embargo, cuando se trata de empujar, hay una manera de hacer esto. Mira este ejemplo:

 #include  #include  #include  #include  #include  #include  int take_me_back_to_DOS_times(const void *ptr, size_t len); int main() { const *data = "Bender is always sober."; printf("Before: %s\n", data); if (take_me_back_to_DOS_times(data, sizeof(data)) != 0) perror("Time machine appears to be broken!"); memcpy((char *)data + 17, "drunk!", 6); printf("After: %s\n", data); return 0; } int take_me_back_to_DOS_times(const void *ptr, size_t len) { int pagesize; unsigned long long pg_off; void *page; pagesize = sysconf(_SC_PAGE_SIZE); if (pagesize < 0) return -1; pg_off = (unsigned long long)ptr % (unsigned long long)pagesize; page = ((char *)ptr - pg_off); if (mprotect(page, len + pg_off, PROT_READ | PROT_WRITE | PROT_EXEC) == -1) return -1; return 0; } 

He escrito esto como parte de mis pensamientos más profundos sobre la corrección de const , que puede encontrar interesante (espero :)).

Espero eso ayude. ¡Buena suerte!

Debe copiar la cadena en otro buffer de memoria no de solo lectura y modificarlo allí. Utilice strncpy () para copiar la cadena, strlen () para detectar la longitud de la cadena, malloc () y free () para asignar dinámicamente un buffer para la nueva cadena.

Por ejemplo (C ++ como pseudocódigo):

 int stringLength = strlen( sourceString ); char* newBuffer = malloc( stringLength + 1 ); // you should check if newBuffer is 0 here to test for memory allocaton failure - omitted strncpy( newBuffer, sourceString, stringLength ); newBuffer[stringLength] = 0; // you can now modify the contents of newBuffer freely free( newBuffer ); newBuffer = 0; 
 char *a = "stack overflow"; char *b = "new string, it's real"; int d = strlen(a); b = malloc(d * sizeof(char)); b = strcpy(b,a); printf("%s %s\n", a, b);