Foros del Web » Programación para mayores de 30 ;) » C/C++ »

El maravilloso mundo de los punteros...

Estas en el tema de El maravilloso mundo de los punteros... en el foro de C/C++ en Foros del Web. Primero saludar a todos, soy nuevo en el foro, pero supongo que a partir de ahora me vereis a menudo =) vereis, tengo un problema ...
  #1 (permalink)  
Antiguo 23/05/2006, 08:16
 
Fecha de Ingreso: mayo-2006
Mensajes: 1
Antigüedad: 17 años, 11 meses
Puntos: 0
El maravilloso mundo de los punteros...

Primero saludar a todos, soy nuevo en el foro, pero supongo que a partir de ahora me vereis a menudo =) vereis, tengo un problema con un puntero a cadena, el caso es que quiero recibir por pantalla el nombre de un archivo que luego abrire en otra funcion.

Pongo una parte del codigo para que veais lo que he hecho:

Cita:
//PROTOTIPOS DE FUNCIONES DE GUARDAR Y CARGAR
char* Solicitar_Fichero();
void Guardar_Vehiculo_Optimo(pVehiculo pCabezaVehiculoOptimo, char* Nombre_Fichero);

//PROGRAMA PRINCIPAL
void main(){
char* Nombre_Fichero; //declaramos puntero a dato tipo char

Nombre_Fichero = Solicitar_Fichero(); //llama a la funcion solicitar fichero
Guardar_Vehiculo_Optimo(pCabezaVehiculoOptimo,Nomb re_Fichero);
}

//Funcion solicitar Fichero
char* Solicitar_Fichero()
{
char Nombre[20]; //declaramos variable tipo char
char* Nombre_Fichero; //declaramos puntero a tipo char
Nombre_Fichero=Nombre; //apuntamos el puntero a la variable Nombre
clrscr();
gotoxy(6,10);
textcolor(14);
cprintf("Introduzca nombre del archivo: ");
scanf("%s", Nombre); //escaneamos el nombre y lo guardamos en la variable Nombre
return (Nombre_Fichero); //devolvemos el puntero a la variable nombre
}

//Funcion Guardar Vehiculo Optimo
void Guardar_Vehiculo_Optimo(pVehiculo pCabezaVehiculoOptimo, char* fichero)
{
FILE* pFichero;
char nombre_fichero[100];

strcpy(nombre_fichero,fichero);
strcat(nombre_fichero,".opt");

pFichero = fopen(nombre_fichero,"ab");
if(pFichero == NULL)
{
cprintf("El Fichero no se ha podido crear!",10,25);
while(!kbhit());
}
}
El caso es que salta el error de que no se ha podido crear el fichero, y tiene toda la pinta de que al declarar la variable Nombre dentro de la funcion Solicitar_Fichero, una vez que termina esta funcion esa variable desaparece y el puntero devuelto no sirve para nada =P

Asi que no se como hacerlo, quizas creando una variable global para el Nombre? cualquier idea seria de ayuda

Un saludo,
Gracias
  #2 (permalink)  
Antiguo 23/05/2006, 10:15
Avatar de Instru  
Fecha de Ingreso: noviembre-2002
Ubicación: Mexico
Mensajes: 2.751
Antigüedad: 21 años, 5 meses
Puntos: 52
Pues tu suposicion es correcta.
Lo que podrias hacer para que el valor no desaparesca es alojar memoria a traves del puntero. Luego compiar la cadena que quieres en ese nuevo espacio y finalmente devolver el puntero, asi no se destruira la informacion.

Espero que te sirva, sino aqui andamos.

Saludos
  #3 (permalink)  
Antiguo 23/05/2006, 15:02
 
Fecha de Ingreso: abril-2005
Mensajes: 3.083
Antigüedad: 19 años
Puntos: 17
O otra manera para que no juegues con punteros si es que no estás acostumbrado a ellos, es declarar la variable estática:

Código:
char * Solicitar_Fichero()
{
    static char Nombre[20];
    clrscr();
    gotoxy(6,10);
    textcolor(14);
    cprintf("Introduzca nombre del archivo: ");
    scanf("%s", Nombre);
    return Nombre;
}
Por cierto, con declarar "char Nombre[20];" es suficiente, lo de "char * Nombre_Fichero" es redundante. Nombre ya se comporta como un puntero.

Tampoco te recomiendo usar la librería conio.h, no es C estándar, sólo existe en Turbo C.

Por otra parte, los () del return son innecesarios.

Ahora bien, si usas lo que te he escrito arriba, cuidado, porque deberás hacer una copia de la cadena que te devuelvan. Si llamas de nuevo Solicitar_Fichero perderás la anterior. Es decir:

