Functions in c ++

0

Given a function to read a file, how can I make it so that when calling the function in the main program, it closes when the file does not exist?

At the moment I have done this:

int leer_correo (int cart[], int certif[], int paq[]){
    FILE *fe;
    int i, anyo, total[ANYOS];
    if((fe=fopen("correo.txt", "r"))==NULL){
        printf("Error\n");
        return -1;
    }

    for(i=0 ; i<ANYOS ; i++)
        fscanf(fe, "%d%d%d%d", &anyo, &cart[i], &certif[i], &paq[i]);
    total[anyo-1900]=cart[anyo-1900]+certif[anyo-1900]+paq[anyo-1900];
    return 0;
}

void main(){
    int opc, cart[ANYOS], certif[ANYOS], paq[ANYOS];    
    leer_correo(); // Llamar a la función leer correo
    // Si hay error: terminar el programa
}
    
asked by eacs98 16.11.2016 в 11:49
source

3 answers

1

You should clarify if you are using C or C ++, the label says C ++ but your code is ANSI C.

You can use the exit function to finalize your process, indicating a status code that will help you identify the reason.

#define NO_CORREO         -1
#define RESULTADO_NOFILE   1

void main() // Cambia el tipo de 
{
    int opc, cart[ANYOS], certif[ANYOS], paq[ANYOS];    
    if( leer_correo() == NO_CORREO ) // Llamar a la función leer correo
        exit(RESULTADO_NOFILE);      // Salida con código 1

    // Haz el resto de cosas que tengas que hacer.
}
    
answered by 16.11.2016 в 12:20
1

You have several ways to report an error:

Use an error code

This can be done with #define or with enum . My personal preference would be the second option for several reasons:

  • Those listed generate a different identification for each element automatically, reduces the risk of having repeated identifiers
  • As of C ++ 11 (see third example), a strong typing can be provided to those listed. The great advantage of activating this feature is that we provide a more robust code.

Example with #define :

#define OK 0
#define FILE_NOT_FOUND 1
#define ANOTHER 2
// ...

int TestFunc()
{
  return FILE_NOT_FOUND;
}

int main()
{
  switch( TestFunc() )
  {
    case OK:
      std::cout << "Ok\n";
      break;

    case FILE_NOT_FOUND:
      std::cout << "Fichero no encontrado\n";
      break;

    // ...
  }
}

Example with enum :

enum TestFuncReturn
{
  OK,
  FILE_NOT_FOUND,
  ANOTHER,
  // ...
};

TestFuncReturn TestFunc()
{
  return FILE_NOT_FOUND;
}

int main()
{
  switch( TestFunc() )
  {
    case OK:
      std::cout << "Ok\n";
      break;

    case FILE_NOT_FOUND:
      std::cout << "Fichero no encontrado\n";
      break;

    // ...
  }
}

Example with enum in C ++ 11:

enum class TestFuncReturn
{
  OK,
  FILE_NOT_FOUND,
  ANOTHER,
  // ...
};

TestFuncReturn TestFunc()
{
  return TestFuncReturn::FILE_NOT_FOUND;
}

int main()
{
  switch( TestFunc() )
  {
    case TestFuncReturn::OK:
      std::cout << "Ok\n";
      break;

    case TestFuncReturn::FILE_NOT_FOUND:
      std::cout << "Fichero no encontrado\n";
      break;

    // ...
  }
}

Exceptions:

Using error codes has several drawbacks:

  • occupy the return of the function, so to return additional information it is necessary to resort to artifices as parameters by reference or to use std::pair or std::tuple .
  • Many times the function that receives the error message can not do anything by itself to recover the situation, it is up to it to propagate the error upwards and this causes that special care must be taken so that different error messages do not overlap .
  • Returning an error code sometimes seems insufficient to, for example, inform the user about the problem (What file has failed ?, Why?, Is there anything else to be taken into account?) .

To meet these deficiencies there are exceptions. Exceptions can (and should) be objects, which allows legacy, polymorphism and encapsulation characteristics to be used to provide all the information necessary to recover from an error.

Example C ++ 98:

class FileNotFoundException : public std::exception
{
  public:

    FileNotFoundException(const std::string& mensaje)
      : m_error(mensaje)
    { }

    const char* what() const
    { return m_error.c_str(); }
  private:

    std::string m_error;
};

class AnotherException : public std::exception
{
  public:

    AnotherException (const std::string& mensaje)
      : m_error(mensaje)
    { }

