C ++ - Different Ouput (Sum and product of Vectors)

0

I'm trying to add to a third vector. The addition and multiplication of two different vectors. However I can not understand why the output values are not as expected.

The methods I use are: show, add and make Product.

void mostrar(int vecAMostrar[], int tamanioVector){
    for(int i = 0; i < tamanioVector ; i++){
        cout << vecAMostrar[i] << endl;
    }
    return;
}

void suma(int vec1[], int vec2[], int vecResultado[], int tamanioAceptado){

    for(int i = 0; i < tamanioAceptado; i++){
        vecResultado[i] = vec1[i] + vec2[i];
    }
    return;
}

void producto(int vec1[], int vec2[], int vecResultado[], int tamanioAceptado){

    for(int i = 0; i < tamanioAceptado; i++){
        vecResultado[i] = vec1[i] * vec2[i];
    }
    return;
}

But, when I invoke them in the main:

int main()
{
    int vecUno[] = {1, 2, 3, 4, 5};
    int vecDos[] = {1, 2, 3, 4, 5};
    int vecSuma[] = {};
    int vecProducto[] = {};

    producto(vecUno, vecDos, vecProducto, 5);
    cout << "PRODUCTO" << endl;
    mostrar(vecProducto, 5);

    suma(vecUno, vecDos, vecSuma, 5);
    cout << "SUMA" << endl;
    mostrar(vecSuma, 5);

    return 0;
}

What I get is that the second output is wrong. Am I doing something wrong in the main or functions?

    
asked by jqc 15.08.2017 в 18:01
source

2 answers

0

The problem is that it seems that the memory is not being handled well and vec2 takes the values of the last operation, I was testing and if the fixed fixes have no problem the final result tests to make sure:

int vecUno[5] = {1, 2, 3, 4, 5};
int vecDos[5] = {1, 2, 3, 4, 5};
int vecSuma[5];
int vecProducto[5];

These are the lines where you initialize the vectors.

    
answered by 15.08.2017 / 22:22
source
0

You are using two different language features that combined in the wrong way, cause your code to behave erratically.

Implicit deduction of array size.

The C ++ language (and also C) allows the size of an array to be omitted if the elements are given explicitly when initializing it; in that case the compiler will count the elements saving that tedium to the programmer, in your case:

int vecUno[] = {1, 2, 3, 4, 5}; // Arreglo de 5 elementos, equivale a int vecUno[5] = ...
int vecDos[] = {1, 2, 3, 4, 5}; // Arreglo de 5 elementos, equivale a int vecDos[5] = ...
int vecSuma[] = {}; // Arreglo de CERO elementos
int vecProducto[] = {}; // Arreglo de CERO elementos

Since when initializing vecSuma and vecProducto you have given them an empty list, the count of elements of these lists is zero, so they contain zero elements; on the other hand vecUno and vecDos contain five elements because the count of elements of the list used to initialize them is five; in memory they would look similar to:

As you can see, neither vecSuma nor vecProducto point to space in memory because they have 0 elements!

Decay from fix to pointer.

Passing an array to a function without indicating its size is equivalent to passing a pointer to the first element of the array, so your functions mustrar , suma and producto could be rewritten to accept pointers without their behavior was affected:

void mostrar(int vecAMostrar *, int tamanioVector);
void suma(int vec1 *, int vec2 *, int vecResultado *, int tamanioAceptado);
void producto(int vec1 *, int vec2 *, int vecResultado *, int tamanioAceptado);

However, if you had specified the size in the array parameter of the functions (instead of adding it as an additional parameter) you would have encountered an error at compile time:

void mostrar(int (&vecAMostrar)[5]) { ... }
void suma(int (&vec1)[5], int (&vec2)[5], int (&vecResultado)[5]) { ... }
void producto(int (&vec1)[5], int (&vec2)[5], int (&vecResultado)[5]) { ... }

int main()
{
    // ...
    producto(vecUno, vecDos, vecProducto);
    mostrar(vecProducto

    // ..
    suma(vecUno, vecDos, vecSuma);
    mostrar(vecProducto

    // ...
    return 0;
}

error: ninguna función coincide con la llamada a 'producto'
producto(vecUno, vecDos, vecProducto);
^~~~~~~~
nota: la función candidata no es viable: no existe conversión conocida de 'int [0]' a 'int (&)[5]' para el 3r parámetro
void producto(int (&vec1)[5], int (&vec2)[5], int (&vecResultado)[5]){
                                                   ^
error: ninguna función coincide con la llamada a 'mostrar'
mostrar(vecProducto);
^~~~~~~
nota: la función candidata no es viable: no existe conversión conocida de 'int [0]' a 'int (&)[5]' para el 1r parámetro
void mostrar(int (&vecAMostrar)[5]){
                  ^
error: ninguna función coincide con la llamada a 'suma'
suma(vecUno, vecDos, vecSuma);
^~~~
nota: la función candidata no es viable: no existe conversión conocida de 'int [0]' a 'int (&)[5]' para el 3r parámetro
void suma(int (&vec1)[5], int (&vec2)[5], int (&vecResultado)[5]){
                                               ^

By passing the parameters as a reference to a fixed-size array (that odd parameter of tipo (&nombre)[tamaño] ) we avoid that the array drops to pointer and then the compiler is forced to check if the last parameter matches the expected parameter; As we can see, the errors do not coincide: an arrangement of any element is not an arrangement of five elements.

What happened to your program?

We have seen that vecSuma and vecProducto do not point to any space in memory (of course, they have zero elements) so when indexing and writing about them you are forcing a undefined behavior that could make the program work without visible errors, or could cause memory corruption (showing erroneous values), or it could erase your hard drive, cause Third World War or invoke demons inside your nostrils .

How to fix it?

As Dariel Ramos Díaz de Villegas has already commented, a possible solution is to assign size to the destination arrangements ( although it has not explained why this solves it) in this way you avoid indefinite behavior since the fixes vecSuma and vecProducto will point to a memory space large enough to assign the results of the operations; if you are going to use fixes of prefixed size I would also advise to use the type of these fixes as type of the parameters, getting in this way that the compiler detects the errors in compile time:

using cinco_enteros = int[5];

void mostrar(const cinco_enteros &vecAMostrar){
    for (const auto &valor : vecAMostrar) {
        std::cout << valor << '\n';
    }
}

void suma(const cinco_enteros &vec1, const cinco_enteros &vec2, cinco_enteros &vecResultado){
    for(int i = 0; i < 5; ++i){
        vecResultado[i] = vec1[i] + vec2[i];
    }
}

void producto(const cinco_enteros &vec1, const cinco_enteros &vec2, cinco_enteros &vecResultado){
    for(int i = 0; i < 5; ++i){
        vecResultado[i] = vec1[i] * vec2[i];
    }
}

In the previous code we have defined an alias for the type int[5] (an array of five integers) and we use it to declare the parameters of the functions, you can see the code working here ; note that in addition the parameters that will be used only to be read are passed as constants, this is considered a good practice; also bear in mind that I have eliminated the instruction return of the end of the functions, it is not necessary because the function was already going to end likewise.

Another alternative, knowing the size beforehand, is to use a std::array<int, 5> instead of a int[5] .

Other things to consider.

  • Encourage when possible (almost always) the pre-increment to the post-increment, read this article for more details.
  • In such a short program you will not have many problems, but as far as possible avoid using namespace std; in headers (does not apply in your case), read this thread to know why.
  • Encourage the use of \n versus std::endl where possible (almost always), read this thread to find out why.
answered by 16.08.2017 в 10:29