Creating a 2D string array in C - arrays

So basically I am trying to read from a huge text file and need to store the data in a 2D string array in C. But I am getting a segmentation fault every time.
Here is the code I use to create the array:
Y = 3
X = 12
char ***some_array=NULL;
some_array = (char ***)malloc(Y * sizeof(char *));
for (int i=0; i<Y; i++)
for (int j=0; j<X; j++){
some_array[i] = (char **)malloc(X * sizeof(char *));
some_array[i][j] = (char *)malloc(16 * sizeof(char));
}
So technically, I am creating a 3D char array for this means. Am I doing something wrong here?

You need to move the allocation of some_array[i] = (char **)malloc(X * sizeof(char *)); from the inner most loop to the outer loop. Moreover, you should not cast the malloc return value. For the final code:
Y = 3
X = 12
char ***some_array = NULL;
some_array = malloc(Y * sizeof(char *));
for (int i = 0; i < Y; i++){
some_array[i] = malloc(X * sizeof(char *));
for (int j = 0; j < X; j++){
some_array[i][j] = malloc(16 * sizeof(char));
}
}
Alternatively you can create a statically allocated array:
char some_array [X][Y][16];

Error is in your loop:
for (int i=0; i<Y; i++) {
some_array[i] = (char **)malloc(X * sizeof(char *));
for (int j=0; j<X; j++){
some_array[i][j] = (char *)malloc(16 * sizeof(char));
}
}
You are supposed to allocate memory to some_array[i] outside the inner loop.

Related

Dynamic Memory allocation for 2D Arrays in C Language

I am trying to solve a Leetcode problem in C.
https://leetcode.com/problems/pascals-triangle/description/
This is my solution to the problem.
I don't think there's an issue with the solution but dynamically allocating memory for a 2D array is getting very complex. Can someone please help me figure out how to correctly allocate memory dynamically to a 2D array. Updated the code based on BLUEPIXY suggestions, I still seem to be getting runtime error.
/**
* Return an array of arrays.
* The sizes of the arrays are returned as *columnSizes array.
* Note: Both returned array and *columnSizes array must be malloced, assume caller calls free().
*/
int** generate(int numRows, int** columnSizes) {
int i=0,j=0,numColumns =2;
columnSizes = (int **)malloc(numRows * sizeof(int *));
for (i=0; i<numRows; i++)
columnSizes[i] = (int *)malloc( sizeof(int));
int **returnArray = (int **)malloc(numRows * sizeof(int *));
for (i=0; i<numRows; i++)
returnArray[i] = (int *)malloc((i+1) * sizeof(int));
returnArray[0][0] = 1;
*columnSizes =1;
for(i=1;i<numRows;i++)
{
for(j=0;j<numColumns;j++)
{
if(j==0 )
columnSizes[i][j] = returnArray[i-1][j];
else if(j==(numColumns-1))
columnSizes[i][j] = returnArray[i-1][j-1];
else
returnArray[i][j] = returnArray[i-1][j-1] + returnArray[i-1][j];
numColumns++;
}
*(columnSizes+i) = numColumns-1;
}
return returnArray;
}
Problems of new version
(1)
columnSizes = (int **)malloc(numRows * sizeof(int *));
for (i=0; i<numRows; i++)
columnSizes[i] = (int *)malloc( sizeof(int));
should be
*columnSizes = malloc(numRows * sizeof(int));
(※ it is not necessary to cast from void * in C).
(2)
*columnSizes =1;//type of `*columnSizes` is `int *`
should be
**columnSizes = 1;//meant columnSizes[0] = 1; at caller side (main)
(3)
columnSizes[i][j] = returnArray[i-1][j];
...
columnSizes[i][j] = returnArray[i-1][j-1];
should be
returnArray[i][j] = returnArray[i-1][j];
...
returnArray[i][j] = returnArray[i-1][j-1];
because this is typo.
(4)
numColumns++; move to after for(j=0;j<numColumns;j++){ }
(5)
*(columnSizes+i) = numColumns-1;
should be
*(*columnSizes+i) = numColumns-1;//For reasons similar to (2)
The whole fix code:
int** generate(int numRows, int** columnSizes) {
int i=0,j=0,numColumns =2;
*columnSizes = malloc(numRows * sizeof(int));
int **returnArray = (int **)malloc(numRows * sizeof(int *));
for (i=0; i<numRows; i++)
returnArray[i] = (int *)malloc((i+1) * sizeof(int));
returnArray[0][0] = 1;
**columnSizes = 1;
for(i=1;i<numRows;i++)
{
for(j=0;j<numColumns;j++)
{
if(j==0 )
returnArray[i][j] = returnArray[i-1][j];
else if(j==(numColumns-1))
returnArray[i][j] = returnArray[i-1][j-1];
else
returnArray[i][j] = returnArray[i-1][j-1] + returnArray[i-1][j];
}
numColumns++;
*(*columnSizes+i) = numColumns-1;
}
return returnArray;
}
Just do this
int *arr = (int *)malloc(r * c * sizeof(int));
and access the elements like this
int i, j, count = 0;
for (i = 0; i < r; i++)
for (j = 0; j < c; j++)
*(arr + i*c + j) = ++count;
OR
If you have the pointer to the pointer, then you get get some help from this code
int main()
{
int i,j;
int **p;
(p)=(int**)malloc(5*sizeof(int*));
for(i=0;i<5;i++)
*(p+i)=(int*)malloc(4*sizeof(int));
for(i=0;i<5;i++)
for(j=0;j<4;j++)
p[i][j]=2;
for(i=0;i<5;i++)
for(j=0;j<4;j++)
printf("%d",p[i][j]);
}
If all you have to do for your programming exercise is print out the results, why bother with any storage at all? Just use the solution here.
How to efficiently calculate a row in pascal's triangle?
Regarding multi-dimensional arrays and C, there is no native support for such a thing. So you have to build your own using one or more 1-D blocks of storage and tricks to index into that storage.
The simplest thing, which #tanuj-yadav suggested works fine for most 2-d arrays is just allocate a nXm-length block of storage and do very simple index arithmetic arr[i*c+j].
The other common approach is arrays of arrays (aka ragged arrays). Which is just like a list of lists, and are naively done with a malloc on each row (or column).

