Dynamic string matrix in C - c

I am having the next problem. I'm trying to create a dynamic matrix of strings which dimensions are defined by the user. The next code I made returns a segmentation fault:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(){
char ***pa = NULL;
int rows, columns , max, i, j = 0;
//Ask dimension
puts("Type number of columns: ");
scanf("%d",&columns);
puts("Type number of rows: ");
scanf("%d",&rows);
puts("Type max string length: ");
scanf("%d",&max);
//Allocate in memory
***pa = (char ***)malloc(rows * sizeof(char**));
for(i=0;i<rows; i++){
pa[i] = (char **)malloc(columns * sizeof(char*));
for(j=0; i<columns;j++){
pa[i][j] = (char)malloc((max+1)*sizeof(char));
}
}
puts("Memory OK");
//Fill the matrix
i = 0;
j = 0;
for(i=0;i<rows;i++){
strncpy(pa[i][j] , "Hello world", max);
for(j=0;j<columns;j++){
strncpy(pa[i][j] , "Hello world", max);
}
}
//Shows the matrix
for(i=0;i<rows;i++){
puts(pa[i][j]);
for(j=0;j<columns;j++){
puts(pa[i][j]);
}
}
//Cleans the matrix
free(pa);
return 0;
}
I know I should check if the returned pointer by malloc is NULL but I didn't included it yet.
The program does not print this so the problem is in the malloc for's
puts("Memory OK");
How can I debug this so I could know what happend? Did I made a mistake while coding it?

I'd recommend you leverage c99 to the fullest, and allocate the entire matrix as a single block. You'll be reducing the fragmentation of your programs memory and making iteration over the matrix more cache friendly:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
int rows, columns , max;
puts("Type number of columns: ");
scanf("%d",&columns);
puts("Type number of rows: ");
scanf("%d",&rows);
puts("Type max string length: ");
scanf("%d",&max);
char (*mat)[columns][max+1] = malloc(rows * columns * (max + 1));
for(int i = 0; i < rows; ++i){
for(int j = 0; j < columns; ++j) {
strncpy(mat[i][j] , "Hello world", max);
}
}
for(int i = 0; i < rows; ++i){
for(int j = 0; j < columns; ++j){
puts(mat[i][j]);
}
}
free(mat);
return 0;
}
Other added bonii:
Removes the complexity involved with allocating your memory. No more nested loops with mallocs
No need to loop for freeing the whole thing, just free the one pointer. You already do that, but in your case it leaks memory.
Cons:
May fail to allocate the entire block for large matrices. Here the fragmented approach may be better.

Change
pa[i][j] = (char)malloc((max+1)*sizeof(char));
into:
pa[i][j] = (char *)malloc((max+1)*sizeof(char));
Also, no need for the outer (first) strncpy in the main.
[EDIT]
Also, the first allocation line ***pa = ... should be pa = .... You want to assign an address to the pointer pa, not de-reference it (***pa de-references the pointer pa that has not been yet initialized).

Thanks to veryone for helping me to solve it. I've learned new things with you.
First of all, I changed this.
pa = malloc(rows * sizeof(char**));
for(i=0;i<rows; i++){
pa[i] = malloc(columns * sizeof(char*));
for(j=0; j<columns;j++){//Here there was an i. That was totally wrong.
pa[i][j] = malloc((max+1)*sizeof(char));
}
}
Now it works and allocates correctly the matrix into de memory.

Related

How to dynamically allocate memory for words stored in an array?

I input words one by one from the screen and send them to an array. I can, of course, immediately allocate large memory for the array, but I would like to allocate memory for this dynamically.
For example I have an array words. First, I allocate a little memory for it char *words = malloc(capacity) , where capacity = 15 for example. ...enter words from the screen... . All allocated memory is full and I allocate more memory for further work char *tmp = realloc(words, capacity*2). Probably,I understand how it works. But I can't figure out how to write it. That is, how to enter these words and send them to an array. Could you describe in detail how I should do this?
Example:
I input words from the screen side left ball rich and at the end I have an array *arr = ["side", "left", "ball", "rich"]
You need to have a arry of pointers where each index stores a word.
Also attention has to be given to release the memory.
Snippet as follows,
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
int size = 3;
char word[30];
char **word_list = malloc(sizeof(word_list) * size);
printf("Enter %d Words\n",size);
for(int i =0; i<size; ++i){
scanf("%30s",word);
int word_size = strlen(word)+1;
word_list[i] = malloc(word_size);
strncpy(word_list[i],word,word_size);
}
printf("\nEntered words are\n");
for(int i=0; i<size; ++i){
printf("%s ",word_list[i]);
}
//resizing the capacity of the array
{
int resize;
printf("\nresize array size to: ");
scanf("%d",&resize);
if(size<resize){
for(int i=size-1; i>=resize; --i)
free(word_list[i]);
}
word_list = realloc(word_list, sizeof(word_list) * resize);
if(resize > size)
printf("Enter %d Words \n",resize-size);
for(int i =size; i<resize; ++i){
scanf("%30s",word);
int word_size = strlen(word)+1;
word_list[i] = malloc(word_size);
strncpy(word_list[i],word,word_size);
}
size = resize;
}
printf("Current words are\n");
for(int i=0; i<size; ++i){
printf("%s ",word_list[i]);
}
//Memory deallocation
for(int i=0; i<size; ++i){
free(word_list[i]);
}
free(word_list);
return 0;
}
DEMO

