[C con Clase] Pregunta tonta de char *algo.
Programante
programante en gmail.com
Vie Mar 16 20:18:37 CET 2007
dani escribió:
> Buenas a todos,
> mirad quiero hacer algo que parece simple pero que no me sale y n o encuentro en ningún sitio. Se trata de que tengo en un programa
>
> char *file_name;
> file_name="hola_0.000_.dat";
>
Esto es correcto (siento contradecirte, Joaquín). Estás haciendo apuntar
el puntero a una cadena estática.
> y lo que quiero es cambiar los 0s de file_name por otros números y no se como. He intentado las siguientes opciones para cambiar el primer 0 por un 1,
>
> name[5]='1';
>
Esta es la opción correcta, o alternativamente *(name+5)='1'; Las otras
colocan el caracter con nº ascii 1, que es distinto del '1' (caracter
ascii 49). (pero pon file_name, no name)
> pero siempre ocurre un error y el programa se cierra aunque el compilador no da errores. En principio creo que son equivalentes pero no funciona ninguna.
> Gracias a todos por las ayudas recibidas y un saludo.
> Dani.
>
> PS: No vale cambiar char *file_name por char file_name[16] pq necesito que sea un puntero.
Ya apuntaron la solución, pero no el motivo.
Cuando se inicializa una variable a un valor, el compilador almacena
previamente ese valor en la memoria y luego lo copia a la variable. Con
números funciona siempre sin problemas. Cuando se trata de una cadena,
estás apuntando el lugar donde está la cadena. Sería equivalente a
char dato_interno[] = "hola_0.000_.dat"; //Colocado en algún sitio por
el compilador
....
file_name=dato_interno;
Ahora, ¿dónde está dato_interno? Donde le parezca al compilador. Desde
su punto de vista es una constante, así que puede perfectamente situarlo
en memoria ROM. En ese caso al hacer file_name[5]='1'; estás intentando
modificar un dato de sólo lectura. Error. Ese código es incorrecto y
fallará en un microcontrolador, por ejemplo.
En los PC ese código incorrecto se ha venido usando desde hace años.
Como funcionaba...
Recientemente los procesadores han incorporado nuevas características de
protección de memoria. Como consecuencia, es muy probable que en un
ordenador nuevo dato_interno esté en una sección marcada como sólo
lectura. Cuando intentas escribir en él, se te produce un fallo.
El código es correcto, por eso el compilador no da ningún error. Pero lo
que intentas hacer no está permitido y falla al ejecutarse.
La solución pasa por utilizar memoria dinámica. Ya han mencionado usar
news grandes, etc. Yo usaría file_name = strdup("hola_0.000_.dat"); Esto
nos da un puntero con una copia de la cadena que le pasamos.
Ahora file_name[5] = '1'; ya funciona.
Para convertir todos los 0 en 1, puedes usar por ejemplo:
for (i=0; file_name[i]; i++)
if (file_name[i] = '0') file_name[i] = '1';
Más información sobre la lista de distribución Cconclase