How to dynamically allocate and reallocate char arrays in C program? - arrays

I'm writing a card game program and currently, I'm trying to create global char* arrays to represent a player 1 hand and a player 2 hand. I want to use malloc if the arrays have not been initialized yet and realloc later in the game in order to deal into them again. I have a function called dealCards which takes the deck of cards and the number to deal out as arguments. Within I want to be able to reallocate memory to the player arrays with each call depending on the number of cards to deal. So far I tried to test if the arrays were NULL and to use malloc and if not, use realloc, but I got errors of my conditions always equalling false and true therefore the would not test correctly. My current approach which still isn't working is to malloc a single char in the first index of each array, then reallocate in my function. But this is returning an error that reallocation has not occurred. So essentially how can I dynamically create two char* arrays, and then reallocate as needed on a function call?
Deal cards function
int dealCards(char *(*deck)[13], int numCardsToDeal)
{
char *player1Hand = realloc(player1Hand, numCardsToDeal / 2 * (4 * sizeof(char)));
char *player2Hand = realloc(player2Hand, numCardsToDeal / 2 * (4 * sizeof(char)));
//If number of cards passed in is greater than whats left in deck
if (numCardsToDeal > cardsRemaining)
{
printf("Number of cards to deal exceeds remaining deck. Remaining deck will be dealt.");
numCardsToDeal = cardsRemaining;
}
for (int i = 0; i < numCardsToDeal;)
{
player1Hand[i] = *deck[placeInDeck / 13][i];
printf("%c", player1Hand[i]);
i++;
if (i == numCardsToDeal)
{
break;
}
player2Hand[i] = *deck[placeInDeck / 13][i];
printf("%c", player2Hand[i]);
i++;
}
return numCardsToDeal;
}
My current attempt at initially using malloc
char **player1Hand;
char **player2Hand;
void initializePlayers(void)
{
char **player1Hand = malloc(sizeof(*player1Hand));
char **player2Hand = malloc(sizeof(*player2Hand));
for (int i = 0; i < 1; i++)
{
player1Hand[i] = malloc(sizeof(char));
player2Hand[i] = malloc(sizeof(char));
}
}
If any more info is needed please let me know, thanks.

Related

Array of pointers in C with easy iteration

