Taking an input through array of pointers - arrays

I learnt about the concept of array of pointers and ragged arrays, but i'm not able to understand why my code isn't working.
#include<stdio.h>
int main(void)
{
int* b[10] ;
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
scanf_s("%d", (*(b+i)+j));
}
}
return 0;
}

There are multiple issues with your code, so I will just post the corrected one with explanations:
int *b[10];
for (int i = 0; i < 3; i++) {
// you need to allocate memory to each pointer inside your array as well
// I have allocated for 3, since you scan 3 integers
b[i] = malloc(3 * sizeof(int));
for (int j = 0; j < 3; j++) {
// use scanf like this, you need the address not the value of variable you are scanning
scanf("%d", (*(b + i) + j));
}
}
You need to include the header file for malloc.
#include <stdlib.h>
Also, don't forget to free the dynamically allocated memory later to avoid memory leaks.

You are declaring an array of pointers:
int* b[10];
you need to allocate memory for each of those pointers, namely:
for (int i = 0; i < 10; i++) {
b[i] = malloc(3 * sizeof(int));
}
From Difference between scanf and scanf_s one can read:
scanf originally just reads whatever console input you type and assign
it to a type of variable.
(..)
scanf_s has an argument(parameter) where you can specify the buffer size and actually control the limit of the input so you don't crash the whole building.
Therefore, what you need is scanf, hence change your code from:
scanf_s("%d", (*(b+i)+j));
to
scanf("%d", (*(b+i)+j));
You should also check the returning value of the scanf function, and free the memory of the dynamically allocated array.
An example of a full running code:
#include<stdio.h>
#include <stdlib.h>
int main(void)
{
int array_size = 3;
int* b[array_size] ;
// Allocate memory for my array
for (int i = 0; i < array_size; i++)
b[i] = malloc(3 * sizeof(int));
int scanf_value = 0;
for (int i = 0; i < array_size; i++)
for (int j = 0; j < 3; j++){
if(scanf("%d", &b[i][j]) != 1){
while(getchar()!='\n'); // clean the input buffer
printf("Invalid Input! Add just numbers\n");
j--;
}
}
// print those elements
for (int i = 0; i < array_size; i++)
for (int j = 0; j < 3; j++)
printf("%d ",b[i][j]);
// lets free the memory
for (int i = 0; i < array_size; i++)
free(b[i]);
return 0;
}

scanf_s takes an address of a variable but you are passing a value. Doesn't your compiler complain? If not, bump up the warning/errors levels. Others already told you that you need to allocate memory for the array pointers to point at. If this was production code remember to free().

Related

How to access a 2d array inside a struct using only pointers

Trying to understand pointers as a beginner in C-
I've got this struct:
typedef struct {
int size; // dimension of array
int **arr; // pointer to heap allocated array
} someStruct;
So I use malloc to generate this struct, and an array, and initialize all the values to zero-
someStruct *m = (someStruct*)malloc(sizeof(someStruct));
m->size = n;
m->arr = (int**)malloc(n * sizeof(int));
// initialize array
for (int i = 0; i < n; i++) {
*(m->arr + i) = (int*)malloc(n * sizeof(int));
// set value to 0
for (int j = 0; j < n; j++) {
*(*(m->arr + i) + j) = 0;
}
}
After this I basically continue to access the array in later stages using the same kind of pointer logic-
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
int num = *(*(m->arr + i) + j);
printf("num: %d\n", num);
}
}
Here's the problem- when I try to use this method of access, I'm clearly not getting the right answer- my print output look like this:
num: -2043774080
num: 22031
num: 0
num: 0
...
num: 0
num: 0
Here's the really weird part- this seeming bug of the 'weird' random numbers only comes when I'm creating and accessing an array of size 5-
I've come to believe that the whole
*(*(m->arr + i) + j)
method of access must be wrong- any help on this would be really useful. Thanks in advance, I apologize if this was already answered, my searching was unable to find it.
You should give complete code, but I think I was able to figure out your intent. You have one glaring problem, and many style issues. Here is what I think your code should look like:
typedef struct {
int size; // dimension of array
int **arr; // pointer to heap allocated array
} MagicSquare;
:
:
// no need to dynamically allocate this, it is small
MagicSquare m;
m.size = n;
m.arr = malloc(n * sizeof(int*)); // note it is sizeof(int*), not (int)
// initialize array
for (int i = 0; i < n; i++) {
m.arr[i] = malloc(n * sizeof(int));
// set value to 0
for (int j = 0; j < n; j++) {
m.arr[i][j] = 0;
}
}
:
:
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
printf("num: %d\n", m.arr[i][j]);
}
}
Note that if you want to initialize the allocated memory to zero, you should just use calloc, which does this initialization for you:
// initialize array
for (int i = 0; i < n; i++) {
m.arr[i] = calloc(n,sizeof(int));
}

