2

I am very new to C programming and am learning on my own. I want to write a code that asks user to enter some numbers and store them into an array. The program would stop if the user enters 'q'. Then it is supposed to print the array and tell the user how many numbers are in that array. (the length)

I wrote the following code, but if I leave int array[]; empty, it does't work (obviously). I can't define it either because it depends on how many numbers the user enters... I searched a lot through the Internet and came across malloc and calloc. I tried to use them here but I honestly don't know how and I'm sitting on this code for a couple of days now.

#include <stdio.h>
#include <stdlib.h>
int main()
{
int array[]; //I want to leave this empty but C doesn't allow me to.
int len=sizeof(array)/sizeof(array[0]);

for(int a=0;a<len;a++)
{
    printf("Enter element %d: ", a);
    scanf("%d",&array[a]);
    if(getchar()=='q')
        break;
}

printf("Array: [");
for(int a=0;a<len-1;a++)
{
    printf("%d, ", array[a]);
}   printf("%d]", array[len]);
printf("\nArray length: %d\n", len);
return 0;
}

Sample output for int array[5];

Enter element 0: 1
Enter element 1: 2
Enter element 2: 3
Enter element 3: 4
Enter element 4: 5
Array: [1, 2, 3, 4, 5]
Array length: 5

Any help is highly appreciated. Thanks and have a nice day.

3
  • User will input any number of elements? You have store it in array? Commented Jan 30, 2018 at 18:05
  • I don't know if I really "have to" store the numbers into an array or not. I didn't come up with any other better solution for a series of inputs. I want the user to be able to store for example not more than 100 integers or something like that into that array. I don't know how to set this "limit". Sorry if my definitions are off the book. Commented Jan 30, 2018 at 18:11
  • Yes, malloc/calloc is the normal way to create an array sized at runtime. But you'll have to declare array to be a pointer type, not an array type. Commented Jan 30, 2018 at 18:16

3 Answers 3

3

Malloc and calloc functions allows you to dynamically allocate memory for your variables. I think it would work better if you used an int pointer ( int* ) instead of int []. You can do something like this

int * array = malloc (sizeof(int)); //this will allocate enough memory for 1 int element
Len = 1;

And then at the end of the loop, if the user doesn't enter 'q' you can do something like this

len ++ ;
array = realloc(array,len*sizeof(int)); //this will reallocate memory for your int pointer

Then at the end of the code you will have to call the function free like this : free(array); to free the allocated memory.

Edit: after the for loop you are accessing memory that you shouldn't in array[len]. I think you should change it to array[len-1]

Sign up to request clarification or add additional context in comments.

2 Comments

Wow thanks a lot! This is exactly what I was looking for! Yes I fixed that by writing len-1, but I still get a huge random number in my array when it is printed.
Everything works fine now, I just figured out I needed to delete array[len] in the last for loop, because there was no need to it. :)
2

As you yourself said, the idea would be to allocate some number of elements and then store elements in it. When it is full, then reallocate and linearly increase its size. At the end of the processing, you free the memory you didn't use.

A close implementation of what I said:

#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <limits.h>
#include <stdlib.h>

#define MAXLEN 3
#define MAXBUFF 30
int main(void)
{
    size_t sz = 0,tsz=MAXLEN;
    int *arr= malloc(sizeof*arr*MAXLEN);
    if( !arr){
        perror("malloc:");
        exit(EXIT_FAILURE);
    }
    char s[MAXBUFF];
    while(fgets(s,MAXBUFF,stdin)!=NULL){
        if(strstr(s,"q") != NULL){
            break;
        }
        else{

            char *t;
            errno = 0;
            long n = strtol(s, &t, 10);
            if ((errno == ERANGE && (n == LONG_MAX || n == LONG_MIN))|| (errno != 0 && n == 0)) {
                perror("strtol");
                exit(EXIT_FAILURE);
            }
            if (t == s) {
                fprintf(stderr, "No digits were found\n");
                exit(EXIT_FAILURE);
            }
            if ( n >= INT_MIN && n <= INT_MAX)
            {
                arr[sz++]=(int)n;  
            }
            else{
               fprintf(stderr, "Too big/small a number\n");
               exit(EXIT_FAILURE); 
            }

        }
        if( sz == tsz){
            int *p = realloc(arr,sizeof *p*(tsz+MAXLEN));
            if(!p){
                perror("Realloc:");
                exit(EXIT_FAILURE);
            }
            arr = p;
            tsz+= MAXLEN;
        }
    }
    int *p = realloc(arr,sizeof *p*sz);
    if(!p){
        perror("Realloc:");
        exit(EXIT_FAILURE);
    }
    arr = p;
    printf("Numbers entered = %zu\n",sz );
    for(size_t i = 0; i< sz; i++)
        printf("a[%zu]=%d\n",i,arr[i] );
    free(arr);
    return(0);
}

While reading this code, I would recommend looking at the man pages to know what each function returns. The last realloc() basically shrinks the memory to the appropriate size (if there was more allocated than needed). Increase of memory is linear (we have added the size gradually).

4 Comments

Thank you so much for this! It works perfectly but it is hard for me to understand because there are lot of things in it I am not familiar with. I will keep studying the code since it is a very useful example. :)
You can simplify by starting with arr = NULL; tsz = 0 and performing the realloc() at the start of the loop (remember, you can realloc(NULL, size) quite legitimately).
@TobySpeight.: Yes one can..I simply used malloc/
Otherwise, it's pretty robust code - many would forget to reset errno before calling strtol(), or use the wrong printf conversion for size_t - so I've upvoted as a valuable teaching resource. I might remind a beginner of the precedence of sizeof - e.g. that sizeof*arr*MAXLEN is (sizeof *arr)*MAXLEN.
0

array without size is only allowed after c99 came into play for your problem you can make use of malloc and realloc to define the size of the array dynamically here is how the program will go

#include <stdio.h>
#include <stdlib.h>
int main()
{
//Initially defining the size of our dynamic array=1
int *arr = malloc(1 * sizeof(int));
int counter=2;
while(1)
{
    printf("Enter element %d: ", a);
//reallocating array size after user enters a value
    arr = realloc(arr, counter * sizeof(int)); 
    counter++;

    scanf("%d",&arr[counter]);

    if(getchar()=='q')

     break;
}

printf("Array: [");
for(int a=0;a<counter-1;a++)
{
    printf("%d, ", array[a]);
}   printf("%d]", array[counter]);
printf("\nArray length: %d\n", counter);
return 0;
}

let me know if that helped

5 Comments

Thanks a lot. I changed the variable len to counter but I get the following error: test.c:8:7: error: 'true' undeclared (first use in this function) while(true)
i have changed true to 1 its for infinite loop
Thanks a lot sir, yes I did that. Your answer helped me a lot. However I still get a random list of large numbers. There are a couple of undeclared variables in the code that I changed, maybe that's the problem, but I keep changing them and code still gives me random numbers.
sorry it was my mistake i have edited it again please make changes accordingly and do upvote the answer you didn't upvote it yet
Don't forget to check the return value of malloc; even more importantly, check the return value of realloc before assigning to arr and leaking the memory!

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.