How to create a dynamic array of strings in C? - c

I want to make an array of strings in which I don't have a fix lenght for every string. How do i do it?
This is my code:
char **a;
int n, m;
scanf_s("%d %d", &n, &m);
a = (char**)malloc(n*sizeof(char*));
for (int i = 0; i < n; i++)
a[i] = (char*)malloc(m*sizeof(char));
for (int i = 0; i < n; i++)
for (int j = 0; j < m;j++)
scanf_s(" %c", &a[i][j])
I have to input an array of words and i don't know the lenght for them. In this code I can input only words of a certain lenght and I want to change that.

An example of what #Daniel says is:
int NumStrings = 100;
char **strings = (char**) malloc(sizeof(char*) * NumStrings);
for(int i = 0; i < NumStrings; i++)
{
/*
Just an example of how every string may have different memory allocated.
Note that sizeof(char) is normally 1 byte, but it's better to let it there */
strings[i] = (char*) malloc(sizeof(char) * i * 10);
}
If you don't need to malloc every string at the beginning, you can do it later. If you need to change the number of strings allocated (do a realloc to strings), then it might be slightly more complicated.

Allocate an array of strings char ** mystrs = malloc(numstrings * sizeof(char *)). Now mystrs is an array of pointers. Now all you need to do is use malloc for each string you want to add.
mystrs[0] = malloc(numchars +1 * sizeof(char)). // add extra char for null character
Then you can copy the string data with strcpy.
strcpy(mystrs[0], "my string")

Related

My program crashes when using realloc in C

#include <stdio.h>
#include <stdlib.h>
char **Names;
int size = 2; //Minimum size for 2D array
void main() {
int i;
Names = (char **)malloc(size * sizeof(char *)); // First initaliaion of 2D array in heap
for (i = 0; i < size; i++)
Names[i] = (char *)malloc(20 * sizeof(char));
printf("\nenter");
for (i = 0; i < size; i++)
scanf("%s", Names[i]);
while (1) {
size++;
Names = (char **)realloc(Names, size * sizeof(char *)); //Dynamic allocation of 2D aray
for (i = 0; i < size; i++)
Names[i] = (char *)realloc(Names[i], 20 * sizeof(char));
i = size - 1;
printf("\nenter");
scanf("%s", Names[i]);
for (i = 0; i < size; i++)
printf("\n%s", Names[i]);
}
}
It doesn't crash immediately it depends on the "size" I initialized.
It crashes after 5 allocations for me.
I tried adding free function but it did not seem to help.
After this memory reallocation
size ++;
Names= (char**)realloc(Names,size*sizeof(char *));
the last pointer pf the array of pointers has an indeterminate value because it was not initialized.
As a result the call of realloc for the last pointer in this loop
for (i=0; i<size; i++)
Names[i] = (char*)realloc(Names[i],20*sizeof(char));
invokes undefined behavior.
Before executing the loop you need to initialize the last pointer at least like
Names[size-1] = NULL;
In fact there is no sense to use the for loop because what you need is to allocate memory for the newly added pointer. The allocated memory pointed to by the early created pointers is not being changed in size.
So instead of
for (i=0; i<size; i++)
Names[i] = (char*)realloc(Names[i],20*sizeof(char));
you could just write
Names[size-1] = malloc( 20 * sizeof( char ) );
Pay attention to as you have an infinite loop then the memory reallocation sooner or later can fail.
Also according to the C Standard the function main without parameters shall be declared like
int main( void )

dynamically create multiple character array at runtime

I need to create character array at runtime because question input goes like this:
1. The first line contains , N the number of strings.
2. The next N lines each contain a string.
I tried creating 2-D array but it didn't work.
int main() {
int n,count;
scanf("%d",&n);
for(int i=0; i<n; i++){
char* arr[i]= char*(malloc(sizeof(char)));
}
return 0;
}
Do something like this:
#define STRINGSIZE 30;
int main() {
int n,count;
scanf("%d",&n);
char **arr;
arr = malloc(sizeof(char*) * n);
for(int i=0; i<n; i++){
arr[i]= malloc(sizeof(char) * STRINGSIZE);
}
return 0;
}
Explanation:
In C, you have pointers to access array. For a multidimensional array with variable lengths, its common to have pointer to pointers. So char **arr; arr = malloc(sizeof(char*) * n); means that you're creating an array of pointers to char. Then you need to call malloc for each of these pointers to allocate memory for each string.
Of course, you do not need to use a constant for string sizes. You can use a variable instead, and you can use different sizes for each string.
Note:
To avoid problems in the future if you want to change the array to an int array instead, do like this and you do not have to worry about changing on more places:
char **arr;
arr = malloc((sizeof a[0]) * n);
for(int i=0; i<n; i++){
arr[i]= malloc((sizeof a[0][0]) * STRINGSIZE);
}
Also, do not cast malloc
And as kkk pointed out in the comments. Check return values.
arr = malloc(sizeof(char*) * n);
if (NULL == arr) {
perror("Could not allocate memory");
exit(EXIT_FAILURE);
}

