recortar - ¿Por qué este código para modificar una cadena no funciona?
string c# ejemplos (5)
Con cadenas de estilo c, ¿cómo se asigna un carácter a una dirección de memoria a la que apunta un puntero de carácter? Por ejemplo, en el ejemplo siguiente, quiero cambiar num a "123456", así que intenté establecer p en el dígito donde está ubicado ''0'' e intento sobrescribirlo con ''4''. Gracias.
#include <stdio.h>
#include <stdlib.h>
int main()
{
char* num = (char*)malloc(100);
char* p = num;
num = "123056";
p = p+3; //set pointer to where ''4'' should be
p = ''4'';
printf("%s/n", num );
return 0;
}
Además del problema * p que otros han señalado, también tiene problemas de uso de memoria. Tienes un buffer de 100 bytes, con contenido desconocido. Tiene otro búfer de 7 bytes, que contiene la cadena "123056" y un terminador nulo. Estás haciendo esto:
- num está configurado para apuntar al buffer de 100 bytes
- p está configurado para señalar num; es decir, apunta al búfer de 100 bytes
- restablece num para señalar el búfer de 7 bytes; p todavía apunta al buffer de 100 bytes
- Usas p para modificar el buffer de 100 bytes
- luego usas num para imprimir el buffer de 7 bytes
Por lo tanto, no está imprimiendo el mismo búfer que está modificando.
Bueno, sabes que p es un tipo de puntero. Almacena la dirección de char ''0''. Si asigna p el valor de ''4''. Tomará ''4'' como la dirección. Sin embargo, la dirección ''4'' es ilegal. Puede usar el operador ''*'' para obtener el valor de la dirección almacenada en p almacenada.
Ese código no funcionará, simplemente porque la línea:
num = "123056";
cambia num
a punto lejos de la memoria asignada ( p
sigue apuntando a esa memoria para que ya no sean la misma ubicación) a lo que probablemente sea la memoria de solo lectura. No está permitido cambiar la memoria que pertenece a los literales de cadena, es un comportamiento indefinido.
Necesitas lo siguiente:
#include <stdio.h>
#include <stdlib.h>
int main (void) {
char *num = malloc (100); // do not cast malloc return value.
char *p = num;
strcpy (num, "123056"); // populate existing block with string.
p = p + 3; // set pointer to where ''0'' is.
*p = ''4''; // and change it to ''4''.
printf ("%s/n", num ); // output it.
return 0;
}
Primero que nada, cuando lo haces:
num = "123056";
No está copiando la cadena "123056" al área de pila asignada por malloc()
. En C, al asignar un puntero char *
un valor literal de cadena es equivalente a establecerlo como una constante, es decir, idéntica a:
char str[] = "123056";
Entonces, lo que acaba de lograr es que haya abandonado su única referencia al área de malloc()
100 bytes asignada por malloc()
, que es la razón por la cual su código subsiguiente no imprime el valor correcto; '' p
'' todavía apunta al área de pila asignada por malloc()
(ya que num
apunta a ella en el momento de la asignación), pero num
ya no lo hace.
Supongo que tu intención era copiar la cadena "123056" en esa área del montón. He aquí cómo hacerlo:
strcpy(num, "123056");
Aunque, esta es una mejor práctica por una variedad de razones:
strncpy(num, "123056", 100 - 1); /* leave room for /0 (null) terminator */
Si acabas de hacer:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
char *num = malloc(100);
char *p = num;
strncpy(num, "123056", 100 - 1);
p = p + 3;
*p = ''4'';
printf("%s/n", num);
return 0;
}
Habría obtenido el resultado correcto:
123456
Puedes contratar esta operación:
p = p + 3;
*p = ''4'';
... y evitar iterar el puntero, haciendo referencia de la siguiente manera:
*(p + 3) = ''4'';
Algunas otras notas:
Aunque es una práctica estilística común, el lanzamiento del valor de retorno de
malloc()
a(char *)
es innecesario. La conversión y alineación del tipovoid *
está garantizada por el lenguaje C.SIEMPRE verifique el valor de retorno de
malloc()
. Será NULO si la asignación del montón falló (es decir, se ha agotado la memoria), y en ese momento su programa debería salir.Dependiendo de la implementación, el área de memoria asignada por
malloc()
puede contener basura obsoleta en ciertas situaciones. Siempre es una buena idea ponerlo en cero después de la asignación:memset(num, 0, 100);
¡Nunca olvides
free()
tu montón! En este caso, el programa se cerrará y el sistema operativo limpiará su basura, pero si no adquiere el hábito, tendrá pérdidas de memoria en muy poco tiempo.
Entonces, aquí está la versión de "mejores prácticas":
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
char *num, *p;
/*
* Don''t take 1-byte chars for granted - good habit to get into.
*/
num = malloc(sizeof(char) * 100);
if(num == NULL)
exit(1);
memset(num, 0, sizeof(char) * 100);
p = num;
strncpy(num, "123056", 100 - 1);
*(p + 3) = ''4'';
printf("%s/n", num);
free(num);
return 0;
}
Solo use *p = ''4'';
...!