How to pass and return two-dimensional array from function in c

I am relatively new to c, and I still have not been able to find a good way of passing and returning a multi-dimensional array from a function. I found the following code, however it doesn't seem like a good way to do things because it passes the array and then to use it, it creates a duplicate with the malloc function. Is there a way to do it without the copying and malloc function, or a better way to pass and return an 2d array from a function in c in general? Thanks.
#include <stdio.h>
#include <stdlib.h>
int **matrix_sum(int matrix1[][3], int matrix2[][3]){
int i, j;
int **matrix3;
matrix3 = malloc(sizeof(int*) * 3);
for(i = 0; i < 3; i++) {
matrix3[i] = malloc(sizeof(int*) * 3);
}
for(i = 0; i < 3; i++){
for(j = 0; j < 3; j++){
matrix3[i][j] = matrix1[i][j] + matrix2[i][j];
}
}
return matrix3;
}
int main(){
int x[3][3], y[3][3];
int **a;
int i,j;
printf("Enter the matrix1: \n");
for(i = 0; i < 3; i++){
for(j = 0; j < 3; j++){
scanf("%d",&x[i][j]);
}
}
printf("Enter the matrix2: \n");
for(i = 0; i < 3; i++){
for(j = 0; j < 3; j++){
scanf("%d",&y[i][j]);
}
}
a = matrix_sum(x,y); //asigning
printf("The sum of the matrix is: \n");
for(i = 0; i < 3; i++){
for(j = 0; j < 3; j++){
printf("%d",a[i][j]);
printf("\t");
}
printf("\n");
}
//free the memory
for(i = 0; i < 3; i++) {
free(a[i]);
}
free(a);
return 0;
}
The array are not copied for agurments. Just pointers to the first elements of them (int[3]) are passed.
To avoid malloc(), you should add another argument to specify the array where the result should be stored.
#include <stdio.h>
void matrix_sum(int matrix3[][3], int matrix1[][3], int matrix2[][3]){
int i, j;
for(i = 0; i < 3; i++){
for(j = 0; j < 3; j++){
matrix3[i][j] = matrix1[i][j] + matrix2[i][j];
}
}
}
int main(){
int x[3][3], y[3][3], a[3][3];
int i,j;
printf("Enter the matrix1: \n");
for(i = 0; i < 3; i++){
for(j = 0; j < 3; j++){
scanf("%d",&x[i][j]);
}
}
printf("Enter the matrix2: \n");
for(i = 0; i < 3; i++){
for(j = 0; j < 3; j++){
scanf("%d",&y[i][j]);
}
}
matrix_sum(a,x,y);
printf("The sum of the matrix is: \n");
for(i = 0; i < 3; i++){
for(j = 0; j < 3; j++){
printf("%d",a[i][j]);
printf("\t");
}
printf("\n");
}
return 0;
}
An array can be declared and used through a reference (pointer)
for instance
char array[] = {'h','e','l', 'l', 'o', '\0'};
char *pointer = array;
the way pointers work can be understood by calling sizeof() on a given type
printf("char:%d\nchar_pointer: %d\n", sizeof(char), sizeof(char*));
which results in the following output.
char:1
char_pointer: 4
these results mean that even though a char has 1byte, its pointer needs 4 in order to be stored in memory thus, they are not the same type.
now in order to pass an array as an argument to a function you have many options
void function1(array[4])
{
//this function can receive an array of four elements and only four elements;
//these types of functions are useful if the algorithm inside the function only works
//with a given size. e.g. matrix multiplication
}
//or
void function2(char array[], int size)
{
//this function can receive an array of elements of unknown size, but you can
//circumvent this by also giving the second argument, the size.
int i;
for(i = 0; i <= size; i++)
{
printf("%c", array[i]);
}
}
In order to use or call any of these functions you could pass the array or a pointer to the array
function2(array, 5);
function2(pointer, 5);
//these results are the same
The same applies to a multidimensional array
void function3(char** multi_dim_array, array_size_first_dim, array_size_second_dim);
//and you can call it by using the same syntax as before;
void main(int argc, char[] argv*)
{
char** multi_dim = malloc(sizeof(char*) * 3);
int i;
for(i = 0; i<=3 ; i++)
{
multi_dim[i] = malloc(sizeof(char) * 4);
}
function3(multi_dim, 3,4);
}
if you want to return a multidimensional array you can just return a pointer
char **malloc_2d_array(int dim1, int dim2)
{
char ** array = malloc(sizeof(char*)*dim1);
int i;
for(i = 0; i<=dim2; i++)
{
array[i] = malloc(sizeof(char) * dim2);
}
return array;
}
as a final note, the reason the code you found, copies the array, is because of functional programming(a way of programming if you will) where a function call cant modify its input, thus it will always create a new value;
First of all this is not gonna be a technical explanation. I am just gonna try and explain what works not why.
For passing a multidimensional array you can use either an array with a defined size as you did in your example code:
void matrix_sum(int matrix3[][3])
Or if you don't want to use a defined size and want to take care of memory usage you can use a pointer to a pointer. For this case you also need to pass the size (unless you are passing NULL-terminated strings). Like this:
void matrix_sum(int **matrix, int size)
BUT for this case you can't call the function with a "normal" array. You need to use a pointer to a pointer or a pointer to an array.
int **matrix;
// make sure to allocate enough memory for this before initializing.
or:
int *matrix[];
For returning an array you can just return a pointer to a pointer like you did in your code example.
But you don't need to return an array, because if you change a value in an array, (in a different function) the value will stay changed in every other function.
A short example for this:
#include <stdio.h>
void put_zeros(int matrix[][3])
{
int i;
int j;
i = 0;
while (i < 3)
{
j = 0;
while (j < 3)
{
matrix[i][j] = 0;
j++;
}
i++;
}
}
void print_matrix(int matrix[][3])
{
int i;
int j;
i = 0;
while (i < 3)
{
j = 0;
while (j < 3)
{
printf("%d ", matrix[i][j]);
j++;
}
printf("\n");
i++;
}
}
int main(void)
{
int matrix_first[3][3] = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
print_matrix(matrix_first);
put_zeros(matrix_first);
print_matrix(matrix_first);
}
This will print "1 2 3 4 5 6 7 8 9" because that's the first value we assigned.
After calling put_zeros it will contain and print "0 0 0 0 0 0 0 0 0" without the put_zeros returning the array.
1 2 3
4 5 6
7 8 9
0 0 0
0 0 0
0 0 0

