How can allocate multi dimensional array at run time? - c

at design time I could have declare a variable like this:
char szDesignTimeArray[120][128];
The above declaration is 120 arrays of size 128. At run time I need to allocate the following:
char szRunTime[?][128];
I know the size of the arrays but I do not how many arrays I need to allocate. How can I declare this and allocate them when I know the number?
Thnaks all

I assume at run-time you know the Row_Size as well.
You can dynamically allocate a multidimensional array at run time, as follows:
#include <stdlib.h>
int **array;
array = malloc(nrows * sizeof(int *));
if(array == NULL)
{
fprintf(stderr, "out of memory\n");
exit or return
}
for(i = 0; i < nrows; i++)
{
array[i] = malloc(ncolumns * sizeof(int));
if(array[i] == NULL)
{
fprintf(stderr, "out of memory\n");
exit or return
}
}
Reference:
http://www.eskimo.com/~scs/cclass/int/sx9b.html

With the length of the rows statically know, you could also allocate
char (*szRunTime)[128];
// obtain row count
szRunTime = malloc(rowCount * sizeof *szRunTime);
memory to a pointer to char[128]. That way, you get a contiguous block of memory, which may give better locality, and you need only free one pointer.
If the number of rows is not too large, using a variable length array,
rowCount = whatever;
char szRunTime[rowCount][128];
may however be the best option if C99 or later is supported.

use this ,, where Variable is the how many array you want :
char **szRunTime = malloc(sizeof(char *)*Variable);
int i;
for(i=0 ; i<Variable ; i++)
szRunTime[i] = malloc(sizeof(char)*128);

Related

How to initialize and save data to 2d array in C

If I had a 2d array with multiple c strings, how would I initialize the array without knowing how many c string will be added into that array.
I have tried to initialize like below but when I try to add a c string I get an error when compiling.
Error : explicit dimensions specification or initializer for an auto or static array.
static Char data[][100];
int main(){
int i;
char word[5];
strcpy(word,"data");
For(i=0; i < rows; i++){
strcpy(data[i],word);
}
}
So the array should hold for example
data[][100]= {"data","data"};
The row value depends on how many rows are retrieved from an sql so my problem is I want to somehow dynamically create the array to fit the size of the rows retrieved from the SQL.
Any help or information would be great.
You can use a pointer to array and reallocation.
#include <stdlib.h> /* for realloc() */
#include <string.h> /* for strcpy() */
int rows = 100; /* for example */
static char (*data)[100] = NULL;
int main(){
int i;
char word[100]; /* allocate array, not a single char */
strcpy(word,"data");
for(i=0; i < rows; i++){
char (*newData)[100] = realloc(data, sizeof(*data) * (i + 1));
if (newData == NULL) { /* allocation error */
free(data);
return 1;
}
data = newData;
strcpy(data[i],word);
}
}
If you don't know how many strings there will be in advance, you either have to set a fixed maximum limit to the static array, or alternatively use dynamic allocation of an array of char pointers.
When using dynamic allocation, you can malloc a "pretty large number" at first, keep track of how many strings there are, and then realloc when you run out of space.
EDIT: pseudo-code example without error handling, free() etc
int main (void)
{
size_t alloc_size = sizeof(char*[100]);
char** data = malloc(alloc_size);
for(size_t i=0; i<rows; i++){
if(i > alloc_size)
{
alloc_size *= 2;
data = realloc(data, alloc_size);
}
size_t str_size = strlen(input)+1;
data[i] = malloc(str_size);
memcpy(data[i], input, str_size);
}
}

is this a nice way to allocate memory for an array of arrays? (C)

