In the C language, is there a way to automatically grow an array.
For example:
int arr [100] [10];
If the array is full is it possible to have it "automatically" become larger? Or is that only possible if you're using C++. How would you write this in C?
There is no such feature in C: you have to declare the array using pointers, detect the "array is full" condition manually, call malloc, make a copy into an extended array, and free the original one. Even the variable-length arrays would not work, because they let you set their size only once per the array lifetime.
In C++, you can use std::vector<std::vector<int> > instead of a plain array. You still need to detect the "array is full" condition, but the std::vector<T> container takes care of all re-allocations and extensions on resizing for you.
"automatic" growth of any array in C is not possible. If you declare an array statically:
int arr[10];
you have however many memory locations as you indicated. If you want to be able to change it during runtime you need to declare it dynamically using malloc() and make it larger using realloc()
A quick example for you:
int main(void){
int input, count = 0, length = 2;
int * arr = malloc(sizeof(int) * length); // array of size 2
while((input = getchar()) != 'q') //get input from the user
{
getchar(); //get rid of newlines
arr[count] = input;
if(count + 1 == length){ // if our array is running out of space
arr = realloc(arr, length * length); // make it twice as big as it was
length *= length;
}
count++;
}
for(length = 0; length < count; length++) // print the contents
printf("%d\n", arr[length]);
free(arr);
return 0;
}
Related
I've taking many attempts at solving this problem but failed every time.
I have an array
char *array[1024] = {};
Now I would like to add an item to the array and would also access the items by numbers
For example:
array[0] would be the first item
array[1] would be the second
array[2] would be the third item
But also I would like to know how many items are in the array so I could use something like
for(int i = 0; i <= totalitemsinarray; i++) {
print(array[i]);
}
You cannot change the size of an array in C. You can however allocate a sufficiently large array and then fill it up with entries. First, declare an array with a sufficient size, say, 1024.
char *array[1024];
Then declare a variable fill that counts the number of used slots in array. Initialize it to 0 as 0 slots are used in the beginning. Then, each time you insert an item, increment fill:
array[fill++] = ...;
...
array[fill++] = ...;
Make sure that you never attempt to insert more than 1024 items into the array, C doesn't check that for you.
For a more flexible approach, use malloc() to allocate memory for the array and then periodically enlarge it with realloc() when it's full. If you increase the array size in exponential steps (say, multiply with Φ = 0.5 + 0.5 √2 ≈ 1.61), this runs in O(1) amortised time per entry inserted.
There is no way to do what you're asking directly with C. One option could be if you knew that only certain values were valid. For example, you have an array of char *s so often people use NULL as a flag/invalid value. In that case you could initialize your array to have all NULLs and use that to know the size of the array:
char *array[1024];
memset(array, 0, sizeof(array));
/* .... */
for (int i = 0; i < sizeof(array)/sizeof(char*); i++) {
if (array[i]) {
printf("%s\n", array[i]);
}
}
char *array[1024] = {};
First, that is an array with 1024 char pointers/strings. Those elements can be 0s or plain garbage. If you don't plan to set them all you may want to nullify the array.
For the matter of storing the values and the count you might want to have a look at structs. For example:
typedef struct elem {
int count;
char *value;
} elem;
Then elem.count would be the number and elem.value would be the value accordingly.
And then initialize them in a for loop.
The only really valid way to approach this, is to dynamically grow the array. Allocate the array on the heap, and manage two counts: 1. the count of currently used elements, and 2. the count of elements for which you currently have memory allocated. Something like this:
//the setup
size_t arrayLength = 0, allocatedSize = 8;
int* array = malloc(sizeof(*array) * allocatedSize);
//grow the array -> first check that we have space to add an element
if(arrayLength == allocatedSize) {
array = realloc(array, allocatedSize *= 2);
assert(array);
}
assert(arrayLength < allocatedSize);
//grow the array -> add an element
array[arrayLength++] = ...;
You see, the realloc() call is not too much hassle, but it will protect you from bugs when the requirements change. My experience is that any fixed limit in the code, as insanely large as it may seem to be, will eventually be exceeded, and miserable failure will result. The only safeguard is to use as much memory as needed everywhere.
I'm working on a basic shell (as in the console program that awaits commands and executes them in UNIX systems) replica in C, and need to be able to manipulate 2d arrays of char to store the environment variables.
I wrote a small function to create that 2d array and initialize each string to NULL before I fill it up elsewhere in my code.
Except that it crashes as soon as the program is launched, for some reason.
I have similar issues (namely occasional segfaults, probably due to me reading/writing in an inapropriate place) with two other functions, respectively to free those 2d arrays when needed, and to get the length of one of those 2d array.
If I don't use these two functions and malloc the 2d array within the rest of my code, without initializing anything except the last entry to NULL, but instead copy the env strings directly after the malloc, I have something that works. But it'd be better to be able to prevent the memory leaks, and to have that ft_tabnew function to work so that I could reuse it in future projects.
char **ft_tabnew(size_t size)
{
char **mem;
size_t i;
if (!(mem = (char **)malloc(size + 1)))
return (NULL);
i = 0;
while (i < size + 1)
{
mem[i] = NULL;
i++;
}
return (mem);
}
void ft_tabdel(char ***as)
{
int i;
int len;
if (as == NULL)
return ;
i = 0;
len = ft_tablen(*as);
while (i < len)
{
if (*as[i])
ft_strdel(&(*as[i]));
i++;
}
free(*as);
*as = NULL;
return ;
}
size_t ft_tablen(char **tab)
{
size_t i;
i = 0;
while (tab[i])
i++;
return (i);
}
NOTE : The ft_strdel function used in ft_tabdel is freeing a string that was dynamically allocated, and sets the pointer to NULL. I've been using it for a few months in several projects and it has not failed me yet.
Hopefully, you wonderful people will be able to tell me what misconception or misunderstanding I have about 2d arrays of chars, or what stupid error I'm making here.
Thank you.
You're not allocating enough space.
if (!(mem = (char **)malloc(size + 1)))
only allocates size+1 bytes. But you need to allocate space for size+1 pointers, and pointers are typically 4 bytes. You need to multiply the number of elements by the size of each element:
if (!(mem = malloc((size + 1) * sizeof(*mem))))
In the code
char **mem;
while (i < size + 1)
{
mem[i] = NULL;
i++;
}
mem is a "pointer to a pointer to a char" and hence its size is that of a pointer, not of a char. When you say mem[i] and incement i, you increment with the size of pointer, not of char, and so overwrite memory outside your allocated memory. Try:
if (!(mem = (char **)malloc((size + 1)*sizeof(void *))))
I am new to C and was writing a function to insert an element to sorted list. But my code does not display the last digit correctly. Though i know there are variety of ways to correct it but i want to know why my code isnt working, here's the code
#include <stdio.h>
int insert(int array[],int val);
int main (void)
{
int arr[5],j;
for (j = 0; j<5; j++)
{
scanf("%d",&arr[j]);
}
insert(arr,2);
for(j = 0;j<6;j++)
printf("%d",arr[j]);
return(0);
}
int insert(int array[],int val)
{
int k,i;
for (k = 0;k<5;k++)
if(val<array[k])
break;
for (i = 4; i>=k;i--)
{
array[i+1] = array[i];
}
array[k] = val;
return(1);
}
You are writing out of the range of the array here:
for (i = 4; i>=k;i--)
{
array[i+1] = array[i];
Where i+1 == 5 and you array has a range of 0 ...
4
Then you try to print the array but you go out of bounds again:
for(j = 0;j<6;j++)
printf("%d",arr[j]);
First make sure your array is large enough.
When you give a static / auto array to a function for insertion of elements, you must give: Address, Valid length, and Buffer Space unless guaranteed large enough.
When giving a dynamically allocated array, you must give pointer and valid length, you might give buffer space or guarantee enough space left to avoid reallocations.
Otherwise, you risk a buffer overrun, and UB means anything may happen, as in your example.
You're trying to make arr[6] out of arr[5] adding one val - it's impossible in C using statically allocated arrays.
To accomplish what you're trying to do you'd need to use dynamical arrays allocation:
int *arr;
int N = 5;
arr = (int *)malloc(N*sizeof(int));
then you use this arr same way as you did with arr[5] for loading data here via scanf.
And later on , while adding extra value to array - you'd need to reallocate your arr to make it bigger (read about malloc/realloc C functions):
arr = (int *)realloc((N+1)*sizeof(int));
Now your arr is of 6 int-s size.
Unfortunately if you don't know array sizes (number of elements) a priori you would need to deal with dynamical memory allocations in C.
Don't forget to release that memory in the end of the main() function:
free(arr);
You have to increase your array size from 5 to 6 as you are inserting one new element in your array, so there should be some space for that.
int arr[6];
you can also find more information in the link below:
https://learndswithvishal.blogspot.com/2020/06/insert-element-in-sorted-array.html
I have a char array
char *data[]= {"11", "22", "33", "44", "55"};
How can I add some extra items to it in the end? data[]="66";
I'd like a dynamic array in C.
Thanks
Arrays created using the [] syntax are not dynamic, the length is set at compile-time and cannot change.
UPDATE: Actually, C99 adds so-called "variable-length arrays", which can get their length at run-time. After they've been initialized, however, they can't shrink or expand so the below still applies.
However, an array is trivially expressed when you have pointers: an array can be represented as a pointer to the first element, and a length.
So, you can create a new array by dynamically allocating memory using malloc():
size_t array_length = 3;
int *array = malloc(array_length * sizeof *array);
if(array != NULL)
{
array[0] = 11;
array[1] = 22;
array[2] = 33;
}
You cannot use the {} list of elements here, that's only usable when initializing arrays declared using the [] syntax.
To grow the array, you can use the realloc() function to re-allocate the memory and copy the old values over:
size_t new_length = array_length + 1;
int *bigger_array = realloc(array, new_length * sizeof *bigger_array);
if(bigger_array != NULL)
{
bigger_array[new_length - 1] = 44;
/* We have successfully grown the allocation, remember the new address. */
array = bigger_array;
array_length = new_length;
}
Note that every time you call malloc() (or realloc()), it can return NULL if it failed to allocate the requested block. That's why the if statements are needed. I cut the initial size down a bit from your example to reduce the number of assignment-lines needed, to make the example shorter.
To make the above more efficient, typical dynamical array code uses two length values: one for the actual array (how many values are in the array right now) and one for the memory (how many values to we have room to store). By making the latter value grow in chunks, the total number of memory allocations can be cut down a bit, at the cost of some memory of course.
vc_vector
vc_vector* vector = vc_vector_create(0, sizeof(const char *), NULL);
vc_vector_push_back(vector, "11");
vc_vector_push_back(vector, "22");
vc_vector_push_back(vector, "33");
for (int i = 0; i < vc_vector_count(vector); ++i) {
printf("%s ", (const char*)vc_vector_at(vector, i));
}
// output: 11 22 33
vc_vector_release(vector);
Here is a macro based solution for a dynamic array in C with a very nice syntax to use. Works for any data type.
#include <stdio.h>
#include <stdlib.h>
#include <wondermacros/array/dynamic_array.h>
int main()
{
int* elems = NULL; /* Initialize a dynamic array. */
W_DYNAMIC_ARRAY_PUSH(elems, 1, 2, 3, 4); /* Push some elements. */
/* Iterate all elements. */
W_DYNAMIC_ARRAY_FOR_EACH(int, e, elems) {
printf("%d\n", e);
}
W_DYNAMIC_ARRAY_FREE(elems); /* Free the array only this way since there is a hidden header. */
}
The library uses Boost pre-processor library so Boost library needs to be there at build time.
Ok, this is a C programming homework question. But I'm truly stuck.
I ask the user to input words, and then I insert the input into an array, but I can't have any control over the number of words the user types.
I guess what I'm asking is how do you declare a an array in C without declaring its length and without asking the user what the length should be.
I know this has something to do with malloc, but if you could give me some examples of how to do this, I would really appreciate it.
You can malloc a block of memory large enough to hold a certain number of array items.
Then, before you exceed that number, you can use realloc to make the memory block bigger.
Here's a bit of C code that shows this in action, reallocating an integer array whenever it's too small to hold the next integer.
#include <stdio.h>
#include <stdlib.h>
int main (void) {
int *xyzzy = NULL; // Initially NULL so first realloc is a malloc.
int currsz = 0; // Current capacity.
int i;
// Add ten integers.
for (i = 0; i < 10; i++) {
// If this one will exceed capacity.
if (i >= currsz) {
// Increase capacity by four and re-allocate.
currsz += 4;
xyzzy = realloc (xyzzy, sizeof(int) * currsz);
// Should really check for failure here.
}
// Store number.
xyzzy[i] = 100 + i;
}
// Output capacity and values.
printf ("CurrSz = %d, values =", currsz);
for (i = 0; i < 10; i++) {
printf (" %d", xyzzy[i]);
}
printf ("\n");
return 0;
}
You can realloc it every time like:
int size = 0;
char **array = malloc(0);
while(/* something */)
{
char *string = // get input
size++;
array = realloc(array, size * sizeof(char*));
array[size - 1] = string;
}
Or in chunks if you care about speed.
Yes, you want malloc. Checkout this tut.
http://www.cprogramming.com/tutorial/dynamic_memory_allocation.html
This site is good in general for learning.
Here is an example of using realloc, it is basically exactly what you are asking to do.
http://www.cplusplus.com/reference/clibrary/cstdlib/realloc/
0) obviously you will need multiple buffers, so you will need a list like structure: perhaps a record with char array 100 chars and a pointer to next structure
1) You need to capture the words char by char and store them in your buffer
2) once the buffer is full you allocate another record, chain it with the previous one and keep going until you are out of mem or the process is over.
That should be better performance than realloc function. I believe malloc is trying to give contious block of memory. Therefore the list like structure will be faster and work better.