Value is being used without being initialized

in my code i use malloc to create n string for my project
and after that , i created 'tr' to put all of string from
**str with small letters .
and it give me an error :
Run-Time Check Failure #3 - The variable 'str' is being used without being initialized.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void main(void)
{
int n;
char **str;
char *tr;
int cnt, k;
cnt = k = NULL;
printf("Enter number fo strings:\n");
scanf("%d", &n);
for (int i = 0; i < n; i++)
str[i] = (char*)malloc(sizeof(char)*n);
str = (char**)malloc(sizeof(char)*n + 1);
puts("Enter The strings");
for (int i = 0; i < n; i++)
{
for (int j = 0; i < n; j++)
scanf("%s", &str[i][j]);
}
for (int i = 0; i < n; i++)
{
for (int j = 0; i < n; j++)
{
if (str[i][j] >= 'a' && str[i][j] <= 'z')
cnt++;
}
}
tr = (char*)malloc(sizeof(char)*(cnt + 1));
for (int i = 0; i < n; i++)
{
for (int j = 0; i < n; j++)
{
if (str[i][j] >= 'a' && str[i][j] <= 'z')
tr[k++] = str[i][j];
}
}
tr[k] = NULL;
puts(tr);
free(tr);
free(str);
}
char **str;
char *tr;
int cnt, k;
cnt = k = NULL;
printf("Enter number fo strings:\n");
scanf("%d", &n);
for (int i = 0; i < n; i++)
str[i] = (char*)malloc(sizeof(char)*n); // here
you use str which is uninitialized. What do you expect? str has indeterminate value since it is uninitialized and almost certainly holds an invalid pointer value. Dereferencing an invalid pointer (which the operator [] does) is undefined behaviour.
What you'd have to do is first allocating memory for str to hold the pointers to the strings.
Btw.
puts("Enter The strings");
for (int i = 0; i < n; i++)
{
for (int j = 0; i < n; j++)
scanf("%s", &str[i][j]);
}
Is also incorrect. There is no need for the inner loop to read input from stdin and store it in str[i]. Also, don't use %s without specifying a with to limit the number of characters written to the destination.
if (str[i][j] >= 'a' && str[i][j] <= 'z')
That's what islower() from <ctype> is for.
free(str);
That's not enough to deallocate the memory since str points to a number of pointers to char which also point to allocated memory.
for (size_t i = 0; i < n; ++i)
free(str[i]);
free(str);
to the rescue.
You're not allocating before using, you're using then allocating, but also allocating incorrectly. The correct allocation is:
str = malloc(sizeof(char*) * n);
Where str is an array of char*, not an array of char.
It's good that you're listening to your compiler warnings, but this one was really specific and you should be able to find the problem. Ordering of allocations is extremely important and "close enough" is not acceptable. It either works, or it's undefined behaviour.
You have these two sections of code in the wrong order:
for (int i = 0; i < n; i++)
str[i] = (char*)malloc(sizeof(char)*n);
str = (char**)malloc(sizeof(char)*n + 1);
You need to allocate memory for str before you can assign to str[i]. And it should be sizeof(char *) * n; there's no need to add 1 to this (you only need this in tr, since you add a null terminator at the end).
It should be:
str = malloc(sizeof(char*)*n);
for (int i = 0; i < n; i++) {
str[i] = malloc(sizeof(char)*n);
}
After
Also, please read Do I cast the result of malloc? and Why is it considered a bad practice to omit curly braces?