Recently I was pondering over this question: how to make an easier way to iterate over an array of pointer in C.
If I create an array of string in C, it should look like this right?
int size = 5;
char ** strArr = (char **) malloc(sizeof(char *) * size);
if (strArr == NULL) return;
But the problem is, when you want to iterate over this array for some reason (like printing all values inside it), you have to keep track of its current size, storing in another variable.
That's not a problem, but if you create lots of arrays, you have to keep track of every single one of their sizes inside the code. If you pass this array to another function, you must pass its size as well.
void PrintValues (char ** arr, int size) {
for (int i = 0; i < size; i++)
printf("%s\n", arr[i]);
}
But when iterating over a string, it's different. You have the '\0' character, which specifies the end of the string. So, you could iterate over a string like this, with not need to keep its size value:
char * str = (char *) malloc(sizeof(char) * 4);
str[0] = 'a';
str[1] = 'b';
str[2] = 'c';
str[3] = '\0';
for (int i = 0; str[i] != '\0'; i++)
printf("%c", str[i]);
printf("\n");
Now my question:
Is it ok or morally right to allocate +1 unit in an array of pointers to maintain its tail as NULL?
char ** strArr = (char **) malloc(sizeof(char *) * (5 +1);
if (strArr == NULL) return;
strArr[0] = PseudoFunc_NewString("Car");
strArr[1] = PseudoFunc_NewString("Car#1");
strArr[2] = PseudoFunc_NewString("Car#2");
strArr[3] = PseudoFunc_NewString("Tree");
strArr[4] = PseudoFunc_NewString("Tree#1");
strArr[5] = NULL; // Stop iteration here as next element is not allocated
Then I could use the NULL pointer to control the iterator:
void PrintValues (char ** arr) {
for (int i = 0; arr[i] != NULL; i++)
printf("%s\n", arr[i]);
}
This would help me to keep the code cleaner, though it would consume more memory as a pointer size is larger than a integer size.
Also, when programming with event-based libraries, like Gtk, the size values would be released from the stack at some point, so I would have to create a pointer to dynamically store the size value for example.
In cases like this, it ok to do this? Or is it considered something bad?
Is this technique only used with char pointers because char type has a size of only 1 byte?
I miss having a foreach iterator in C...
Now my question: Is it ok or morally right to allocate +1 unit in an array of pointers to maintain its tail as NULL?
This is ok, the final NULL is called a sentinel value and using one is somewhat common practice. This is most often used when you don't even know the size of the data for some reason.
It is however, not the best solution, because you have to iterate over all the data to find the size. Solutions that store the size separately are much faster. An arrays of structs for example, containing both size and data in the same place.
Now my question: Is it ok or morally right to allocate +1 unit in an array of pointers to maintain its tail as NULL?
In C this is quite a common pattern, and it has a name. You're simply using a sentinel value.
As long as your list can not contain null pointers normally this is fine. It is a bit error-prone in general however, then again, that's C for you.
It's ok, and is a commonly used pattern.
As an alternative you can use a struct, in there you can create a size variable where you can store the current size of the array, and pass the struct as argument. The advantage is that you don't need to iterate through the entire array to know its size.
Example:
Live demo
#include <stdlib.h>
#include <stdio.h>
typedef struct
{
char **strArr;
int size;
} MyStruct;
void PrintValues(MyStruct arr) //pass the struct as an argument
{
for (int i = 0; i < arr.size; i++) //use the size passed in the struct
printf("%s\n", arr.strArr[i]);
}
int main()
{
// using the variable to extract the size, to avoid silent errors
// also removed the cast for the same reason
char **strArr = malloc(sizeof *strArr * 5);
if (strArr == NULL) return EXIT_FAILURE;
strArr[0] = "Car";
strArr[1] = "Car#1";
strArr[2] = "Car#2";
strArr[3] = "Tree";
strArr[4] = "Tree#1";
MyStruct strt = { strArr, 5 }; // initialize the struct
PrintValues(strt); //voila
free(strArr); // don't forget to free the allacated memory
return EXIT_SUCCESS;
}
This allows for direct access to an index with error checking:
// here if the array index exists, it will be printed
// otherwise no, allows for O(1) access error free
if(arr.size > 6){
printf("%s\n", arr.strArr[6]);
}

C - (malloc, calloc, or static) 2d char array returned from function

I've been on the site for hours now and I read a lot of new techniques and programmed defined functions,but I'm still a little confused on how to apply it to my own program. I trying to start slow and build a checkers game. So first I created a function to create a Board. Of course i researched and read that C doesn't easily allow for you to return char arrays from functions. So I read up on memory allocation using malloc or calloc.
So my first mistake...
void printBoard(char arr[9][19]);
int makeMove(char arr[11][23], int king, struct player P, char player);
char *createBoard();
char Rows[8]="ABCDEFGH";
int main()
{
int x, y;
int isKing = 1;
char checkerBoard[9][19];
checkerBoard[9][19] = createBoard();
printBoard(checkerBoard);
/* ... */
}
and then...
void printBoard(char array[9][19])
{
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 19; j++)
printf("%c", array[i][j]);
}
printf("\n");
};
char * createBoard()
{
// where I put code
return checkerBoard[9][19];
}
I purposely left out the code inside createBoard() it was a lot. So when using void *malloc(size_t size), I know i need to specify the bytes in size like 4 * sizeof(char)but doesn't the size the array go in there also? Also, would changing the checkerBoard array to static be better?
Its great that you are reading about arrays in C. You mentioned in your question that you read that "C doesn't allow you to easily return arrays from functions". In C, when you declare a statically sized array inside of a function, that array in memory exists on the stack. Every function has it's own stack, so when you return from a function, that memory can be reused again.
When you allocate space with malloc and calloc, that allocates space on the heap. Here is an article with more information: Stack Vs Heap.
Now onto your checkerboard issue, what you want is an array of arrays. You can think of each square on the checkerboard as being an individual character. Let's say our checkerboard had one row.
char * row_zero = malloc(sizeof(char) * 15); //row_zero has a length of 15
Checkerboards obviously have more than one row though, what about 9?
char * row_zero = malloc(sizeof(char) * 15);
char * row_one = malloc(sizeof(char) * 15);
.
.
char * row_eight = malloc(sizeof(char) * 15);
While you can do this, it will be incredibly messy. So instead of creating individual rows, you can simply have a pointer to an array of pointers.
char ** my_checkerboard = malloc(sizeof(char*) * 9); //has 9 rows.
I will let you figure out how to finish making your board.