freeing multidimensional array C

I have this struct called Grid that holds a 2d array of strings. I'v been searching on how to free multidimensional arrays properly and can't seem to find the problem with this procedure as valgrind keeps detecting errors and leaked memory. Thanks in advance!
typedef struct Grid{
int N;
int M;
char ***adj;
}TGrid;
TGrid* emptyGrid(int N, int M){
int i,j;
TGrid *Grid = malloc(sizeof(TGrid));
Grid->N = N;
Grid->M = M;
Grid->adj = malloc(N * sizeof(char ***));
for(i = 0; i < N; i++){
Grid->adj[i] = malloc(M * sizeof(char **));
for(j = 0; j < M; j++){
Grid->adj[i][j] = malloc(10 * sizeof(char *));
}
}
return Grid;
}
void freeGrid(TGrid *Grid){
int i, j;
for(i = 0; i < Grid->N; i++){
for(j = 0; j < Grid->M; j++){
free(Grid->adj[i][j]);
}
free(Grid->adj[i]);
}
free(Grid->adj);
free(Grid);
}
The way you malloc memory is incorrect, proper ways should be:
TGrid* emptyGrid(int N, int M){
int i,j;
TGrid *Grid = malloc(sizeof(TGrid));
Grid->N = N;
Grid->M = M;
Grid->adj = malloc(N * sizeof(char **));
for(i = 0; i < N; i++){
Grid->adj[i] = malloc(M * sizeof(char *));
for(j = 0; j < M; j++){
Grid->adj[i][j] = malloc(10 * sizeof(char));
}
}
return Grid;
}
Note that, Grid->adj[i][j] always points to array of 10 char, you can use this:
#include <stdio.h>
#include <stdlib.h>
typedef struct Grid{
int N;
int M;
char (**adj)[10];
}TGrid;
TGrid* emptyGrid(int N, int M){
int i;
TGrid *Grid = malloc(sizeof(TGrid));
Grid->N = N;
Grid->M = M;
Grid->adj = malloc(N * sizeof(char (*)[10]));
for(i = 0; i < N; i++){
Grid->adj[i] = malloc(M * sizeof(char[10]));
}
return Grid;
}
void freeGrid(TGrid *Grid){
int i;
for(i = 0; i < Grid->N; i++){
free(Grid->adj[i]);
}
free(Grid->adj);
free(Grid);
}
int main() {
TGrid* t = emptyGrid(2,3);
freeGrid(t);
return 0;
}
However, since free receives a void* parameter, there must be something else in your code.
The general structure of your code is fine, but the types under sizeof are wrong. The general idiom for malloc-ing memory looks as follows
T *p = malloc(N * sizeof *p);
or, equivalently
T *p = malloc(N * sizeof(T));
Note that in the latter (type-based) variant there's one less asterisk under sizeof than there's is in the recipient pointer type.
That's exactly how it should be in your case as well
Grid->adj = malloc(N * sizeof(char **));
/* Since `Grid->adj` is `char ***`, you should have `char **` under `sizeof` */
...
Grid->adj[i] = malloc(M * sizeof(char *));
/* Since `Grid->adj[i]` is `char **`, you should have `char *` under `sizeof` */
...
Grid->adj[i][j] = malloc(10 * sizeof(char));
/* Since `Grid->adj[i][j]` is `char *`, you should have `char` under `sizeof` */
If that's not what you need, then there must be something wrong with your types. There's no way to say without knowing your intent.
(And I would suggest you use the first approach to specifying sizeof under malloc - use expressions, not types. That way you won't have to count asterisks.)
However, in real life this specific error would typically only result in over-allocated memory. No out-of-bound access or memory leaks should occur. If valgrind reports such errors, there must be something else at work here as well.
It's difficult to see where the problem is since you haven't posted the code that uses the functions.
I want to point out that the calls to malloc need to be changed.
You have:
Grid->adj = malloc(N * sizeof(char ***));
for(i = 0; i < N; i++){
Grid->adj[i] = malloc(M * sizeof(char **));
for(j = 0; j < M; j++){
Grid->adj[i][j] = malloc(10 * sizeof(char *));
}
}
Those calls need to be changed to:
Grid->adj = malloc(N * sizeof(char **));
for(i = 0; i < N; i++){
Grid->adj[i] = malloc(M * sizeof(char *));
for(j = 0; j < M; j++){
Grid->adj[i][j] = malloc(10 * sizeof(char));
}
}
You can avoid such errors by using a coding style as follows:
Grid->adj = malloc(N * sizeof(*(Grid->adj)));
for(i = 0; i < N; i++){
Grid->adj[i] = malloc(M * sizeof(*(Grid->adj[i])));
for(j = 0; j < M; j++){
Grid->adj[i][j] = malloc(10 * sizeof(*(Grid->adj[i][j])));
}
}
A simpler case that uses the same style:
char* cp = malloc(10*sizeof(*cp));
You are not allocating arrays, you are allocating pointer-based look-up tables. The only reason for doing so is if you wish the individual dimensions to have different lengths (such as in an array of strings). If you don't need that, you should never use pointer-to-pointer tables since they are slow, error-prone and needlessly complex.
To allocate an actual 3D array, you would do like this:
char (*array)[Y][Z] = malloc ( sizeof(char[X][Y][Z] );
...
free(array);
To allocate an array of strings, you would do like this:
char** lookup = malloc ( sizeof( char*[N] ) );
for(size_t i=0; i<N; i++)
{
lookup[i] = ...; // assign pointers to strings
}
...
free(lookup);
As a rule of thumb, whenever your program contains more than two levels of indirection, the program design is most likely bad.

How to compare two strings, which(both of them) are stored in char double pointer?

char ** magazine;
char ** ransom;
*magazine = malloc(sizeof(char*) * m);
for(int magazine_i = 0; magazine_i < m; magazine_i++){
magazine[magazine_i] = (char *)malloc(10240 * sizeof(char));
scanf("%s",magazine[magazine_i]);
}
*ransom = malloc(sizeof(char*) * n);
for(int ransom_i = 0; ransom_i < n; ransom_i++){
ransom[ransom_i] = (char *)malloc(10240 * sizeof(char));
scanf("%s",ransom[ransom_i]);
}
Now I want to compare the string stored in ransom to magazine. How it can be done? Please help
You can use strcmp in a loop:
for (i = 0; i < n; i++) {
if (strcmp(magazine[i], ransom[i]) == 0) {
...
}
}
But if (as the title suggests) ransom is declared as a pointer to pointer to char:
char **ransom;
you don't want the dereference operator *
*ransom = malloc(sizeof(char*) * n);
should be
ransom = malloc(sizeof(char*) * n);

An array of integers and an array of int pointers that point to the first array, does this make sense?

I am experimenting to set up two arrays, let's say array myflags_init and array tripleP; both arrays are two dimenstional, because tripleP is an array of pointers that point to the corresponding index in array myflags_init. Below is my code, and the compiling works fine. I would like to discuss whether this makes sense, as the syntax is a bit crazy to me (e.g. int **tripleP[2] for declaring the two-dimenstional array tripleP of int pointers).
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
int m;
for (m = 0; m < 20; m++)
{
int *myflags_init[2];
myflags_init[0] = (int *) calloc(2, sizeof(int));
myflags_init[1] = (int *) calloc(2, sizeof(int));
int r, k;
for (r = 0; r < 2; r++)
{
for (k = 0; k < 10; k++)
{
myflags_init[r][k] = 0; /* initialize the two-d array to 0 */
}
}
int false_num = 0;
int **tripleP[2];
tripleP[0] = (int **) calloc(10, sizeof(int **));
tripleP[1] = (int **) calloc(10, sizeof(int **));
for (r = 0; r < 2; r++)
{
for (k = 0; k < 10; k++)
{
tripleP[r][k] = &myflags_init[r][k]; /* tripleP pointers point to the corresponding index in myflags_init */
}
}
}
return 0;
}
int **tripleP[2];
tripleP[0] = (int **) calloc(10, sizeof(int **));
tripleP[1] = (int **) calloc(10, sizeof(int **));
That works, but shouldn't be written like this. You want to allocate an array of int*, not int**. However it just so happens that both types have the same size (they are both pointers) and thus this will work anyway. But for clarity replace it with this:
int **tripleP[2];
tripleP[0] = (int **) calloc(10, sizeof(int *));
tripleP[1] = (int **) calloc(10, sizeof(int *));
Also the initialization of myflags_init[0] and myflags_init[1] is wrong, because you allocated for 2 elements for each, but try to initialize 10 of them:
myflags_init[0] = (int *) calloc(2, sizeof(int));
myflags_init[1] = (int *) calloc(2, sizeof(int));
//...
for (k = 0; k < 10; k++)
Also you don't need to set them manually to zero. That is exactly what calloc already does for you (in contrast to malloc).
And the outer for-loop seems rather pointless, not to mention the memory leak, because you keep allocating new memory but never call free.

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

Resources