In C, it is not possible to simply resize an array. However, there are several other options for solving the problem:
Solution #1: Define an upper-bound of how many numbers you will need, and make the array that size.
Example:
#include <stdio.h>
#define MAX_NUMBERS 100
int main( void )
{
int numbers[MAX_NUMBERS];
int i;
for ( i = 0; i < MAX_NUMBERS; i++ )
{
printf( "Please enter #%d, or -1 to stop: ", i + 1 );
if ( scanf( "%d", &numbers[i] ) != 1 || numbers[i] == -1 )
break;
}
printf( "\nYou entered the following numbers:\n" );
for ( int j = 0; j < i; j++ )
{
printf( "#%d: %d\n", j + 1, numbers[j] );
}
}
This program has the following behavior:
Please enter #1, or -1 to stop: 7
Please enter #2, or -1 to stop: 3
Please enter #3, or -1 to stop: 5
Please enter #4, or -1 to stop: 8
Please enter #5, or -1 to stop: 3
Please enter #6, or -1 to stop: -1
You entered the following numbers:
#1: 7
#2: 3
#3: 5
#4: 8
#5: 3
However, the disadvantages of this solution are that
- you have a hard limit on how many numbers you can have, and
- setting this limit very high may cause you to waste a lot of memory.
If you don't want these disadvantages, then an alterantive would be:
Solution #2: Use a dynamically allocated array and resize it as necessary.
#include <stdio.h>
#include <stdlib.h>
int main( void )
{
int *numbers = NULL;
int i;
for ( i = 0; ; i++ ) //infinite loop
{
//attempt to create/resize buffer to desired capacity
//NOTE: calling realloc with a NULL argument is equivalent
// to calling malloc
numbers = realloc( numbers, (i+1) * sizeof(int) );
if ( numbers == NULL )
{
fprintf( stderr, "Memory allocation error!\n" );
exit( EXIT_FAILURE );
}
printf( "Please enter #%d, or -1 to stop: ", i + 1 );
if ( scanf( "%d", &numbers[i] ) != 1 || numbers[i] == -1 )
break;
}
printf( "\nYou entered the following numbers:\n" );
for ( int j = 0; j < i; j++ )
{
printf( "#%d: %d\n", j + 1, numbers[j] );
}
//cleanup
free( numbers );
}
This solution has the same behavior:
Please enter #1, or -1 to stop: 7
Please enter #2, or -1 to stop: 3
Please enter #3, or -1 to stop: 5
Please enter #4, or -1 to stop: 8
Please enter #5, or -1 to stop: 3
Please enter #6, or -1 to stop: -1
You entered the following numbers:
#1: 7
#2: 3
#3: 5
#4: 8
#5: 3
This solution has the advantage that you are only limited by available memory. However, a disadvantage of this solution is that realloc
may have to copy the entire array to a new memory location, every time you call that function. If you only have a few numbers, then this should not be a problem. However, if you have thousands or even millions of numbers, then it probably will be a problem.
One way of solving this problem would be to not only increase the size of the array by a single element in every loop iteration, but to instead double the size of the array whenever more capacity is needed. That way it is guaranteed that, on average, every number will not have to be copied more than twice by realloc
.
Here is an example:
#include <stdio.h>
#include <stdlib.h>
int main( void )
{
int capacity = 100;
int *numbers;
int i;
//allocate initial array
numbers = malloc( capacity * sizeof(int) );
if ( numbers == NULL )
{
fprintf( stderr, "Memory allocation error!\n" );
exit( EXIT_FAILURE );
}
for ( i = 0; ; i++ ) //infinite loop
{
//double the capacity of the array, if necessary
if ( i == capacity )
{
capacity *= 2;
numbers = realloc( numbers, capacity * sizeof(int) );
if ( numbers == NULL )
{
fprintf( stderr, "Memory allocation error!\n" );
exit( EXIT_FAILURE );
}
}
printf( "Please enter #%d, or -1 to stop: ", i + 1 );
if ( scanf( "%d", &numbers[i] ) != 1 || numbers[i] == -1 )
break;
}
printf( "\nYou entered the following numbers:\n" );
for ( int j = 0; j < i; j++ )
{
printf( "#%d: %d\n", j + 1, numbers[j] );
}
//cleanup
free( numbers );
}