Trouble Resizing a 2D Array in C

I have a project where I create a 2D char array that stores words, with the option to add more words, and then resize the array when necessary. I'm getting a variety of errors as I try to play with it and fix it so now I think I need some extra eyes on my code. I'm specifically looking for anything that obviously stands out as an incorrect or troublesome way of allocating memory or initializing an array.
The error I am getting specific to this code says "free(): invalid pointer" and leads to a SIGABRT. Below is my code.
Here is my resize function.
char ** resize_array(char **array)
{
int i;
char** tmp = malloc(2 * sizeof(*array));
int j;
for(j = 0; j < (2 * sizeof(*array)); j++)
tmp[j] = malloc(2 * sizeof(*array));
for(i = 0; i < (sizeof *words); i++)
{
strcpy(tmp[i], words[i]);
}
for(i = 0; words[i] != NULL; i++)
free(words[i]);
free(words);
return tmp;
}
Here is my resize function being implemented
int len;
len = (sizeof words);
if(upperbound > len) //upperbound keeps track of the word count
//and resizes the array
{
char **tmp = resize_array((char **) words);
int i;
for(i = 0; i <= upperbound; i++)
strcpy(words[i], tmp[i]);
}
And finally here is the "words" array as it is initially initialized.
char words[14][50];
I'm using VI and running everything on Ubuntu just fyi. Thanks in advance for everyones help!
Inside the resize_array function, you can't determine the previous size of the array using only a pointer to it.
The call to malloc
malloc(2 * sizeof(*array))
requests an allocation twice the size of a pointer to a char (only 16 bytes on a 64bit machine).
This is the first problem you need to fix.

Dynamically allocate a string matrix in C

