Question:
Here's the statement:
Write a program that reads numbers from the keyboard and stores them in a dynamically allocated array. The user will type a sequence of numbers, with no amount limit. The numbers will be typed one by one and, if he wants to finish the data entry, he will type the number ZERO. Data must be stored in memory this way
- Start with a dynamically allocated array of size 10;
- Afterwards, if the allocated vector is full, allocate a new vector the size of the previous vector adding space for 10 more values (size N+10, where N starts with 10);
- Copy the values already entered from the initial area to this larger area and free the memory of the initial area;
- Repeat this procedure of dynamically expanding the allocated vector with 10 more values each time it is full. So the vector will be 'expanded' by 10 in 10 values.
At the end, display the read vector. Do not use the REALLOC function.
I'm still pretty new, so there's probably a lot of things wrong with my code.
I tried using a second vector, passing everything to it, allocating 10 more spaces in the main vector and then passing everything to it again.
However, when I'm typing I get to 19 and the program stops. In the first 10, it works perfectly, but then when I allocate another 10 (in which case the vector would have 20 spaces) it doesn't work.
Here's the code I made:
#include <stdio.h>
#include <stdlib.h>
int main(){
int *vet, c=1, c2=0, *vet1, aux;
vet =(int*) calloc(10, sizeof(int));
do {
scanf("%d", &aux);
if (c == 10){
vet1 = (int*) malloc (c2 * sizeof(int));
for (int i=0; i<c2+1; i++) vet1[i] = vet[i];
vet = (int*) malloc (c2 * sizeof(int));
for (int i=0; i<c2; i++) vet[i] = vet1[i];
c = 1;
}
c++;
c2++;
vet[c2] = aux;
} while (aux != 0);
printf("\n\n") ;
for (int i=0; i<c2; i++) printf("%d ", vet[i]);
system("pause");
return 0;
}
Answer:
One of the reasons for the confusion is that the code uses variable names that are difficult to understand what they mean. With better names, you can better follow what is happening. The code does more than it should and falls into some pitfalls.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
int indice = 0, indiceParcial = 0;
int *vetor = malloc(sizeof(int) * 10);
while (1) {
int valor;
scanf("%d", &valor);
if (valor == 0) break;
vetor[indice++] = valor;
if (indiceParcial++ == 9) {
int *vetorAuxiliar = malloc(sizeof(int) * (indice + 10));
memcpy(vetorAuxiliar, vetor, indice * sizeof(int));
free(vetor);
vetor = vetorAuxiliar;
indiceParcial = 0;
}
}
printf("\n");
for (int i = 0; i < indice; i++) printf("%d ", vetor[i]);
}
See it working on ideone . And on repl.it. I also put it on GitHub for future reference .
- Only declare the variable when you need it
- It doesn't need
calloc()
and shouldn't cast the result. - I'm not worrying about the test to see if the allocation spoke because in exercise like this it won't fail
- This is a typical endless loop as the output is in its core there is no reason to use condition
- Once the value is entered, it must determine whether to continue or exit the loop.
- The first thing that must operate is the addition of the value in the vector
- Then it analyzes if the vector is full and must proceed with a reallocation and copy
- When to recreate you create based on the current size plus 10, as stated
- And use
memcpy()
which is ready and reliable function to copy data. You usesizeof
in it for the same reason you use it inmalloc()
, these functions operate based onchar
, so copy byte by byte, and if you have a number of elements of a multibyte type you have to multiply by that number - Can't forget to free the previous vector memory
- And then the newly created vector is adopted as the default by copying its address (
vetor
becomes null afterfree()
, if all goes well) - And we zeroed out the partial index that controls when it breaks the limit. It is possible to eliminate this variable and make an
indice % 10
, but it will almost certainly be slower as division is by far the slowest processor operation. Or use one thing or another, you need to decide if you want simpler code or more performance - Maybe it would be better to use a
for
reducing scope of 2 variables.