[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