malloc a char[][] - c

I am trying to malloc a char to have rows and columns with one letter in each cell. Something similar to int x[i][j] where I have i*rows and j*columns. Basically I want to make this:
|
1
222
33333
4444444
I tried with this code but it gives me an error: assignment makes an integer from pointer without a cast
A=(char**) malloc (5*sizeof(char*));
for(i=0;i<N+2;i++)`{
A[i]=(char*) malloc(7*sizeof(char));
}
for(i=0;i<3;i++){
for(j=0;j<7;j++){
left=3;
right=3;
if((j>=left)&&(j<=right)){
A[i][j]=i;
}
}
left--;
right++;
}

I would go with different approach:
#define STEPS 5
#define ARRAY_SIZE STEPS*STEPS
The size of the array in your case can be easily calculated by the formula above.
Now, you just need to allocate fixed size of bytes, and fill it. That's it. Even more, the version below will simply out-beat your version in simplicity and performance.
int i, j;
char *array;
array = malloc(ARRAY_SIZE);
for (i = 0; i < STEPS; i++)
for (j = 0; j < (i * 2 + 1); j++)
*(array + i * STEPS + j) = i + 1;
Proof.

This compiles fine for me, as long as I add this around your code snippet; note that "A" was declared as being of type "char **". It won't work if you write, say "char A[][]".
#include <stdlib.h>
int main() {
const int N = 10;
int i, j, left, right;
char **A;
/* your code */
return 0;
}

Related

Unexpected outputs, why?

This is simple, I am allocating a dynamic 2d array using functions. I limited the scanf() len and my problem is when input a value over the limit, something weird happen.
Example
Input: 111,222,333,444
Expected output: 11,22,33,44
Real output: 11,12,33,34
#include <stdio.h>
#include <stdlib.h>
#define gd 2
void get_mem(int ***arr);
void get_data(int **arr);
int main(){
int **arr;
arr = NULL;
get_mem(&arr);
get_data(arr);
free(*arr);
return 0;
}
void get_mem(int ***arr){
int i;
*arr = (int**)malloc(gd*sizeof(int*));
for(i=0;i<5;i++){
(*arr)[i] = (int*)malloc(gd*sizeof(int));
}
printf("oki\n");
}
void get_data(int **arr){
int c,f;
for(c=0;c<gd;c++){
for(f=0;f<gd;f++){
scanf("%2d",&*(*arr+c)+f);
fpurge(stdin);
fflush(stdin);
}
}
for(c=0;c<gd;c++){
for(f=0;f<gd;f++){
printf("%d ",*(*arr+c)+f);
printf("\n");
}
}
}
The value of macro gd is 2. In get_mem(), allocating memory for 2 int *:
*arr = (int**)malloc(gd*sizeof(int*));
and below it, accessing arr beyond it size:
for(i=0;i<5;i++){ //allocating memory to 5 int pointers
^^
(*arr)[i] = (int*)malloc(gd*sizeof(int));
}
Accessing an unallocated memory is undefined behaviour.
Instead of using magic number 5 in the loop condition, you should check i with gd, like this
for(i=0;i<gd;i++){
In get_data(), the way you are accessing elements of arr for input is wrong
scanf("%2d",&*(*arr+c)+f);
^^^^^^^^^^^^
because
&arr[c][f] --> &(*(arr[c] + f) --> &(*(*(arr + c) + f)) --> &*(*(arr + c) + f) --> (*(arr + c) + f)
Note: The operator & is used to get the address and the operator * is used for dereferencing. These operators cancel the effect of each other when used one after another. Hence, &(*(arr + i)) is equivalent to arr + i.
That means, &arr[c][f] is equivalent to (*(arr + c) + f) and you should use &arr[c][f] which is less error prone and more readable:
for(f = 0; f < gd; f++) {
scanf("%2d", &arr[c][f]);
Same mistake you have made while printing the arr elements in second for loop:
for(f=0;f<gd;f++){
printf("%d ",*(*arr+c)+f);
^^^^^^^^^^^
It should be *(*(arr + c) + f). More readable form is arr[c][f]:
for(f = 0; f < gd; f++){
printf("%d ", arr[c][f]);
You should not use fflush() for input stream. It's undefined behavior. From C Standards#7.21.5.2p2 -
If stream points to an output stream or an update stream in which the most recent operation was not input, the fflush function causes any unwritten data for that stream to be delivered to the host environment to be written to the file; otherwise, the behavior is undefined.
Also, fpurge() is nonstandard and not portable. Moreover, you don't need to use either of them.
Rather than using more & more pointers, I'd like to do it in this way:-
#include <stdio.h>
#include <stdlib.h>
//#define gd 2
#define ROW 2
#define COLUMN 2
void get_mem(int ***arr);
void get_data(int **arr);
int main(){
int **arr = NULL;
get_mem(&arr);
printf("Enter 4 int values: ");
get_data(arr);
free(*arr);
return 0;
}
void get_mem(int ***arr)
{
int i;
*arr = ( int ** )malloc( ROW * sizeof(int *) );
for(i = 0; i < COLUMN; i++)
{
(*arr)[i] = ( int * )malloc( COLUMN * sizeof(int) );
}
printf("Okay!\n");
}
void get_data(int **arr)
{
int c, f;
for(c = 0; c < ROW; c++)
{
for(f = 0; f < COLUMN; f++)
{
scanf("%2d", &arr[c][f]); //*(*arr+c)+f)
}
}
for(c = 0; c < ROW; c++)
{
for(f = 0; f < COLUMN; f++)
{
printf("%d ", arr[c][f]); //*(*arr+c)+f)
}
putchar('\n');
}
}
I don't know what that gd is but it was making code ambiguous so I removed that and replaced it with ROW & COLUMN everywhere in the program(where it was necessary).
After allocating space to int **arr via get_mem() function, at least ask the user to input values and use proper spacing & indenting.
There's no need of fflush or fpurge, so I removed them.
Now, here if you're accessing array this way you need to be very careful of using parenthesis at proper places. You should use *(*(arr+c)+f) instead of *(*arr+c)+f)(It was an error.) this. But I chose to access the elements or store values as we do in 2D arrays. That's easier.
If you want to access this array using pointers only, instead of arr[c][f] you can do it in this way:-
scanf("%2d", &(*(*(arr+c)+f)));
&
printf("%d ", *(*(arr+c)+f));
Note: Also, you should check for any error while allocating memory.
Hope, it helps.

Strange behavior while filling dinamically allocated 2D char array in C

I need to create a program that plays the game Hex on a 14x14 board.
So I created, allocated and filled the board with '-' (our pattern for empty spaces).
When I try to print the board's coordinates, I don't always get '-' but some random characters.
Also, if I try to printf array[i][j] on the createBoard function after the line "board[i][j] = '-';" I get a segmentation fault right after it prints tab[8][0].
What is causing this and how can I fix it?
My code:
#include <stdio.h>
#include <stdlib.h>
char **createBoard()
{
/*Allocates a 14x14 matrix and fills it
*with '-' to create the board.*/
int i, j;
char **board;
board = malloc(14);
if (!board) exit(1);
for (i = 0; i < 14; i++){
board[i] = malloc(14);
if (!board[i]) exit (1);
for (j = 0; j < 14; j++)
board[i][j] = '-';
}
return board;
}
int main()
{
int i, j;
char **board = createBoard();
for (i = 0; i < 14; i++)
for (j = 0; j < 14; j++)
printf("tab[%d][%d]: %c\n",i, j, board[i][j]);
return 0;
}
For starters it is not clear why you don't want to declare an array instead of allocating dynamically numerous one-dimensional arrays.
As for the code then this memory allocation
board = malloc(14);
is invalid. You have to write
board = malloc( 14 * sizeof( char * ));
Also you should free all the allocated memory in the reverse order relative to its allocation before the program ends.
Take into account that it is always better to use named constants instead of magic numbers. At least you could write either
#define N 14
before main
or
const int N = 14.
and use the variable N everywhere where you are using magic number 14.
By the way according to the C Standard function main without parameters shall be declared like
int main( void )
The variable *board is a pointer, but you only allocate one byte for each array element, which should be
#define DIM 14
board = malloc(DIM * sizeof *board);
Following that up with the second allocation
board[i] = malloc(DIM * sizeof **board);
This also allows (a) that the dimension 14 is hard coded in only one place in the program and (b) the allocation will survive if you later make the board's element a different type, for example a struct, as the program develops.

Function passing of multidimensional array in c

#include <stdio.h>
void spiral(int a[10][10]) {
printf("%d", a[1][3]);
}
int main() {
int r, c, j, i;
scanf("%d%d", &r, &c);
int a[r][c];
for (i = 0; i < r; i++)
for (j = 0; j < c; j++) {
scanf("%d", &a[i][j]);
}
spiral(a);
return 0;
}
When I give a 3 x 6 array
1 2 3 4 5 6
7 8 9 10 11 12
13 14 15 16 17 18
The output is 14, while it should be 10
How to fix this issue?
If you enter 3 and 6 for r and c (respectively) then the type of a is not int[10][10] (or int(*)[10] as the spiral argument really is), it's int[3][6]. The memory layout is completely different for the arrays, leading to undefined behavior.
You can solve this by passing the size along to the function, and using it in the declaration of the array:
void spiral(const size_t r, const size_t c, int (*a)[c]) { ... }
Call it like expected:
spiral(r, c, a);
As noted using int a[r][c] as argument might be easier to read and understand, but it gives a false impression that a is actually an array. It's not. The compiler treats the argument as a pointer to an array of c integers, i.e. int (*a)[c].
This makes me a little conflicted... On the one hand I'm all for making things easier to read and understand (which means it will be easier to maintain), on the other hand newbies often get it wrong and think that one can pass an array intact when in fact it decays to a pointer which can lead to misunderstandings.
A few things are wrong: in void spiral() you ask for a 2D-array of 10*10, but you do not give that. Keep that part as a variable, so only ask the type you receive and not what you want to receive and with creating a dynamic array you should always do that with malloc or calloc and free them afterwards. This might be a bit hard at first, but when you start creating bigger programs this is a must if you have a question or do not understand the pointers in the program called (*) then ask me:
#include <stdio.h>
#include <stdlib.h>
void spiral(int **a) {
printf("%d", a[1][3]);
}
int main() {
int r, c, j, i;
scanf("%d%d", &r, &c);
int **a = malloc(r * sizeof(int*));
for (i = 0; i < r; i++) {
a[i] = malloc(c * sizeof(int));
}
for (i = 0; i < r; i++) {
for (j = 0; j < c; j++) {
scanf("%d", &a[i][j]);
}
}
spiral(a);
for (i = 0; i < r; i++) {
free(a[i]);
}
free(a);
return 0;
}

C, passing 2 dimensional array

I haven't used pure C in a few years now, but I can't seem to make this really basic use case work. Here is the simple use-case in simple C, the actual situation is wrapped in the HDF library, but I need to start with this, first.
#include <stdio.h>
void print_data(float **data, int I, int J)
{
for(int i=0;i<I;i++)
{
for(int j=0;j<J;j++)
printf("%02.2f\t", data[i][j]);
printf("\n");
}
}
void initialize_data(float **data, int I, int J)
{
for(int i=0;i<I;i++)
for(int j=0;j<J;j++)
data[i][j] = i * 6 + j + 1;
}
int main(int argc, char *argv[])
{
float data[4][6];
int I=4;
int J=6;
initialize_data((float **)data, 4,6);
print_data((float **)data, 4, 6);
return 0;
}
The above program will cause a failure and raise a EXC_BAD_ACCESS signal. GDB outputs:
Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_PROTECTION_FAILURE at address: 0x00007fff5fc0131a
0x0000000100000de6 in initialize_data (data=0x7fff5fbff348, I=4, J=6) at simple.c:16
16 data[i][j] = i * 6 + j + 1;
I know this is really stupid simple, but I'm at my wits' ends trying to figure out this simple thing. Could someone point me in the right direction for this?
void print_data(float **data, int I, int J)
expects an array of pointers to (the first element of arrays of) float.
But when you pass
float data[4][6];
you pass a pointer to float[6].
So in print_data, an access to
data[i]
reads sizeof(float*) bytes at an offset of i * sizeof(float*) bytes after what address data holds, and interprets these bytes as a float* that it then dereferences (after adding a suitable offset) in data[i][j].
So when you pass your 2D array, some float values are interpreted as pointers and then followed. That often leads to a segmentation fault.
You can either declare
void print_data(float (*data)[6], int I, int J)
and pass your 2D array, or you need to pass an array of pointers,
float *rows[4];
for(i = 0; i < 4; ++i) {
rows[i] = &data[i][0];
}
and pass rows. Or, the third possibility is to pass and expect a flat array
void initialize_data(float* data, int I, int J) {
for(i = 0; i < I; ++i) {
for(j = 0; j < J; ++j) {
data[i*J + j] = whatever;
}
}
}
and pass &data[0][0] from main.
A bi-dimensionnal array is not evaluated as a pointer to pointer, so you need to use an array of a pointer to array in your prototype:
void print_data(float data[4][6]);
void print_data(float (*data)[6]);

c pointer understanding issue

Please have a look at the following code and tell me where does ***ptr locates ?
i.e. i have a feelings that ***ptr actually locates at ptr[0][0][0]
Am I wrong ? The following is a 3d representation of pointer. where I am trying to assign some characters and later i wanted to test what is the index of ***ptr? will be waiting
#include<stdio.h>
#include<conio.h>
#define row 5
#define rw 3
#define col 10
char ***ptr;
int i,j,k;
void main()
{
clrscr();
ptr=(char *)malloc(row*sizeof(char *));
for(i=0;i<row;i++)
{
*(ptr+row)=(char *)malloc(rw*sizeof(char *));
printf("\t:\n");
for(j=0;j<rw;j++)
{
*(*(ptr+row)+rw)=(char *)malloc(col*sizeof(char *));
if(i==0 && j==0)
{ // *(*(ptr+row)+rw)="kabul";
**ptr="zzz";
}
else
*(*(ptr+row)+rw)="abul";
printf("\taddress=%d %d%d = %s\n",((ptr+row)+rw),i,j,*(*(ptr+row)+rw));
}
printf("\n");
}
printf("%c %d",***ptr,ptr);
getch();
}
First of all, I find your coding style extremely hard to read.
Answering your question, yes, ptr[0][0][0] is a synonym of ***ptr. Thats because a[b] is by definition equal to *(a+b), so ptr[0] is equal to *ptr, etc.
Said that, here is my version of your code:
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#define row 5
#define rw 3
#define col 10
char ***ptr;
int main()
{
int i, j;
ptr = (char***)malloc(row * sizeof(char **));
for(i = 0; i < row; i++)
{
ptr[i]= (char**)malloc(rw * sizeof(char *));
printf("\t:\n");
for(j = 0; j < rw; j++)
{
ptr[i][j] = (char*)malloc(col * sizeof(char));
if (i == 0 && j == 0)
{
strcpy(ptr[i][j], "zzz");
}
else
{
strcpy(ptr[i][j], "abul");
}
printf("\taddress=%p %d,%d = %s\n", ptr[i][j], i, j, ptr[i][j]);
}
printf("\n");
}
return;
}
Note the following changes:
Never write void main in C or C++. And throw away any book that prints it.
The argument of malloc is usually the number of elements times the size of the element. Place special attention to the real type that you intend to use.
The return of malloc is usually cast to the type pointer-to-the-type-of-the-element.
The index in the arrays should be i and j, not row and rw.
Why all the *(ptr + x) stuff? That's why we have the ptr[x] syntax.
You probably want to use strcpy to fill your strings, but difficult to say without explaining the problem.
When you want to printf a pointer, use %p.
If you use malloc, include <stdlib.h>.
Prefer local variables (i, j) to global ones, particularly for loops.
And a few other minor changes here and there...
PS. <conio.h>? Really? Are you still using Turbo-C or what?

Resources