2

Buen día a todos! Esta pregunta es una continuación del siguiente enlace: Leer string y floats de un archivo para calcular promedio ponderado en C++

Para lograr lo propuse en la pregunta decidí implementar una opción y consiste en lo siguiente: Cada vez que el usuario abra el programa, éste va a buscar si existe el archivo "Nombres", el cual debería existir si el usuario usó el programa antes por lo que de encontrarlo va a preguntar al usuario si quiere usar la misma información o si prefiere empezar de cero. Para esto, creé una función 'Bool' fuera de 'main' que verifique dicha existencia y que retorne un valor 'true' o 'false' si encuentra el archivo o no, respectivamente. El problema es que cuando devuelvo el valor obtenido por mi función 'bool', el IDE me arroja un error: '"undefined reference to `existencia()"' El código es el siguiente:

 bool existencia (const string& Nombres){
 std::ifstream ifile(Nombres.c_str());
 return (bool) ifile;
 }

 int main(){
 //Nombre del programa
 cout << "\t\t Promedio Ponderado\n";

 int x;
 bool existencia();
 //Prueba de la existencia de archivos
 if  (true == existencia()){
do {
    system("cls");
    cout << "Escoja la opción 1 o 2:" << endl;
    cout << "1: Usar los nombres y creditos guardados" << endl;
    cout << "2: Usar toda la informacion anterior e imprimir el resultado" << endl;
    cin >> x;
} while (x!=1 || x!=2);
 }

 if(x==1){

cout << "Programa en construccion";
 } else{
cout << "Aquí va el programa que publiqué en la pregunta original";
 }
 return 0;
 }

1 Answers1

1
bool existencia();

Lo anterior se conoce como declaration forward o simplemente como declaracion de función. Sirve para que el compilador sepa que existe una función con una firma determinada pero sin proporcionar el código de dicha función... Esta característica permite crear archivos de cabecera que agilizan enormemente los procesos de compilación y permiten eliminar dependencias circulares.

Bien, al usar un declaration forward hay que tener en cuenta que la función debe estar declarada en el mismo ámbito que la correspondiente implementación ya que si no el compilador va a ser incapaz de relacionar ambos usos:

namespace test
{
  void func();
}

int main()
{

  //func(); // error... funcion no declarada
  test::func(); // ok
}

void func()
{
  std::cout << 1;
}

namespace test
{
  void func()
  {
    std::cout << 2;
  }
}

En tu caso el uso incorrecto se encuentra aquí:

int main(){
 //Nombre del programa
 cout << "\t\t Promedio Ponderado\n";

 int x;
 bool existencia(); // <<---

Esa declaración debería encontrarse fuera del main. Como la declaración debe encontrarse antes de empezar la función main():

bool existencia();

int main()
{
  // ...
}

bool existencia()
{
  // ...
}
eferion
  • 49,291
  • 5
  • 30
  • 72
  • Gracias por la respuesta! Mi pregunta es, cómo sabe la función `main` que la función `existencia` debe ser ejecutada en la posición en la que puse inicialmente dicha función? – Germán Diego Guisasola Plejo Jun 05 '17 at 10:44
  • @GermánDiegoGuisasolaPlejo no he entendido tu pregunta, lo siento – eferion Jun 05 '17 at 10:49
  • Es decir, la función existencia está fuera de main pero yo quiero que se ejecute al iniciar el programa para comprobar si existe el archivo o no, lo que hice fue ver un vídeo de forward declaration y pude entender mejor por lo que el código queda así: `bool existencia(); int main(){ bool Ver_existencia; Ver_existencia = existencia(); //Prueba de la existencia de archivos } bool existencia (const string& Nombres){ std::ifstream ifile(Nombres.c_str()); return (bool) ifile; } ` Pero cuando ejecuto el programa me dice undefined reference to existencia() – Germán Diego Guisasola Plejo Jun 05 '17 at 10:56
  • @GermánDiegoGuisasolaPlejo *forward declaration* sirve para que el compilador sea consciente de que en algun lugar del código existe esa función... realizar la llamada efectiva a esa función es tarea del enlazador o *linker*... por eso para enlazar hay que pasar todos los `.o` que conforman el proyecto... es en esta parte en la que se comprueba si la función realmente existe... si no se encuentra entonces se produce un error en tiempo de enlazado... te toca implementar la función o adjuntar el fichero objeto que contiene su implementación – eferion Jun 05 '17 at 10:57
  • @GermánDiegoGuisasolaPlejo en el ejemplo que has puesto en el comentario puedes ver que `bool existencia()` no es lo mismo que `bool existencia(const string&)` (el nombre de los parametros es irrelevante aqui)... el error te está diciendo que el enlazador no encuentra una función llamada *existencia* que no tenga argumentos y que devuelva un booleano – eferion Jun 05 '17 at 11:00
  • Entiendo eso pero estoy perdido con el tema de hacerlo funcionar, es decir, no sé qué debo cambiar o aumentar >.< Sé que debe ser algo muy sencillo pero de veras, no sé qué debo corregir. Si los parámetros son irrelevantes, por qué `bool existencia()` y `bool existencia(const string&)` no son lo mismo? Y sí tengo bien lo que va dentro del main? Gracias por tu paciencia! – Germán Diego Guisasola Plejo Jun 05 '17 at 11:06
  • 1
    @GermánDiegoGuisasolaPlejo Lo irrelevante es el **nombre** de los argumentos. Para que te funcione tu ejemplo, la *forward declaration* debería ser `bool existencia(const string&);` y la llamada a la función dentro del `main` también debería cambiar: `Ver_existencia = existencia(/*aqui falta una cadena de texto*/);` – eferion Jun 05 '17 at 11:07
  • Me funcionó! Abrí el programa y como no lo había usado antes, no encontró ningún archivo y fue directamente al `main`. Luego, lo volví a abrir y como ya encontró el archivo, me preguntó qué quería hacer; me falta pulir el programa ya que cuando me preguntó qué quería hacer y escogí "usar la info anterior" no hizo nada ya que aún no he creado la función que me permita leer la información de los archivos. Primero voy a cambiar un poco el programa, en lugar de usar un `array` para cada variable, usaré `push_back()` y luego crearé la función que me permite hacer lo anterior. Muchas gracias!!! – Germán Diego Guisasola Plejo Jun 05 '17 at 11:15
  • 1
    @GermánDiegoGuisasolaPlejo me alegro. Si la respuesta soluciona tu problema no olvides marcarla como solución. Así ayudas a futuros visitantes. – eferion Jun 05 '17 at 11:17