I'm a CS student working on a homework assignment, and I need help with a C syntax issue. Yesterday in class, my professor said, "an int** pointer is a pointer to a 2D int array." This blew my mind.
Turns out, we have to write a C program which reads an int matrix from a file, then do operations on that matrix. For example, "matrix1.txt" might look like this:
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
...for a 5x3 matrix. I get the dimensions of the matrix from another file, which is a problem I've already solved. But the point is I have to dynamically allocate the matrix array using variables.
Here's my issue: Its easy enough to use an int** pointer to malloc() an Y-by-X array... but what's the syntax to access it? Here's my code:
#include<stdio.h>
#include<stdlib.h>
int main(int argc, char *argv[]){
char *myFile = argv[1];
FILE *targetFile;
targetFile = fopen(myFile, "r");
if (targetFile == NULL)
return -1;
else {
// Successfully opened "matrix1.txt" file
int x, y; // dimensions of the array, learned elsewhere...
int i, j;
char* data = NULL;
int** matrix = (int**)malloc((x*y)*sizeof(int)); // allocate memory for an Y-by-X array
for(i=0; i<y; i++){
for(j=0; j<x; j++){
fscanf(targetFile, "%c ", &data);
matrix[i][j] = atoi(data); // program seg faults here
}
}
}
fclose(targetFile);
return 1;
}
The issue is the "matrix[i][j] = atoi(data);" line; I'm either using the wrong syntax or I haven't initialized the array. I can't tell which - the program seg faults IMMEDIATELY once I hit this line in the GDB debugger.
I'm sure this is a C 101 kind of question... but I post this because I've been reading a lot of different posts on 2D arrays and pointers, yet I can't seem to find an example that fits my precise situation. Can anyone help me out with this?
Thanks,
-ROA
The syntax used in
matrix[i][j] = atoi(data);
is not incorrect. It's the logic used to allocate memory that is wrong.
One way to allocate memory for the 2D array is:
// Allocate memory for y number of int*s.
int** matrix = malloc(y*sizeof(int*));
for(i=0; i<y; i++)
{
// Allocate memory for x number of ints.
matrix[i] = malloc(x*sizeof(int));
for(j=0; j<x; j++)
{
// Assign to the ints
matrix[i][j] = <some value>;
}
}
For reading the data, use
int data;
and
fscanf(targetFile, "%d", &data);
Then, the inner loop above can be updated to:
for(j=0; j<x; j++)
{
// Assign to the ints
fscanf(targetFile, "%d", &data);
matrix[i][j] = data;
}
Make sure to add code to release the dynamically allocated memory.
// Free the memory allocated for the ints
for(i=0; i<y; i++)
{
free(matrix[i])
}
// Free the memory allocated for the int*s
free(matrix);
Related
I'm trying to allocate the char** path array in my batiment struct
#ifndef SDL2_BATIMENTS_H
#define SDL2_BATIMENTS_H
typedef struct{
int x;
int y;
}vecteur;
typedef struct{
int numtype; //Détermine quelle representation du batiment (route nor/ route sud...)
char** tabpath; // tableau de chemin d'acces aux images
vecteur size; // Taille du batiment en (x,y)
int habitant;
}batiment;
typedef struct {
vecteur** tuile;
batiment* tabbatiment; //tableau de batiment
}Monde;
Monde* InitBatiment(Monde* monde);
vecteur toGrid(float x,float y);
#endif //SDL2_BATIMENTS_H
I've tried to allocate it like an array[][], at first it seems to be working with no error but everytime i try to access it my program crashes
for(int i=0; i<14;i++)
{
monde->tabbatiment[i].tabpath = malloc(7 * sizeof (char*));
for (int y = 0; y < 7; y++)
monde->tabbatiment[i].tabpath[i] = (char*)malloc(50 * sizeof(char));
}
Ok First of all thank you for your answer, I changed my code to this but everytime my program try to call strcpy it crashes.
I think I still have an allocation problem or a memory leak.
for(int i=0; i<14;i++)
{
monde->tabbatiment[i].tabpath = calloc(10,sizeof(char*));
for(int y = 0; y < 10; y++)
monde->tabbatiment[i].tabpath[i] = calloc(30 ,sizeof(char));
}
FILE *f;
char c;
int numbatiment;
f=fopen("batiment.txt","r");
int x,y,numbat,numtype;
const char path[50];
for(int i =0;i<16;i++)
{
fscanf(f,"%d %d %d %d %s ",&numbat,&x,&y,&numtype,&path);
printf("%s",path);
strcpy(monde->tabbatiment[numbat].tabpath[numtype],path);
monde->tabbatiment[numbat].size.x = x ;
monde->tabbatiment[numbat].size.y=y ;
monde->tabbatiment[numbat].numtype = numtype;
printf("%d %d %d %d %s\n",numbat,monde->tabbatiment[numbat].size.x,monde->tabbatiment[numbat].size.y,monde->tabbatiment[numbat].numtype,monde->tabbatiment[numbat].tabpath[numtype]);
}
fclose(f);
Could you elaborate what you are exactly trying to accomplish with the code? It feels like there is more to it then a simple bug, but more of an implementation issue as a whole.
I cannot replicate your SEGFAULT for what it's worth. I do run into a lot of memory issues in valgrind, all of which could be attributed that you allocate memory in a loop, where you could've easily done it in a linear block (hence why I'm afraid that there might be more to this).
To directly answer your question: allocating memory for a string can go 2 ways: either you allocate enough memory from the start for which you are certain the any string you throw at it will be smaller than the allocated memory. Or you allocate memory on the go based on the length of the string that you are adding to your array.
In both cases you would be looking at a combination of malloc/calloc and strcpy/strncpy (the latter in both having my preference most often). Allocate memory where the string should reside, than copy a local buffered value to the designated memory address.
Anyway, I've refactored your example to this. I have to say: take a GOOD look at how you are using indexes in loops. You are going out of bounds often, which might trigger a SEGFAULT. For monde->tuile for instance you allocate 35 slots, but the next thing you do is loop the tuile index to 44. I've also included some define statements which are good practice over magic numbers.
#define SIZE_BATIMENT 15
#define SIZE_TUILE 34
#define SIZE_TABPATH 8
#define MAX_STRING_LEN 64
Monde *monde = calloc(1, sizeof monde);
monde->tuile = calloc(SIZE_TUILE, sizeof(vecteur *));
for (int i=0 ; i <= SIZE_TUILE ; i++)
{
monde->tuile[i] = (vecteur*)malloc(45 * sizeof(vecteur));
}
// Assign memory to allow MAX_STRING_LEN sizes
monde->tabbatiment = calloc(SIZE_BATIMENT, sizeof(batiment));
for(int i = 0; i <= SIZE_BATIMENT; i++)
{
monde->tabbatiment[i].tabpath = calloc(SIZE_TABPATH, sizeof(char *));
for (int j = 0; j <= SIZE_TABPATH; j++)
{
monde->tabbatiment[i].tabpath[j] = calloc(MAX_STRING_LEN, sizeof(char));
}
}
I'm implementing a K-means algorithm in C. It works well most of the time, but debugging it with Valgrind tell me that I'm doing an "Invalid read of size 8 - Invalid write of size 8 - Invalid read of size 8" using '''memcpy''' at the beginning. I think the problem isn't there, but where I assign a value to the multidimensional float array element, which memory is dynamically allocated with '''malloc''' with a for loop at some point. 'Cause Valgrind also tell "Address 0x572c380 is 0 bytes after a block of size 80 alloc'd".
I've tried to add 1 to the number of bytes that I allocate, cause I thought that maybe '''malloc''' "needed" more memory to do its job, but nothing changed. I know maybe it's a basic error, but I'm quite new to the language and at my course it wasn't explain anything so "technical". I've tried to search the answer and explanation of the error but I have only found problems with '''char''' arrays, and with those I'd understood the function '''strcpy''' can resolve the issue. What about float arrays? It's the first time a use '''memcpy'''.
Here are pieces of code that raise those Valgrind messages.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void main(){
FILE* fp; //used to open a .txt file to read
char buf[100];
float ** a;
char * s;
int i;
int j;
int rows = 10;
fp = fopen("data.txt", "r");
if(fp==NULL){
perror("Error at open file.");
exit(1);
}
a = (float**) malloc(rows*sizeof(float*));
for(i=0; i<rows; i++){
s = fgets(buf, 100, fp); //reading .txt file
if (s==NULL){
break;
}
a[i] = malloc(dim*sizeof(float));
a[i][0] = atof(strtok(s, ","));
for(j=1; j<dim; j++){
a[i][j] = atof(strtok(NULL,",")); //save as float value the token read from a line in file, for example, from line "1.0,2.0,3.0" as first line -> get a[0][1] = 2.0
}
}
fclose(fp);
m = (float**) malloc(rows*sizeof(float*));
for (i=0; i<rows; i++){
m[i]=malloc(dim*sizeof(float)); //not initialized
}
memcpy(m, a, rows*dim*sizeof(float));
}
Can someone also help me understand why it works but Valgrind raises these error messages?
You're first allocating an array of float*, then allocating several arrays of float so your last memcpy(m, a, rows*dim*sizeof(float)) copies an array of float* (pointers to float) to another one, but using rows * dim floats, which #SomeProgrammerDude rightfully noted. That would copy pointers, and not values.
Also, as pointed by #xing, you're allocating rows but using righe (which you didn't show). It might be a cause of problems.
I would suggest allocating the whole array at once on the first row, then having all other rows pointing to adequate rows:
a = malloc(rows * sizeof(float*));
a[0] = malloc(dim * rows * sizeof(float)); // Allocate the whole matrix on row #0
for (i = 1; i < rows; i++) {
a[i] = a[0] + i * dim; // sizeof(float) automatically taken into account as float* pointer arithmetics
}
...
m = malloc(rows * sizeof(float*));
m[0] = malloc(dim * rows * sizeof(float));
memcpy(m[0], a[0], dim * rows * sizeof(float));
(add NULL checks of course)
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.
Just a quick comment to start: While there are similar threads to this one, I haven't quite been able to find the solution I'm looking for. My problem is the following:
I have 2D arrays of doulbes saved to binary files and I would like to read the binary files (using C code) into a 2D array. Additionally, I need to allocate the memory dynamically as the shape of the arrays will be changing in my application. To get started, I tried the following code:
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
int main(){
int N = 10; //number of rows of 2D array
int M = 20; //number of columns
/* first allocate the array */
double **data;
data = (double **)malloc(N*sizeof(double *));
for(unsigned int i=0; i < N; i++) {
data[i] = (double *)malloc(sizeof(double)*M);
}
FILE *ptr;
ptr = fopen("random_real_matrix.dat", "rb");
fread(data, sizeof(data), 1, ptr);
for(unsigned int i=0; i<10;i++){
for(unsigned int j=0; j<20;j++){
fprintf(stderr, "m[%d][%d] = %f\n ", i, j, data[i][j]);
}
}
}
Unfortunately, this code segfaults. I checked to see if I can set the array entries like
d[0][0] = 235;
and that works fine.
Assuming this approach can be fixed, I'm also interested to know if it could be extended to read to an array of double complex's.
Any advice would be greatly appreciated!
Your fread statement is incorrect. It's a common beginner mistake to think that sizeof gets the size of a dynamically allocated array. It doesn't. In this case it just returns the size of a double **. You will need to read in each double in the file and put that into the correct spot in the array.
for (int ii = 0; ii < N; ++ii)
{
for (int jj = 0; jj < M; ++jj)
{
fread(data[ii][jj], sizeof(double), 1, ptr);
// Be sure to check status of fread
}
}
You can do this with a single for loop (or a single fread) but this is probably clearer to read.
Because you allocated each row separately, you can't read into the entire array at once. You need to do it row by row.
for (int i = 0; i < N; i++) {
fread(data[i], sizeof(double), M, ptr);
}
I am trying to build two dimensional array by dynamically allocating. My question is that is it possible that its first dimension would take 100 values, then second dimension would take variable amount of values depending on my problem? If it is possible then how I would access it? How would I know the second dimension's boundary?
(See the comments in the code)
As a result you'll get an array such like the following:
// Create an array that will contain required variables of the required values
// which will help you to make each row of it's own lenght.
arrOfLengthOfRows[NUMBER_OF_ROWS] = {value_1, value_2, ..., value_theLast};
int **array;
array = malloc(N * sizeof(int *)); // `N` is the number of rows, as on the pic.
/*
if(array == NULL) {
printf("There is not enough memory.\n");
exit (EXIT_FAILURE);
}
*/
// Here we make each row of it's own, individual length.
for(i = 0; i < N; i++) {
array[i] = malloc(arrOfLengthOfRows[i] * sizeof(int));
/*
if(array[i] == NULL) {
printf("There is not enough memory.\n");
exit (EXIT_FAILURE);
}
*/
}
You can use array of 100 pointers:
int *arr[100];
then you can dynamically allocate memory to each of the 100 pointers separately of any size you want, however you have to remember how much memory (for each pointer) you have allocated, you cannot expect C compiler to remember it or tell it to you, i.e. sizeof will not work here.
To access any (allowed, within boundary) location you can simply use 2D array notation e.g. to access 5th location of memory allocated to 20th pointer you can use arr[20][5] or *(arr[20] + 5).
I believe the OP wants a single chunk of memory for the array, and is willing to fix one of the dimensions to get it. I frequently like to do this when coding in C as well.
We all used to be able to do double x[4][]; and the compiler would know what to do. But someone has apparently messed that up - maybe even for a good reason.
The following however still works and allows us to use large chunks of memory instead of having to do a lot of pointer management.
#include <stdio.h>
#include <stdlib.h>
// double x[4][];
struct foo {
double y[4];
} * x;
void
main(int ac, char * av[])
{
double * dp;
int max_x = 10;
int i;
x = calloc(max_x, sizeof(struct foo));
x[0].y[0] = 0.23;
x[0].y[1] = 0.45;
x[9].y[0] = 1.23;
x[9].y[1] = 1.45;
dp = x[9].y;
for (i = 0; i < 4; i++)
if (dp[i] > 0)
printf("%f\n", dp[i]);
}
The trick is to declare the fixed dimension in a struct. But keep in mind that the "first" dimension is the dynamic dimension and the "second" one is fixed. And this is the opposite of the old way ...
You will have to track the size of your dynamic dimension on your own - sizeof can't help you with that.
Using anonymous thingies you might even be able to git rid of 'y'.
Using a single pointer:
int *arr = (int *)malloc(r * c * sizeof(int));
/* how to access array elements */
for (i = 0; i < r; i++)
for (j = 0; j < c; j++)
*(arr + i*c + j) = ++count; //count initialized as, int count=0;
Using pointer to a pointer:
int **arr = (int **)malloc(r * sizeof(int *));
for (i=0; i<r; i++)
arr[i] = (int *)malloc(c * sizeof(int));
In this case you can access array elements same as you access statically allocated array.