Okay, imagine I have a char**, would this be the correct way to allocate memory?
I mean: allocate memory for the char** itself and then for each char*...
char** fraseUsuario = NULL;
int length = 100, i = 0;
fraseUsuario = (char **) malloc(sizeof (char*)); //Not pretty sure
for (i = 0; i < 3; i++) {
fraseUsuario[i] = (char *) malloc(length * sizeof (char));
if (fraseUsuario[i] == NULL) {
printf("error\n");
return -1;
}
gets(fraseUsuario[i]);
}
for (i = 0; i < 3; i++) {
printf("%s\n", fraseUsuario[i]);
free(fraseUsuario[i]);
}
And btw, how exactly does free() work? I mean, when I call it at the end, with the debugger it seems as if it does "nothing", if "Hello" is stored in the array, it will continue to be stored there after the free call... is that the normal behavior?
What do you mean allocate memory for the char ** itself? You allocate memory for a variable on the stack when you define it. The following statement defines (allocates memory) fraserUsuario and initializes it to NULL.
char **fraseUsuario = NULL;
I think what you probably meant is how to dynamically allocate an array of char **, i.e., pointer to a pointer to a character. Then you again dynamically allocate an array for each element of the previous allocated array. Do not use gets. It's deprecated and unsafe to use. Use fgets instead. Also, please don't cast the result of malloc. You don't get any benefit and you can run into error if you forget to include the header stdlib.h which contains its prototype. Here's how you do it.
char **fraseUsuario = NULL;
int max_string_len = 100 + 1; // maximum string length. +1 for null byte
int num_string = 3; // number of strings to read
int i, j;
fraseUsuario = malloc(num_string * sizeof *fraseUsuario);
if(fraseUsuario == NULL) { // check for NULL
// handle the case
printf("not enough memory\n");
return -1;
}
for(i = 0; i < num_string; i++) {
fraseUsuario[i] = malloc(max_string_len * sizeof(char));
if(fraseUsuario[i] == NULL) { // check for NULL
printf("not enough memory\n");
for(j = 0; j < i; j++)
free(fraseUsuario[j]); // free memory before returning
free(fraseUsuario); // free memory before returning
return -1;
}
if(fgets(fraserUsuario[i], max_string_len, stdin) == NULL) {
// reading string failed
*fraserUsuario[i] = '\0'; // empty string
}
}
for(i = 0; i < 3; i++) {
printf("%s\n", fraseUsuario[i]);
free(fraseUsuario[i]); // free memory allocated for strings
}
free(fraseUsuario); // free memory allocated for pointers to strings
fraseUsuario = NULL;
When you call free on a memory address which you got by a call to malloc, the memory block is returned to the free pool on the heap. This memory block can then later be reused by malloc. Once you free memory, you have given up your ownership of it. It no longer belongs to you and attempting to use it is illegal and will result in undefined behaviour and likely segfault.
You only allocate memory for one char* but use three.
To fix this do:
#define STR_MAXIMUM (3)
...
size_t length = 100, i = 0; /* No need to use a signed type.
size_t is meant as index and size type. */
char ** fraseUsuario = malloc(STR_MAXIMUM * sizeof(*fraseUsuario));
for (i = 0; i < STR_MAXIMUM; ++i)
{
fraseUsuario[i] = malloc(length * sizeof(*fraseUsuario));
...
Also add error checking to system calls.
Also^2: Do not use gets() as there is no way for the compiler or the machine to prevent the buffer passed in from overflowing. Use fgets() instead.
fgets(fraseUsuario[i], length, stdin);

how to find the new size of array of pointer to string

In the main method , i am creating an array of pointers to string
in the add method i am reallocating the array size and adding x elements which i dont know
while coming back to main how can i know the new size of the array , i mean the number of elements int the array ?
Here is my code .. (it has some bugs)
#include <stdio.h>
void add(char ***x);
int main()
{
char **s;
s = (char **) malloc(sizeof(char *));
int i;
add(&s);
for( i=1;i<=?????(**find the new size of the array** );i++)
puts(*s[i]);
return 0;
}
void add(char ***x)
{
- ** // alter arry add x random datas to the array of string pointer**
/*
s[1]="Hello";
s[2]="Need";
s[3]="a help";
s[4]="and help";
s[5]="for the help";
*/
char **data;
int i = 0;
for (i = 1; i <= 5; i++)
{
data = (char **) realloc(*x, 1 * sizeof(char *));
data[i] = (char *) malloc(i * sizeof(char *));
strcpy(data[i], "first");
}
}
can some one please point and fix the bug in the code..
(Sidenote:
can some one please point and fix the bug in the code..
hey, isn't that what debuggers are for?)
Long story short, keep track of it manually:
char **func_that_reallocs(char **ptr, size_t *sz)
{
char **tmp = realloc(ptr, new_size * sizeof(*ptr));
*sz = new_size;
return tmp;
}
And please do not cast the return value of malloc()!
Always add one entry more to the array as needed and set this additional last entry to NULL.
Then write a function which scans the array until it find this NULL-pointer and return the number of entries counted up until then and you are done.
It's the same concept as for a C-"string", with the only difference of using a NULL instead of '\0' as (array-)terminator.
Some people call this last element also the "stopper"-element.
The positive thing about this approach is, one does not have to keep the array's size in a different variable, which might get out of sync with the real size of the array: The size is implicitly given by the array itself.

how to initialize the array of pointers to a structure to zero

I am allocating memory for array of pointers to structure through malloc and want to initialize it with zero like mentioned below . Assuming the structure contains member of type int and char [] (strings) ? so how can i zero out this struct.
Code : suppose i want to allocate for 100
struct A **a = NULL;
a = (struct **)malloc(sizeof( (*a) * 100);
for(i=1; i < 100; i++)
a[i] = (struct A*)malloc(sizeof(a));
Also please explain me why is it necessary to initialize with zero .
Platform : Linux , Programing language : C
I know we can use memset or bzero . I tried it bt it was crashing , may be i was noy using it properly so pls tell me the correct way .
Use of calloc would be most in line with the example above.
First, C arrays are zero-based, not one-based. Next, you are allocating only enough space to hold one pointer, but you are storing 100 pointers into it. Are you trying to allocate 100 As, or are you trying to allocate 100 sets of 100 As each? Finally, the malloc inside your loop allocates space for the sizeof a, not sizeof (struct A).
I'll assume that you are trying to allocate an array of 100 pointers to A, each pointer pointing to a single A.
Solutions: You could use calloc:
struct A **a;
/* In C, never cast malloc(). In C++, always cast malloc() */
a = malloc(100 * sizeof( (*a)));
for(i=0; i < 100; i++)
a[i] = calloc(1, sizeof(struct A));
Or, you could use memset:
struct A **a;
a = malloc(100 * sizeof(*a));
for(i = 0; i < 100; i++) {
a[i] = malloc(sizeof(struct A));
memset(a[i], 0, sizeof(struct A));
}
You ask "why is it necessary to initialize with zero?" It isn't. The relevant requirement is this: you must assign a value to your variables or initialize your variable before you use them for the first time. That assignment or initialization might be zero, or it might be 47 or it might be "John Smith, Esq". It just has to be some valid assignment.
As a matter of convenience, you might choose to initialize all of your members of struct A to zero, which you can do in one single operation (memset or calloc). If zero is not a useful initial value for you, you could initialize the structure members by hand, for example:
struct A **a;
a = malloc(100 * sizeof(*a));
for(i = 0; i < 100; i++) {
a[i] = malloc(sizeof(struct A));
a[i]->index = i;
a[i]->small_prime = 7;
strcpy(a[i]->name, name_database[i]);
}
As long as you never refer to the value of an uninitialized and unassigned variable, you are good.
You can use memset() to set the whole array to 0
OTOH,
a = (struct **)malloc(sizeof( (a*)));
for(i=1; i < 100; i++)
a[i] = (struct*)malloc(sizeof(a) * 100);
is wrong, because you have just created one element of a * but in the next line when the loop goes to 2nd iteration, it will access illegal memory. So to allocate 100 elements of a *, your first malloc() should be as follows
a = (struct **)malloc(sizeof(a *) * 100);
The correct code (including error handling) would more or less will look as follows:
if ((a = (struct **)malloc(sizeof(a*) * 100)) == NULL) {
printf("unable to allocate memory \n");
return -1;
}
for(i=0; i<100; i++) {
if ((a[i] = (struct*)malloc(sizeof(a) * 100)) == NULL) {
printf("unable to allocate memory \n");
return -1;
}
memset(a[i], 0, 100);
}
or as an alternative to malloc() and memset(), you can use calloc()
You dont need many malloc's, one calloc is enough:
int i;
struct A **a = calloc(100,sizeof**a+sizeof*a),*mem=a+100;
for(i=0;i<100;++i)
{
a[i]=&mem[i];
}
...
free(a); /* and you only need ONE free */

How much memory do I need to allocate for an array of X strings of 50 characters?

I need to make an array of strings for a program in one of my CS classes. We are to just assume that the length of all the strings is no more than 50 (this accounts for the null character).
I need use malloc() or calloc() to allocate the proper amount of memory for the array, but I am new to C and I don't really know how to use those functions.
The real question I guess is how much memory to I need do allocate for an array of x strings of 50 characters.
Assuming type char, at minimum you will need X * sizeof(char) * 50.
If you are doing all of these allocations separately, there will be overhead for each allocation. So the total amount of memory in this case will be higher.
This overhead is unspecified and can be fairly large.
But I wouldn't worry about that for a homework assignment. I can't imagine the problem needing enough memory to possibly run your system out.
\0 is called the termination character for strings.
What you need is array of char pointers.
char *strArrayPtr[X]; // X needs to be a compile time constant.
// C99 supports variable length arrays too.
Now each index holds pointer to an array that is allocated by malloc(50);
Example:
#include <stdlib.h>
#include <stdio.h>
int main() {
char *ar[2] ;
ar[0] = "Hello"; // This needs to malloced memory in your case
ar[1] = "World!"; // i.e., ar[0] = malloc(50);
printf("%s", ar[0]);
return 0;
}
If you want to make a variable-sized array of fixed-size strings:
char **arr = calloc(len, 50 * sizeof(char));
Don't forget to free the memory!
for(unsigned long i = 0; i < len; ++i)
free(*arr++);
You're not going to be dynamically pushing elements, are you? If so, we're going to have to get a bit more complicated. (I'd add a StringArray::capacity, to speed up push, but I don't want to overcomplicate things... Seeing as how I suck at C, if you look at the comments below. ;))
struct StringArray
{
char** arr;
unsigned long len = 0;
};
StringArray StringArray_init(char** arr = NULL, unsigned long len = NULL)
{
StringArray a;
a.arr = arr;
a.len = len;
return(a);
}
void StringArray_push(StringArray *a, char* str)
{
if(len == 0)
{
a.arr = StringArrayInit(malloc(sizeof(char*)), 1);
}
else
{
a.len++;
}
a.arr = realloc(a.arr, a.len * sizeof(char*));
a.arr[a.len - 1] = malloc((strlen(str) + 1) * sizeof(char));
strcpy(a.arr[a.len - 1], str);
}
void StringArray_free(StringArray a)
{
for(unsigned long i = 0; i < a.len; ++i)
free(a.arr[i]);
}
StringArray szArr = StringArray_init();
StringArray_push(&szArr, "This is a string.");
StringArray_free(szArr);
It's a heck lot easier with C++. :)
std::vector<std::string> arr;
arr.push_back("This is a string.");

Resources