Código:
char * uno = Solicitar_Fichero();
char * dos = Solicitar_Fichero();
Eso resulta que "uno" y "dos" contienen lo mismo, en concreto, lo que escribiste en el scanf() de la segunda llamada.
  #4 (permalink)  
Antiguo 23/05/2006, 19:12
 
Fecha de Ingreso: abril-2006
Ubicación: Acapulco Gro. México
Mensajes: 483
Antigüedad: 18 años
Puntos: 2
Las soluciones que te an dado son buenas, pero la verdad poco recomendables, el uso de variables glonales no es una practica muy recomendada, el uso de varables static tienen sus incomvenientes, es mejor usar el estilo delas funciones de la libreria de C, es decir siempre que quieras capturar datos en una cadena, tienes que pasar esta como parametro.

char* Solicitar_Fichero(char Nombre[])
{
clrscr();
gotoxy(6,10);
textcolor(14);
cprintf("Introduzca nombre del archivo: ");
scanf("%s", Nombre); //escaneamos el nombre y lo guardamos en la variable Nombre
return Nombre;
}


de esta forma evitamos crear o reservar mas memoria para cadenas temporales o lidiar con las estaticas.
crear una cadena dinamica dentro de una funcion delega responsabilidades al receptor. (generalmente causa de errores relacionados con la memoria).

Saludos.

Última edición por Nivel7; 23/05/2006 a las 19:42
  #5 (permalink)  
Antiguo 24/05/2006, 09:30
Avatar de Instru  
Fecha de Ingreso: noviembre-2002
Ubicación: Mexico
Mensajes: 2.751
Antigüedad: 21 años, 5 meses
Puntos: 52
MaxExtreme tiene mucha razon. Como trabajas con punteros, la funcion te estaria regresando punteros a la misma variable. Lo ideal seria lo que te dice Nivel7, solicitar esa informacion fuera de la funcion, porque eso de intentar usar variables locales como globales viola, por asi decirlo, la "encapsulacion"(no se como se llama en C) de C.

Saludos
  #6 (permalink)  
Antiguo 24/05/2006, 12:58
 
Fecha de Ingreso: abril-2005
Mensajes: 3.083
Antigüedad: 19 años
Puntos: 17
Cita:
Iniciado por Nivel7
Las soluciones que te an dado son buenas, pero la verdad poco recomendables, el uso de variables glonales no es una practica muy recomendada, el uso de varables static tienen sus incomvenientes, es mejor usar el estilo delas funciones de la libreria de C, es decir siempre que quieras capturar datos en una cadena, tienes que pasar esta como parametro.
Cierto, pero el pretende usarlo como función auxiliar.

Más que una función, es casi un procedimiento. Lo único que hace es repetirse preguntando qué archivo. Por tanto, usado con cabeza, es mejor con una variable estática, para poder hacer cosas como:

fopen(SolicitaFichero(),"r");

Evidentemente, la función SolicitaFichero deberá incluir código contra errores, confirmación de que lo que ha pedido es una ruta de verdad, etc.
  #7 (permalink)  
Antiguo 24/05/2006, 14:32
 
Fecha de Ingreso: abril-2006
Ubicación: Acapulco Gro. México
Mensajes: 483
Antigüedad: 18 años
Puntos: 2
Si esa fuese la intencion, yo haria:

FILE * AbrirFichero(const char tipo[])
{
char nombre_file[40];
printf("Introdusca el nombre del Archivo: ");
scanf("%s", nombre_file);
return fopen(nombre_file, tipo);
}

esto evita el uso de variables static, que ademas creo en C, no funcionan como en C++(Pero no estoy seguro).

Instru, creo que se le llamaria Efecto lateral..

Una de la reglas de la programacion estructurada es:
si la subrrutina retorna valores es una funcion, de lo contrario es un procedimiento, a los procedimientos se les permiten los efectos laterales.
(Eso creo ...jeje).

Saludos.
  #8 (permalink)  
Antiguo 24/05/2006, 21:23
Avatar de Instru  
Fecha de Ingreso: noviembre-2002
Ubicación: Mexico
Mensajes: 2.751
Antigüedad: 21 años, 5 meses
Puntos: 52
Gracias por la aclaracion.

Saludos
  #9 (permalink)  
Antiguo 25/05/2006, 07:32
 
Fecha de Ingreso: abril-2005
Mensajes: 3.083
Antigüedad: 19 años
Puntos: 17
Cita:
Iniciado por Nivel7
esto evita el uso de variables static, que ademas creo en C, no funcionan como en C++(Pero no estoy seguro).
Pues, que yo sepa, son iguales. Una variable "static" no es más que una variable que existe siempre, como una global, pero dentro de una función.
  #10 (permalink)  