Allocating memory to 2D array using an array of NULL (c)

thanks for taking the time in reading this.
In my question a "vector" is defined as a 1D dimensional array of integers.
Therefore an array of vectors would be a 2D dimensional array in which every vector can be of a different length.
I'm asked to use:
int** vectors- the 2D array
int size -an integer that represents how many vectors exist inside **vectors
int* sizes-a 1D array of integers that represents the length of the vectors
for example,for:
vectors = {{4,3,4,3},{11,22,33,44,55,66},NULL,{5},{3,33,333,33,3}}.
size is 5 (there are 5 vectors inside vectors).
sizes is {4,6,0,1,5} (4 is the length of the first vector and so on).
size is inputted by the user at the beginning of main() and **vectors&*sizes are dynimacilly allocated with size's value.
I'm asked to write the function:
int init(int ***vectors, int **sizes, int size) which initializes **vectors to be an array of NULLs and *sizes to be an array of zeros.
I came up with this code:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
int init(int*** vectors, int** sizes, int size)
{
int i, k,j;
printf("check\n");
*vectors = (int**)malloc(size * sizeof(int*));
if (*vectors == NULL)
return 0;
for (i = 0; i < size; i++)
{
*(vectors + i) = NULL;
}
printf("check 2\n");
for (k = 0; k<size; k++)
{
if (*(vectors+k) != NULL)
printf("didn't work\n");
else
printf("current is null\n");
}
*sizes= (int*)malloc(size * sizeof(int));
if (*sizes == NULL)
return 0;
for (j= 0; j < size; j++)
{
*(sizes + j) = 0;
printf("%d ", *(sizes + j));
}
printf("\n");
return 1;
}
int main()
{
int size, i;
int** vectors = NULL;
int* sizes = NULL;
printf("\nPlease enter an amount of vectors:\n");
scanf("%d", &size);
printf("%d\n", init(&vectors, &sizes, size));
printf("size is %d now\n", size);
// for (i = 0; i < size; i++)
// printf("%d ", *(sizes+i));
printf("check 3\n");
free(sizes);
free(vectors);
printf("check 4\n");
printf("check 5\n");
return 0;
}
forgot to mention that init returns 0 if it fails to allocate memory and 1 otherwise.
printing the "checks" was so I could see where the program fails.
the problem is that no matter what,after printing the last check (check 5)
the program fails.(Run-Time Check Failure #2)
if anyone could help me understand what I'm doing wrong I would HIGHLY appreciate it.
thanks alot for reading and have an amazing day.
edit:
i also printed the array sizes/vectors inside init just to see if it prints zeros/nulls,i don't actually need to do it.
One problem of OP's code is in the pointer arithmetic. Given:
int ***vectors;
*vectors = malloc(size * sizeof(int*));
This loop:
for (i = 0; i < size; i++)
{
*(vectors + i) = NULL;
}
Would iterate over the next unallocated pointer to pointer to pointer to int, while what the OP needs is
for (i = 0; i < size; i++)
{
*(*vectors + i) = NULL; // or (*vectors)[i] = NULL;
}
The same holds in the following loops, where *(sizes + j) is used instead of *(*sizes + j) (or (*sizes)[j]).

How do we correctly dynamically allocate memory multiple times?

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#define MAX_STRING_SIZE 20
int main() {
/* Enter your code here. Read input from STDIN. Print output to STDOUT */
int N, Q;
int i, j, k, l, m, x;
char **str;
scanf("%d\n", &N);
str = (char **)malloc(sizeof(char *) * N);
for(i = 0; i < N; i++){
str[i] = malloc(MAX_STRING_SIZE * sizeof(char));
scanf("%s",str[i]);
}
printf("%d\n",N);
for(j = 0; j < N; j++){
printf("%s",str[j]);
printf("\n");
}
scanf("%d",&Q);
printf("%d\n",Q);
char **qry_str;
qry_str = (char **)malloc(sizeof(char *) * Q);
for(l = 0; l < Q; l++){
qry_str = malloc(MAX_STRING_SIZE * sizeof(char));
scanf("%s",qry_str[l]);
}
for(m = 0; m < N; m++){
printf("%s",qry_str[m]);
printf("\n");
}
for(k = 0; k < N; k++)
free(str[k]);
free(str);
for(x = 0; x < N; x++)
free(qry_str[x]);
free(qry_str);
return 0;
}
I am new to programming, and I am trying to allocate memory for two 2d strings using malloc function, but when I try to input data for the second string qry_str, (null) appears on the screen, and the program exits.
My question is:
How do we dynamically allocate memory for 2D arrays in C multiple times?
Do I need to free the memory first before using it again? (Though when I try to do that it causes segmentation fault error.)
Is this the problem due to my compiler? (I am using gcc.)
In your second case, you're overwriting qry_str inside the loop, which is not what is intended. You most probably want
for(l = 0; l < Q; l++){
qry_str[l] = malloc(MAX_STRING_SIZE * sizeof(char));
scanf("%s",qry_str[l]);
}
That said, a few suggestion:
You don't need four separate counters i, j, l, m. The first clause of for statement re-assigns the counter to 0 anyway, even if you reuse only one.
sizeof(char) is gurantted to be 1 in C. Instead, you should consider writing the statements like
qry_str[l] = malloc(MAX_STRING_SIZE * sizeof *qry_str));
to make them more robust.
Always check for the return values for scanf() family to ensure success.