    const char* what() const
    { return m_error.c_str(); }
  private:

    std::string m_error;
};

void TestFunc()
{
  throw FileNotFoundException("No se pudo encontrar el fichero notas.txt");
}

int main()
{
  try
  {
    TestFunc();
  }

  catch( const std::exception& exc )
  {
    std::cout << "Error: " << exc.what();
  }
}

Example C ++ 11:

class FileNotFoundException : public std::exception
{
  public:

    FileNotFoundException(std::string const& mensaje) noexcept
      : m_error(mensaje)
    { }

    const char* what() const noexcept override
    { return m_error.c_str(); }
  private:

    std::string m_error;
};

class AnotherException : public std::exception
{
  public:

    AnotherException (std::string const& mensaje) noexcept
      : m_error(mensaje)
    { }

    const char* what() const noexcept override
    { return m_error.c_str(); }

  private:

    std::string m_error;
};

void TestFunc()
{
  throw FileNotFoundException("No se pudo encontrar el fichero notas.txt");
}

int main()
{
  try
  {
    TestFunc();
  }

  // Solo captura FileNotFoundException
  catch( const FileNotFoundException& exc )
  {
    std::cout << "Error de fichero: " << exc.what();
  }

  // Captura cualquier excepción que herede de std::exception
  // excepto FileNotFoundException, que está capturada en el catch anterior
  catch( const std::exception& exc )
  {
    std::cout << "Error: " << exc.what();
  }
}

Examples with enum or #define I will not put you because you already have other answers covering that area.

I'll give you an example incorporating exceptions. I have also tweaked the code a bit to make it more in line with what is expected of a more or less modern C ++ code (absence of raw fixes, variables declared at the time, use of the C ++ own input / output, ...) . The only thing I have not modified is the use of the file ... yes, remember to close the file before leaving the function.

class FileNotFoundException : public std::exception
{
  public:

    FileNotFoundException(const std::string& mensaje)
      : m_error(mensaje)
    { }

    const char* what() const
    { return m_error.c_str(); }
  private:

    std::string m_error;
};

struct Datos
{
  cart;
  certif;
  paq;
};

typedef std::array<Datos,ANYOS> VectorDatos;

VectorDatos leer_correo ()
{
  VectorDatos datos;
  FILE *fe;

  if((fe=fopen("correo.txt", "r"))==NULL){
    throw FileNotFoundException("Error al abrir correo.txt");
  }

  for(int i=0 ; i<ANYOS ; i++)
  {
    int anyo;
    Datos& item = datos[i];
    fscanf(fe, "%d%d%d%d", &anyo, &item.cart, &item.certif, &item.paq);
  }

  fclose(fe);

  return datos;
}

void main(){
  std::array<Datos,ANYOS> datos;

  try
  {    
    datos = leer_correo(); // Llamar a la función leer correo
  }

  catch( const FileNotFoundException& exc )
  {
    std::cout << "Error: " << exc.what();

    // Si otro programa está esperando a que éste devuelva una respuesta
    // entonces el valor de este código es importante. En caso contrario
    // es irrelevante.
    return -1; 
  }

  // Resto del main
  // ...
}

The code should be compatible with C ++ 98. I've tried to do it on purpose because seeing your code I do not think you're compiling with C ++ 11 or C ++ 14.

    
answered by 16.11.2016 в 13:30
0

You should, in the main, check the result of the method leer_corre to see if there was an error or not in the following way:

    #define ERROR_READ_FILE      -1
    #define SUCCESS_READ_FILE    1

    int leer_correo (int cart[], int certif[], int paq[]){
        FILE *fe;
        int i, anyo, total[ANYOS];
        if((fe=fopen("correo.txt", "r"))==NULL){
            printf("Error\n");
            return ERROR_READ_FILE;
        }

        for(i=0 ; i<ANYOS ; i++)
            fscanf(fe, "%d%d%d%d", &anyo, &cart[i], &certif[i], &paq[i]);
        total[anyo-1900]=cart[anyo-1900]+certif[anyo-1900]+paq[anyo-1900];
        return SUCCESS_READ_FILE;
    }

    void main(){
        int opc, cart[ANYOS], certif[ANYOS], paq[ANYOS];    
        if (leer_correo() == ERROR_READ_FILE) // Llamar a la función leer correo
            exit(0); // Si hay error: terminar el programa
    }

I hope you find it useful!

    
answered by 16.11.2016 в 12:48