Antiguo 25/05/2006, 11:15
Avatar de yournightmare86  
Fecha de Ingreso: abril-2006
Ubicación: Madrid
Mensajes: 875
Antigüedad: 18 años
Puntos: 9
Una variable static no es aquella variable a la que se le otorga un valor de "inicio" podríamos llamarlo para que cada vez que una función llame a esa variable el valor de comienzo sea el mismo?
  #11 (permalink)  
Antiguo 25/05/2006, 11:56
 
Fecha de Ingreso: abril-2006
Ubicación: Acapulco Gro. México
Mensajes: 483
Antigüedad: 18 años
Puntos: 2
Constante.

ES una constante.

La diferencia:

Una variable static, es una variable que se crea antes de la funcion main, su vida es durante todo el programa, pero su visibilidad es solo en su ambito de declaracion..
por tanto si dentro de una funcion le asignas un valor este se conservara, en las proximas llamadas, pero su valor lo puedes modificar.

una constante es una variable que puede ser tanto global como, local pero esta no puede ser modificada.

No esta ba seguro si en C y C++ las variables static se comportaban igual pero ya veo que si.

Saludos.
  #12 (permalink)  
Antiguo 25/05/2006, 13:15
Avatar de yournightmare86  
Fecha de Ingreso: abril-2006
Ubicación: Madrid
Mensajes: 875
Antigüedad: 18 años
Puntos: 9
No estoy seguro pero creo haber visto en algún programa dentro del main la siguiente línea. static int i=0; y según me explicaron sirve para que siempre que se pase esa variable su valor inicial sea el mismo(0 en este caso).
  #13 (permalink)  
Antiguo 25/05/2006, 17:24
 
Fecha de Ingreso: abril-2006
Ubicación: Acapulco Gro. México
Mensajes: 483
Antigüedad: 18 años
Puntos: 2
No lo creo

No creo que tenga sentido usar una variable static, dentro de main.

ya que es muy raro llamar desde otra funcion a main, solo que el SO lo haga, o desde otra aplicacion, pero dudo que de una ejecucion a otra el valor de la variable static se conserve.

tu en realidad te refieres a una constante.

const int i = 0;

i siempre sera i y no podra modificarse.

static int i = 0;

i si se puede modificar.

static tienen dos funciones, como especificador de ambito y de almacenamiento(vida).

En ambito:
static es lo contrario a extern.

En almacenamiento:
static es lo contrario a auto.

en realidad el funcionamiento de static como especificador de almacenamiento, es muy similar auna variable global.

Ejemplo:
int acum = 0;

int acumulado(int val)
{
return acum += val;
}

int main()
{

for(int i = 1; i <= 10; i++)
cout << acumulado(i) << endl;

return 0;
}

este pequeño programa te mostraria la suma de los 10 primeros digitos.

si la funcion fuera esta:
int acumulado(int val)
{
int acum = 0;
return acum += val;
}

la funcion retornaria solo el valor de val + 0;
para solucionar el problema sin usar variables globales hariamos:

int acumulado(int val)
{
static int acum = 0;
return acum += val;
}

acum se crea antes de main y se destruye una vez terminada main, por tanto iría conservando el valor de la suma.

si intentaras hacer esto:

int acumulado(int val)
{
const int acum = 0;
return acum += val;
}

no te compilaria, o te daria error en la ejecucion.

Saludos.
  #14 (permalink)  
Antiguo 26/05/2006, 10:13
Avatar de yournightmare86  
Fecha de Ingreso: abril-2006
Ubicación: Madrid
Mensajes: 875
Antigüedad: 18 años
Puntos: 9
Bien, una vez leído ésto me alegro muchísimo de la decisión que tomé hace mes y medio. Dejar de atender a mi profesora de programación y empezar a mirarme las cosas y aprender por mi cuenta. Creo que aprendí casi más en un mes en éste foro que en 7 meses con mi profesora xD. Muchas gracias por la ayuda.
Un saludo.
  #15 (permalink)  
Antiguo 29/05/2006, 06:38
 
Fecha de Ingreso: abril-2005
Mensajes: 3.083
Antigüedad: 19 años
Puntos: 17
Cita:
Iniciado por yournightmare86
Bien, una vez leído ésto me alegro muchísimo de la decisión que tomé hace mes y medio. Dejar de atender a mi profesora de programación y empezar a mirarme las cosas y aprender por mi cuenta. Creo que aprendí casi más en un mes en éste foro que en 7 meses con mi profesora xD. Muchas gracias por la ayuda.
Un saludo.
Sí, en informática se aprende mucho más y mejor como autodidacta.
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 12:09.