efficient way to get numbers from user and fill Matrix

I want to get numbers from user in a single line for example:
2 1 2 3 4
The first number: 2 means that my Matrix should be with size of 2x2 and the next 4 numbers should insert into my Matrix (Matrix dimension should be n²).
Currently I have this:
int dimension, num;
int *mat;
int numcounter = 0;
int i = 0;
int j, k, t;
char temp;
printf("Please enter numbers: ");
do {
scanf("%d%c", &num, &temp);
i++;
if (i == 1)
{
/* Set Matrix dimension. */
dimension = num;
if (dimension < 2)
{
printf("Size must be a valid number");
return 1;
}
else
/* Allocate dimension size. */
mat = (int*)malloc(dimension * dimension * sizeof(int*));
}
else
{
/* Fill Matrix. */
}
} while (temp != '\n' || temp == EOF)
So here I have all the number and now I need to fill my Matrix but instead of put all the numbers inside temp array and then fill my Matrix I wonder how to do that without another memory allocation.
You can do it simply using a VLA. The OP's initial question never mentioned that OP needs to get the input in a line and parse it. I have given that as an answer in the second part. But simply that is not needed. It is not a feasible reason that you have to get the numbers all at once. You can get the size using one scanf and then the elements in another scanf.
scanf("%d", &num);
//Then you know the dimension of the array.
int arr[num][num];
for(size_t i=0;i<num; i++)
for(size_t j =0; j< num; j++)
if( scanf("%d",&arr[i][j]) != 1)
{
fprintf(stderr,"Error in input");
exit(1);
}
Also as you know how many numbers will be read you don't need to continue scanning until you get '\n' or EOF.
Given your case your over complicating things IMHO. As you know the numbers you can get the benefit of VLA.
If you have to get all the numbers in a single line you need to look at 3 functions. fgets() and strtol. Those will help you achieving reading everything in a line and then tokenizing.
To give you a demo of what I said you can do this
#include <stdio.h>
#include <stdlib.h>
#define BUFSIZE 256
int main(void)
{
char line[BUFSIZE];
long temp[BUFSIZE];
int i = 0;
if (fgets(line, sizeof line, stdin) != NULL)
{
const char *ptr = line;
while (*ptr != '\0')
{
char *endptr = NULL;
long val = strtol(ptr, &endptr, 10);
if (endptr != ptr)
temp[i++] = val;
else
break;
ptr = endptr;
}
}
int sz = temp[0];
if( sz <= 0 )
{
fprintf(stderr,"Error in size input");
exit(1);
}
int tempIn = 1;
long arr[sz][sz];
for(size_t i = 0; i < sz; i++)
for(size_t j = 0; j < sz; j++)
arr[i][j]= temp[tempIn++];
for(size_t i = 0; i < sz; i++)
for(size_t j = 0; j < sz; j++)
printf("%ld ",arr[i][j]);
}
In the second code, as you can see fgets has been used which basically read a line and then strtol has been used. As you have mentioned that you will give a single line input of numbers.
Now what we did?
The line scanned and the parsed number by number using strtol. For a brief overview of strtol check this.
Also OP asked for how to use dynamic memory allocation to do the same thing. And there is no way a while loop is needed here. This is redundant. So while modifying I will add the code that will be able to do it much more simpler way.
scanf("%d", &num);
int matIndex = 0;
/* Set Matrix dimension. */
dimension = num;
if (dimension <= 0)
{
printf("Size must be posiitve integer");
return 1;
}
else
{
mat = malloc(dimension * dimension * sizeof *mat);
if ( mat == NULL ){
fprintf(stderr, "%s\n", "Error in malloc");
exit(1);
}
}
// All the numbers will be taken as elements of the dynamically allocated array,
for(size_t i = 0; i < dimension*dimension ; i++)
if( scanf("%d",&mat[i]) == 1){
//ok
}
else{
fprintf(stderr,"Some error occured");
break;
}
When you want to access the i-th row and j-th column element, you can do this mat[i*dimension+j] //equivalent to mat[i][j]
Some useful information:-
Allocating dim*dim memory doesn't let you access the element in the form of mat[i[[j]. Because you allocated a single chunk of memory - you have to calculate the positions explicitly and access the element in the linear array.
You can do all the scanning using scanf() but you need to be careful when having scanf(). But yes you can get this thing done using scanf also.
Also there is another thing to know about. The VLA will have automatic storage duration and limiting the memory you can have use this way. The dynamically allocated memory has much higher limit giving you a scope of having much larger dimensions array.
Note that in dynamic memory allocation you will need to free the allocated memory when you are done working with it.
If you want to use mat[i][j] not mat[i*dim+j] you can consider creating one jagged array.
Few things that you will need:
Reading Suggestion:
How to debug small programs
Beginner's guide away from scanf
Book list
You can use following code:
Note: You can redirect STDIN to your file. See posts available here
#include <stdio.h>
#include <stdlib.h>
int main()
{
int D, i, j;
freopen("testfile.txt","r",stdin);
printf("Ender dimention of matrix: ");
scanf("%d",&D);
int** matrix = malloc(D*D*sizeof(int));
for(i=0; i<D; i++)
{
for(j=0; j<D; j++)
{
printf("Ender element of matrix: ");
scanf("%d",&matrix[i][j]);
}
}
printf("Matrix is: \n");
for(i=0; i<D; i++)
{
for(j=0; j<D; j++)
{
printf("%d ", matrix[i][j]);
}
printf("\n");
}
free(matrix);
return 0;
}

