Foros del Web

Foros del Web (http://www.forosdelweb.com/)
-   C/C++ (http://www.forosdelweb.com/f96/)
-   -   El maravilloso mundo de los punteros... (http://www.forosdelweb.com/f96/maravilloso-mundo-punteros-396016/)

nILaRT 23/05/2006 08:16

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

Instru 23/05/2006 10:15

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

MaxExtreme 23/05/2006 15:02

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.

Nivel7 23/05/2006 19:12

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.

Instru 24/05/2006 09:30

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

MaxExtreme 24/05/2006 12:58

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.

Nivel7 24/05/2006 14:32

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.

Instru 24/05/2006 21:23

Gracias por la aclaracion.

Saludos

MaxExtreme 25/05/2006 07:32

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.

yournightmare86 25/05/2006 11:15

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?

Nivel7 25/05/2006 11:56

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.

yournightmare86 25/05/2006 13:15

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).

Nivel7 25/05/2006 17:24

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.

yournightmare86 26/05/2006 10:13

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.

MaxExtreme 29/05/2006 06:38

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.


La zona horaria es GMT -6. Ahora son las 18:07.

Desarrollado por vBulletin® Versión 3.8.7
Derechos de Autor ©2000 - 2014, Jelsoft Enterprises Ltd.

SEO by vBSEO 3.3.2