He is working on some modules that will help me in the development of other programs for my classes. Everything has gone well and when I tried them separately they have worked correctly, but now that I have used them together I have noticed something strange, because a class that is responsible for obtaining the factorials of a number does not work.
I have a function that is responsible for obtaining the sine of an angle by means of a formula in which the factorial of the number is needed, in this function I request the data from the user and then I instantiate my class and that is where the program simply finishes executing and it doesn't show any error. I tried putting a cout<<"ok";
after the class instance and it doesn't show it, so the error occurs when instantiating the class.
This is the code I have:
#include <iostream>
#include <math.h>
using namespace std;
struct elemento
{
long long int elemento;
long long int factorial;
};
class Lista_factoriales {
elemento *factoriales = new elemento[4];
elemento ultimo;
public:
int size = 4;
Lista_factoriales(){
elemento F2, F3, F4, F5;
F2.elemento = 2;
F2.factorial = 2;
F3.elemento = 3;
F3.factorial = 6;
F4.elemento= 4;
F4.factorial = 24;
F5.elemento = 5;
F5.factorial = 120;
this->factoriales[0]=F2;
this->factoriales[1]=F3;
this->factoriales[2]=F4;
this->factoriales[3]=F5;
this->ultimo = F5;
}
long long int factorial(int num){
for(int i=0; i<this->size; i++){
if(this->factoriales[i].elemento == num) return this->factoriales[i].factorial;
}
return this->getFactorial(num);
}
long long int getFactorial(int num){
long long int ultimo = this->ultimo.elemento;
long long int resultado = this->ultimo.factorial;
if(ultimo==num) return this->ultimo.factorial;
else if(ultimo<num){
long long int i = ultimo+1;
for(; i<=num; i++){
resultado*=i;
}
}
elemento new_factorial;
new_factorial.elemento = num;
new_factorial.factorial = resultado;
this->factoriales[this->size] = new_factorial;
this->size++;
this->ultimo = new_factorial;
return resultado;
}
};
struct Opcion
{
const char* enunciado;
void (*funcion)();
};
class Menu {
Opcion *lista_opciones = new Opcion[0];
const char* dialogo = "";
public:
int size_opt = 1;
void add_option(const char* msg_opcion, void (*funcion)()){
int i = size_opt-1;
Opcion opcion;
opcion.enunciado = msg_opcion;
opcion.funcion = funcion;
lista_opciones[i] = opcion;
size_opt++;
}
void show(){
for(int i=0; i<size_opt-1; i++){
cout<<i+1<<") ";
cout<<lista_opciones[i].enunciado<<endl;
}
int opt;
while(1){
cout<<">>> ";
cin>>opt;
if(opt>0 && opt<=size_opt-1) break;
cout<<"La opción no es válida"<<endl;
}
lista_opciones[opt-1].funcion();
}
};
void seno(){
int terminos;
int x;
cout<<"Ingrese el numero de terminos: ";
cin>>terminos;
cout<<"Ingrese el valor de x: ";
cin>>x;
Lista_factoriales facotriales;
float resultado = 0;
for(int i=1; i<=terminos; i++){
float num = pow(x, (2*i)+1);
long long int fact = facotriales.factorial((2*i)+1);
int signo = pow(-1, i);
resultado += signo*(num/fact);
}
cout<<"El resultado es: "<< resultado;
}
void nesimo(){
int num, n;
cout<<"Ingrese el numero: ";
cin>>num;
cout<<"Ingrese la posicion: ";
cin>>n;
int digito;
digito = abs(num)/pow(10, n+1);
cout<<"el dígito es: "<<digito%10;
}
int main(){
Menu menu;
menu.add_option("Sacar seno", seno);
menu.add_option("n-esimo numero", nesimo);
menu.show();
return 0;
}
But the weirdest thing is that if I call the function seno
directly on main
it, it executes correctly. All this only happens with the function seno
since the other function works perfectly.
Given that it
this->factoriales
has capacity for 4 elements and thatthis->size == 4
, in this line you are accessing memory that does not belong to the array.On the other hand, arrays cannot increase in size, so increasing the value of
size
, as you do just in the following line, will not give you good results:If you need to handle an array that grows in size, it is preferable to use
std::vector
. This container does all the memory management for you. You only care about adding or removing elements and giving some use to the values you add there:At the end there was another problem that was the same as the previous one, a memory management problem. Well, in the class I
Menu
initialized an array ofOpcion
size0
and apart from that, I added more elements than I could in the array. For some reason it did show me everything correctly (in the menu).The Menu code would look like this:
Calling the method
add_option
creates a new array of a larger size than the previous one, then copies the elements of the previous array to the new array. Finally, the new option instance is created and added to the new array. Now we only have to empty the memory of the previous one and assign the new pointer to it.This can be simplified if used
vector
as @eferion mentions in his answer. And that's how I implemented it for theLista_factorial
. It's a good option, but because my class is just beginning to touch on pointers and arrays, I don't know if they let me use it.