Using scanf to fill out a multidimensional array (C language)

I was wondering how to properly use scanf to fill out a multidimensional array.
Here's my code:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, const char * argv[]) {
int n; //number of rounds
int* sArray; //multidimensional array that holds the scores of both players
int i;
scanf("%d", &n);
sArray = (int*) calloc (n * 2, sizeof(int));
for(i=0; i<n; i++) {
scanf("%d %d", &sArray[i][1], &sArray[i][2]);
}
return 0;
}
It gives me an error, "Subscripted value is not an array, pointer, or vector." Any help would be much appreciated!
A two dimentional array is defined as follows: int sArray[N][M], but since you wanted to work with the dynamic memory I offer you to take a look at a pointer to pointer at int:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int n;
scanf("%d", &n);
int **sArray;
sArray = (int **)malloc(n * sizeof(int *));
int i;
for(i = 0; i < n; i++)
{
sArray[i] = (int *)malloc(2 * sizeof(int));
scanf("%d %d", &sArray[i][1], &sArray[i][2]);
}
return 0;
}
Don't forget to clean-up after you are done with the array.
As mentioned in the commentaries, You don't need to cast the result of malloc if you work with pure c. I did this because my c++ compiler refused to compile it without this cast.
You might need to check errors during a dynamic allocation of the array. Read more here
There are already a lot of good answers here on how to define your dynamic 2D array. But this variant was not yet mentionned, so I put it for the records.
As the last dimension of your array is fixed, you could define your 2D array as follows:
int (*sArray)[2]; //multidimensional array that holds the scores of both players
...
sArray = (int(*)[2]) calloc (n, sizeof(int)*2); // self explaining
In this way, all the elements will be stored contiguously (each n element of the allocated array, is 2 contiguous integers), without the need for an array to arrays.
The rest of your code remains identical. Except that you shoud address sArray[i][0] and ..[1] instead of [1] and [2] and free memory at the end. In C array indexing starts always from 0 and goes to size-1.
Of course, this approach is strictly limited to 2D arrays where the last dimension is fixed.
Live demo with addressing
Usually to fill a bidimensional array you will use two nested for loops.
For example :
int array[2][3] = {0};
for (i = 0; i < 2; i++)
for (k = 0; k < 3; k++)
scanf("%d", &array [i][k]);
You could do this too:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, const char * argv[]) {
int n; //number of rounds
int** sArray = malloc(2 * sizeof(int*)); //multidimensional array that holds the scores of both players
scanf("%d", &n);
sArray[0] = (int*)calloc(n , sizeof(int));
sArray[1] = (int*)calloc(n , sizeof(int));
int i;
for (i = 0; i < n; i++) {
scanf("%d %d", &sArray[0][i], &sArray[1][i]);
}
free(sArray[0]);
free(sArray[1]);
free(sArray);
return 0;
}

Resources