I'm trying to read a map from a text file and create a string array according to the number of rows and columns in the map. Every cell in the grid is a 2 character string.
For instance,
**--**--**--
--**--**--**
should create a 2*6 matrix. The number of rows and columns are ROWS and COLS respectively. I used
char ***map = malloc(ROWS * sizeof(char *));
for (i = 0; i < ROWS; i++)
{
map[i] = malloc(COLS * sizeof(char) * 2);
}
But when I try to use a map[x][y], it will segfault.
char ***map; could be interpreted as an "Array of arrays of strings", so the inner array actually contains char pointers. Therefore, your loop needs to look like this:
for(i = 0; i < ROWS; i++) {
int j;
map[i] = malloc(COLS * sizeof(char*));
for(j = 0; j < COLS; j++) map[i][j] = malloc(3 * sizeof(char)); // 3 chars because a string has to be terminated by \0
}
Alternatively, you could declare map as char **map, then your initialization code would work, but then you'd need to use map[i][j] and map[i][j+1] to access the elements of the individual cells.
It could look like this:
int i, j, ROWS = 2, COLS = 6;
char ***map = malloc(ROWS * sizeof(char **));
for (i = 0; i < ROWS; ++i)
{
map[i] = malloc(COLS * sizeof(char*));
for (j = 0; j < COLS; ++j)
map[i][j] = malloc(2 * sizeof(char));
}
Note that 2 chars allow you to store these characters, but it could cause you some troubles if you are going to work with them as a string (printf("%s, strcpy ...). In that case I would rather allocate memory for 3 chars so that terminating character can be stored as well.
Also note that you should clean this memory once it is allocated and cleaning should be done in reverse order according to allocation. It could look like this:
for (i = 0; i < ROWS; ++i)
{
for (j = 0; j < COLS; ++j)
free(map[i][j]);
free(map[i]);
}
free(map);
Hope this helps.
It needs to be
char ***map = malloc(ROWS * sizeof(char**));
for (i = 0; i < ROWS; i++)
{
map[i] = malloc(COLS * sizeof(char*));
for (int j=0; i<COLS; ++j)
map[i][j] = malloc(3*sizeof(char);
}
Edit: As pointed out in another answer and a comment, should be 3 not 2 malloc'ed chars.
The first line should be:
char **map = malloc(ROWS * sizeof(char *));
As a rule of thumb, add one * to the return type of malloc(). If you allocate an array of five ints with malloc(5 * sizeof(int)) then you would get back an int *.
Or, you can think of each * as adding a dimension—char * is a 1-D array of characters, and char ** is a 2-D array.
If you want 2D array, way do you declare map as char***? Change it to char**.
(If I misunderstoop, and you want 2D array of char*, you should change the allocation, to use sizeof(char**) and sizeof(char*), and allocate memory to the string separately.)
Edit: If you know the size of the map when you declare it, make it char map[ROWS][COLS][2];
If you don't (or you want to simply pass it to another functions), you can declare it as char (**map)[2], and keep your allocations as they are.
(Change the 2 to 3 if you want to terminate them by \0 (To print it, for example))

How can I write a string into a two dimensional array in C?

May I know how I can a write a character string into a 2D character array?
I need to read every character in the string and put it into a 2D array.
For example:
char string[10];
I want to write all the characters in the string into a 2D array.
That means, when I read array[0][0], I should get the first character.
Update:
suppose my string is "GOODMORN"
then the 2D array should be look like this..
0|1|2|3
0 G|O|O|D
1 M|O|R|N
First, make sure array[0] is big enough to hold your string. Second, use memcpy or strncpy to copy the bytes of string into array[0].
If you need to process and address each character individually, you can start by doing what memcpy does, but in a for loop:
#define NUM_ARRAYS 2
#define LENGTH 4
char *string = "GOODMORN";
for (arr = 0; arr < NUM_ARRAYS; arr++)
{
for (idx = 0; idx < LENGTH; idx++)
{
array[arr][idx] = string[idx + (arr * LENGTH)];
}
}
A sample program I just wrote for you to play with and see if this is what you want.
The important part is where the loops enter the game, dividing the strings character by character.
There are a lot of improvements that can be done (strncpy, the input variable being dynamic, MEMORY FREES, etc), but this is up to you.
Edit: The strncpy modification was just posted by rubber boots.
int main()
{
char A[12] = "Hello World", **B;
int B_LEN = strlen(A) / 2 + 1;
B = (char**)malloc(2 * sizeof(char*));
B[0] = (char*)malloc(B_LEN * sizeof(char));
B[1] = (char*)malloc(B_LEN * sizeof(char));
int i, j;
for (i = 0; i < 2; i++) {
for (j = 0; j < B_LEN; j++) {
B[i][j] = A[B_LEN * i + j];
}
B[i][j] = '\0';
}
printf("%s", B[0]);
printf("[END]\n");
printf("%s\n", B[1]);
printf("[END]\n");
return 0;
}
Obs.: The output must be like
Hello [END]
World[END]
The tag is to show you wether there are spaces, i.e., where exactly the division happened.
Disclaimer: I didn't really understand what the question is about ;-)
you could simply copy the string into a location pointed to by the
array constant for the 2D array:
...
char array[2+1][4];
memcpy((void *)array, TEXT, sizeof(TEXT));
...
But this wouldn't yield auto-sizeable arrays. Maybe you think of the following:
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <stdio.h>
char **matrixify(char text[], int vert, int horiz)
{
int i=0;
char **m = (char **)calloc(vert, sizeof(char*));
do m[i] = text + i * horiz; while(i++ < vert);
return m;
}
int main()
{
int x, y;
/* char t[] = "this is a really long text with many words and stuff"; */
char t[] = "GOODMORN";
int edge = 1+(int)sqrt((double)strlen(t)); /* make a square from text */
/* int vert = edge, horiz = edge; */ /* Auto size detection */
int vert = 2, horiz = 4;
char *textbuf = (char *)calloc(vert, horiz); /* not always 0-terminated */
char **matrix = matrixify(strncpy(textbuf, t, vert*horiz), vert, horiz);
for(y=0; y<vert; y++) {
for(x=0; x<horiz; x++) printf("%c ", matrix[y][x]);
printf("\n");
}
/* prints:
G O O D
M O R N
through matrix[i][j] */
return 0;
}
which leads to your memory layout but looks complicated
for the problem state, but it's C ...
regards
rbo

Resources