C malloc (Segmentation fault: 11)

I'm trying to understand malloc but I keep getting "Segmentation fault: 11" with this piece of code:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int i = 0, j = 0;
char ** ptr = (char **) malloc(sizeof(char*));
for(i = 0; i < 5; i++)
{
for(j = 0; j < 10; j++)
ptr[i][j] = 'a';
printf("%s\n", ptr[i]);
}
return 0;
}
I thought there wasn't enough bytes being allocated so I did malloc(sizeof(char*) * 100, but gives me the same error. What am I not understanding here?
When you allocate a 2D array, you need to allocate the individual sub-arrays as well. In addition, you need to say how many elements you wish to have. For that you multiply the desired count by the number of elements, like this:
char ** ptr = (char **) malloc(5*sizeof(char*));
// Size=5 ---------------------^
for(int i = 0; i < 5; i++) {
ptr[i] = malloc(11*sizeof(char));
// sizeof(char) is always 1, so the multiplication above is redundant.
// You need 11 elements for ten characters
for(int j = 0; j < 10; j++) {
ptr[i][j] = 'a';
}
// don't forget to null-terminate the string:
ptr[i][10] = '\0';
printf("%s\n", ptr[i]);
}
Your code is totally messed up in every aspect!
1) you allocated memory for exactly 1 Pointer to it. This means you can access ptr[0], but not ptr[1] ... ptr[4] as you are trying to do.
2) you never allocate anything for the elements in ptr[i].
3) you try to print a string a ptr[i] which is (even if your allocation would be right) never terminated.
4) although this is obviously only a beginners test, never forget to free your memory!!!!
To reach something CLOSE to what your sampel code is describing you could do:
int main()
{
int i,j;
char ** ptr = malloc( 5 * sizeof(char*) ); /* an array of 5 elements of type char* */
for(i = 0; i < 5; i++)
{
ptr[i] = malloc( 11*sizeof(char) ); /* The element i of the array is an array of 11 chars (10 for the 'a' character, one for the null-termination */
for(j = 0; j < 10; j++)
ptr[i][j] = 'a';
ptr[i][10] = '\0'; /* strings need to be null terminated */
printf("%s\n", ptr[i]);
}
// free your memory!
for (i=0; i<5; i++ )
{
free(ptr[i]);
}
free(ptr);
return 0;
Another way to allocate the memory is:
char (*ptr)[11] = malloc( sizeof(char[5][11]) );
for(i = 0; i < 5; i++)
{
for(j = 0; j < 10; j++)
ptr[i][j] = 'a';
ptr[i][10] = 0;
printf("%s\n", ptr[i]);
}
free(ptr);
It seems less hassle to use a single allocation than to use a lot of allocations, unless you have a pressing reason to do the latter.

Allocating dynamic 2D char array

gcc 4.6.2 c89
Allocating memory for a 2D array and filling with characters.
However, I don't seem to be filling as when I print nothing is displayed.
Am I doing something wrong here?
char **attributes = NULL;
/* TODO: Check for memory being allocated */
attributes = malloc(3 * sizeof(char*));
int i = 0;
int k = 0;
for(i = 0; i < 3; i++) {
for(k = 0; k < 5; k++) {
sdp_attributes[i] = malloc(5 * sizeof(char));
sdp_attributes[i][k] = k;
}
}
for(i = 0; i < 3; i++) {
for(k = 0; k < 5; k++) {
printf("attributes[i][k] [ %c ]\n", attributes[i][k]);
}
}
Many thanks for any advice,
Two major issues:
First Issue:
for(i = 0; i < 3; i++) {
for(k = 0; k < 5; k++) {
sdp_attributes[i] = malloc(5 * sizeof(char));
You are reallocating sdp_attributes[i] at each iteration of the inner loop - thereby overwriting it each time. You probably wanted this instead:
for(i = 0; i < 3; i++) {
sdp_attributes[i] = malloc(5 * sizeof(char));
for(k = 0; k < 5; k++) {
Second Issue:
sdp_attributes[i][k] = k;
You are basically writing the lower ascii characters. Most of them are not printable.
Something like this might do what you want:
sdp_attributes[i][k] = k + '0';
You probably want:
for (i = 0; i < 3; i++)
{
attributes[i] = malloc(5 * sizeof(char));
for (k = 0; k < 5; k++)
{
attributes[i][k] = k;
}
}
This ignores error checking on the allocation.
It also fixes the name of the array to match the declaration, but your code either wasn't compiling (don't post non-compiling code unless your question is about why it doesn't compile!) or you have another variable called sdp_attributes declared somewhere which you weren't showing us.
Your code was leaking a lot of memory. Each time around the k-loop, you allocated a new array of 5 characters and stored the pointer in attributes[i] (or sdp_attributes[i]), storing the new pointer over what was there before, so you overwrote the value of the first 4 pointers. You could not possibly free the first four items - they were lost irretrievably. Also, on the last iteration, you initialized the 5th element of the final array, but the previous 4 were not initialized and therefore contained indeterminate garbage.
Also, in your printing loop, the values in the array are control characters ^#, ^A, ^B, ^C and ^D; these do not necessarily print well with %c (especially not ^#, which is also known as NUL or '\0'). The printf() statement might be better written as:
printf("attributes[%d][%d] [ %d ]\n", i, k, attributes[i][k]);
This prints the array indexes (rather than simply the characters [i][k] for each entry), and prints the control characters as integers (since the char values are promoted to int when passed to printf()) rather than as control characters.
(It's also more conventional to use i and j for a pair of nested loops, and i, j, and k for triply nested loops, etc. However, that's a very minor issue.)
for(i = 0; i < 3; i++) {
for(k = 0; k < 5; k++) {
sdp_attributes[i] = malloc(5 * sizeof(char));
sdp_attributes[i][k] = k;
}
}
Your erasing the allocated memory every time you loop in the inner most loop.
Here is a correct version.
for(i = 0; i < 3; i++) {
sdp_attributes[i] = malloc(5 * sizeof(char));
for(k = 0; k < 5; k++) {
sdp_attributes[i][k] = k;
}
}
And you should fix your declaration:
attributes = malloc(3 * sizeof(char*));
to
sdp_attributes = malloc(3 * sizeof(char*));
Don't forget to free up all the memory allocated
for(i = 0; i < 3; i++)
{
free(sdp_attributes[i]);
}
free(sdp_attributes);
The correct way to allocate and assign elements to 2d array is as follows (but this is a int array, you can try and change it for char array):
One thing to note: As mentioned by #Mysticial, you should add/subtract '0' to your int value to get the char value when using ASCII character set (remember our itoa() functions!).
#include <stdio.h>
#include <stdlib.h>
int main()
{
int row, column;
int **matrix;
int i, j, val;
printf("Enter rows: ");
scanf("%d", &row);
printf("Enter columns: ");
scanf("%d", &column);
matrix = (int **) malloc (sizeof(int *) * row);
for (i=0 ; i<row ; i++)
matrix[i] = (int *) malloc (sizeof(int) * column);
val=1;
for (i=0 ; i<row ; i++) {
for (j=0 ; j<column; j++) {
matrix[i][j] = val++;
}
}
for (i=0 ; i<row ; i++) {
for (j=0 ; j<column; j++) {
printf("%3d ", matrix[i][j]);
}
printf("\n");
}
for (i=0 ; i<row ; i++)
free(matrix[i]);
free(matrix);
return 0;
}
Few points to note:
error handling should be added for malloc()
malloc()'ed memory must be free()'ed

Resources