Read string and floats of a file to calculate weighted average in C ++

1

Good day! This question is a continuation of what I did a few weeks ago: How to use Arrays and loops to calculate the weighted average of the university?

In that question Loops and Arrays were used for the calculation of the weighted average of the university, the problem is that the user must put the information (name of the subject, qualification, credits) each time that he opens the program and wanted to automate that part so I used 'fstream' to create a file for each of these variables (the only thing that will change each time the user uses the program is the qualification of each subject so it is not necessary to create a file for be variable, but I did it anyway "to practice": D).

Everything works very well but now I do not know how to read the data from the files and use them in the program. I was thinking of creating an 'if' to ask the user if he wants to use the same subjects and credits or if he wants to enter others (in case the semester has passed or a friend wants to calculate his weighted average), after receiving the answer of the user, how do I use the information already stored in the files? (assuming that the user has already used the program once so that said information is already stored in the files). In short, how to read the file knowing that the one with the names has words and the one with the credits has numbers? Here my code:

#include <iostream>
#include <stdlib.h>
#include <fstream>

using namespace std;

#define NOTA_MIN 0.0f
#define NOTA_MAX 5.0f

#define CRED_MIN 0
#define CRED_MAX 10

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

int num_Mat;
float sumCreditos = 0, sumPonderacion = 0;

// Solicita el numero de materias que luego es usado en el array
cout << "Ingrese el numero de materias\n";
cin >> num_Mat;
float notas [num_Mat];
int creditos [num_Mat];

// Archivo para guardar los nombres de las materias
ofstream file1;                                     // Lo crea
file1.open("Nombre de materias.txt");               // Lo abre y nombra

// Declara un array de tipo string con "n" elementos, definidos por la cantidad de materias
string nombres [num_Mat];

// Loop para obtener el nombre de las materias y guardarlas en el archivo
for (int i = 0; i < num_Mat; i++){
    cout << "Ingresa el nombre de la materia " << i+1 << endl; // "+1" porque no existe Materia 0
    cin >> nombres[i];
    file1 << nombres[i] << endl;
}

file1.close();                                      // Cierra el archivo 1

// Archivo para guardar las calificaciones
ofstream file2;                                     // Lo crea
file2.open("Calificaciones.txt");                         // Lo abre y nombra

// Archivo para guardar los creditos
ofstream file3;                                     // Lo crea
file3.open("Creditos.txt");                         // Lo abre y nombra

for (int i = 0; i < num_Mat; i++){
    cout << nombres[i] << ": \t" << endl;
    // Loop para obtener las calificaciones
    do {
        cout << "nota:\t\t";
        cin >> notas[i];
        file2 << notas[i] << endl;
        cin.clear();
    } while (notas[i] < NOTA_MIN || notas[i] > NOTA_MAX);

    // Loop para obtener los creditos
    do {
        cout << "credito:\t";
        cin >> creditos[i];
        file3 << creditos[i] << endl;
        cin.clear();
    } while (creditos[i] < CRED_MIN || creditos[i] > CRED_MAX);

   // sumar las notas*creditos y los creditos
    sumCreditos += creditos[i];
    sumPonderacion += notas[i] * creditos[i];
}
file2.close();                                      // Cierra el archivo 2
file3.close();                                      // Cierra el archivo 3

cout << "Tu promedio semestral es: " << sumPonderacion / sumCreditos << endl;
cin.get();
return 0;
}

I am aware that my code is a little messy but first I want to finish the program and then I will optimize it and use functions to make it better.

Thank you very much!

    
asked by Germán Diego Guisasola Plejo 07.05.2017 в 21:33
source

2 answers

2

Similar to how you entered the data in the files, but now using ifstream . Now you will be reading the files and saving their contents in a vector. For example:

// Abrir archivo en modo lectura.
ifstream f_palabras ; 
f_palabras.open("Nombre de materias.txt"); 
// aquí se debería de hacer una comprobación de la correcta apertura.

// Vector para guardar los nombres
std::vector<string> nombres ;
string nombre ;

f_palabras >> nombre ; // usar getline(f_palabras, nombre) ; si el nombre es compuesto y leer así la linea completa

// Lectura del fichero hasta el final.
while(!f_palabras.eof()) {
    // inserta nombre en el vector
    nombres.push_back(nombre) ;
    f_palabras >> nombre ; // usar getline(f_palabras, nombre) ; si el nombre es compuesto y así leer la linea completa
}

f_palabras.close();

In the same way it would be done to save the credits. Just change the previous variables of string to the numeric data type that suits you ( double , int ...)

    
answered by 08.05.2017 / 00:09
source
3
string nombres [num_Mat];

Creating an array with a variable-based size is something known as VLA (Variable Length Array) and is a feature not allowed in the C ++ standard. While some compilers and extensions admit it, I would not use it under penalty of seeing how your program fails without remedy at the moment of truth.

To create dynamic-sized arrays you can or use dynamic memory:

string *nombres = new string[num_Mat];
// ...
delete[] nombres;

or you happen to use one of the multiple containers available under the umbrella of the STL. The most generic is std::vector that adapts quite well to most situations:

// No hace falta indicarle el tamaño
std::vector<std::string> nombres;
nombres.push_back("abcd"); // Para añadir un elemento al final de la lista

// Aunque puedes crear un número inicial de elementos si asi lo deseas
std::vector<std::string> nombres(num_Mat);
nombres[1] = "abcd"; // acceder a los elementos se hace igual que en con los arreglos

On the other hand, I do not know what you think cin.clear(); does but I already notice that it does not delete what is in the input buffer. cin.clear() is used to clean the error bits of the stream . To clean the buffer you must use the ignore() method:

std::cin.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
//       ^^^^^^      ^^^^^^^^^^^^^^      ^^^^^^^^^^^  ^^^    ^^
//        (1)              (2)               (3)      (4)    (5)

Where:

  • Method that allows you to discard buffer data
  • Template that allows to recover the maximum and minimum values of each type of data. Found in #include <limits>
  • We are interested in the range of values of streamsize , type used generically for the buffers input and output (in 32 bits it is equivalent to unsigned int ).
  • We recover the maximum value admitted by the previous type.
  • Values will be discarded until the number indicated above or until reaching a line break (which will also be discarded)
  • Well, at this point, to read the data and store it in your program, you have to consider some details such as the format of the file (which you have already decided) and its implications. Do you know how many records each file has? That both files have the same number of records is a requirement? ...

    For the first question I can assume that you do not know it since it does not look like, for example, the first data of each file indicates the number of elements registered in the file. So the most comfortable thing is to use a container of the STL (Standard Template Library) to store the data as we are reading:

    std::vector<float> notas;
    
    std::ifstream fichNotas;
    if( !fichNotas.open("Calificaciones.txt") )
    {
      // No es posible abrir el fichero
    }
    else
    {
      while( true )
      {
        float nota;
        fichNotas >> nota;
        if( fichNotas.good() && !fichNotas.eof() )
          notas.push_back(nota);
        else
          break; // Se ha detectado un error o hemos leido todo el fichero - dejamos de leer
      }
    }
    

    And something similar to read the credit file.

        
    answered by 08.05.2017 в 10:24