String array of n dimensions - c

I want to know how to create a dynamic array of 2 strings per array. And I'm not sure how. I know how to create an array of strings, but not one of "n" dimensions, and i want to know how.
Here are some parts of my code, which is just currently an array of strings:
First I declared my array inside an struct:
typedef struct{
char bloqueCedula[7];
short bloqueDia;
char **bloqueLibrosPrestados;//This is the array i want to modify
}RegistroControl;
then I initialize it on my first registration:
void primerRegistro(RegistroArchivo regArch, RegistroControl *regControl) {
strcpy(regControl->bloqueCedula, regArch.cedula);
regControl->bloqueDia = regArch.dia;
regControl->bloqueLibrosPrestados = malloc(cont * sizeof(regControl->bloqueLibrosPrestados));
regControl->bloqueLibrosPrestados[0] = malloc(7 * sizeof(char));
strcpy(regControl->bloqueLibrosPrestados[0], regArch.codigoLibro);
imprimirCabecera();
//printf("%s\n", regControl->bloqueLibrosPrestados[cont-1]);
}
In the code above I made each string of a length 7, because I already know the length of what I need to copy on it, which is 6.
This is how I kept making it grow:
void procesarRegistro(RegistroArchivo regArch, RegistroControl *regControl) {
cont++;
regControl->bloqueLibrosPrestados = realloc(regControl->bloqueLibrosPrestados,cont * sizeof(regControl->bloqueLibrosPrestados));
regControl->bloqueLibrosPrestados[cont-1] = malloc(7 * sizeof(char));
strcpy(regControl->bloqueLibrosPrestados[cont-1], regArch.codigoLibro);
printf("%s\n", regControl->bloqueLibrosPrestados[cont-2]);
}
I want to know how to add another string of 2 length next to the one that is 7 length. This codes are parts of a code that reads from a file until it reaches EOF, that's why I used a counter which is "cont".
You have a char**.
Suppose a. Allocate some memory to a.
a= malloc(sizeof(char*)*10);
if( a == NULL)
{
fprintf(stderr,"%s","error in malloc");
exit(1);
}
Now for each of the position of a you do the same thing only this time it is for char.
a[i]= malloc(sizeof(char)*100);
if( a[i] == NULL)
{
//...
}
Free them when done.
free(a[i]); //for each i.
free(a);
a=NULL;
Now this is 2 dimension
Now I don't know when you need more than this. This can always be extended.
char *** aa; But it is not needed. {read this}
If you need it then you should think over your data representation.
Theoretical idea for N dimensional strings
For n dimensional you can do this:-
char **...n...** complicated= malloc(sizeof(char**...n...>**)*N1);
// malloc check
for(int i=0;i<N1;i++)
complicated[i]= malloc(sizeof(char**...(n-1)...**)*N2);
...

Manipulation of arrays of strings in C

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 *))))

How to declare an array with an arbitrary size

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.

Resources