I have reacently switched to C due to its exceptional computing speeds. I am currently trying to import a very large CSV table (500.000 x 27) into an array, but am facing majour difficulties in trying to assign the values from the imported cell to the respective array cell.
I hope the following code helps in trying to understand my problem. I would be glad for any help!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
int row = 520241, col = 27, j = 0, i = 0;
double *arr[row];
for(i = 0; i < row; i++)
arr[i] = (double*)malloc(col*sizeof(double));
FILE *f;
f = fopen("WethData.csv","r");
if( f == NULL) { //control
printf("Unable to open file \n");
exit(1);
}
char line[485]; //if too little memory is allocated weird numbers show up
char *sp; //string pointer
i = 0; //loop to store every row
double res;
while(fgets(line, 485, f) !=NULL) {
sp = strtok(line, ","); arr[i][0] = atof(sp); //<- Here the problem lies as far as I know
for(j = 1; j < col; j++)
sp = strtok(NULL, ","); arr[i][j] = atof(sp); //<-
i++;
if( i > row) {
puts("Row count exceeded"); //controll, if the loop repeats more than there are rows: "record count exceeded"
exit(1); //stops loop
}
};
fclose(f);
return 0;
}
There are a few issues ...
Putting arr on the stack can be problematic:
int row = 520241, col = 27;
double *arr[row];
Here, arr takes up 520241 * 8 bytes which is 2,901,208 bytes. Most archs have a default stack size of 4MB or 8MB. While your allocation is below this, the method doesn't scale to really large .csv files.
Also, pre-allocating for a fixed number of rows can be wasteful. Better to allow the array to grow dynamically in both dimensions.
You don't really have a two dimensional array as C defines them. You have a one dimensional array of pointers to double elements. This is how one has to define a 2D array in languages that don't have 2D arrays (e.g. python).
Note that you're using atof to decode numbers (on the return value of strtok). We can skip the strtok altogether if we use strtod to decode the numbers.
Creating a control struct for a dynamic 2D array can be helpful.
Anyway, here is some refactored code. It is annotated:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#define sysfault(_fmt...) \
do { \
printf(_fmt); \
exit(1); \
} while (0)
typedef struct {
int rowmax;
int colmax;
double *data;
} arr_t;
// colcalc -- get number of columns in csv file
int
colcalc(const char *line)
{
int colmax = 1;
// count the number of commas
while (1) {
line = strchr(line,',');
if (line == NULL)
break;
++line;
++colmax;
}
return colmax;
}
// arrload -- read in array from .csv file
arr_t *
arrload(FILE *f)
{
char line[10000];
arr_t *arr;
arr = calloc(1,sizeof(*arr));
if (arr == NULL)
sysfault("calloc failure -- %s\n",strerror(errno));
int rowcap = 0;
double *rowptr;
while (fgets(line, sizeof(line), f) != NULL) {
// dynamically calculate number of columns by probing the first row
if (arr->colmax == 0)
arr->colmax = colcalc(line);
// expand the array size
if (arr->rowmax >= rowcap) {
rowcap += 100;
arr->data = realloc(arr->data,
sizeof(*arr->data) * rowcap * arr->colmax);
if (arr->data == NULL)
sysfault("realloc failure -- %s\n",strerror(errno));
}
// point to the current row we want to fill
rowptr = &arr->data[arr->rowmax * arr->colmax];
char *cp = line;
for (int colidx = 0; colidx < arr->colmax; ++colidx) {
if (*cp == 0)
sysfault("line too short -- rowmax=%d colidx=%d\n",
arr->rowmax,colidx);
// decode the number
rowptr[colidx] = strtod(cp,&cp);
// check the trailing character
switch (*cp) {
case ',': // middle of the line number
++cp;
break;
case '\n': // last number on line
++cp;
break;
case 0: // broken last line (still okay)
break;
default:
sysfault("syntax error -- '%s'\n",cp);
break;
}
}
++arr->rowmax;
}
// trim array to actual size used
rowcap = arr->rowmax;
arr->data = realloc(arr->data,sizeof(*arr->data) * rowcap * arr->colmax);
if (arr->data == NULL)
sysfault("realloc trim failure -- %s\n",strerror(errno));
return arr;
}
void
arrprt(const arr_t *arr)
{
const double *rowptr = arr->data;
for (int rowidx = 0; rowidx < arr->rowmax; ++rowidx,
rowptr += arr->colmax) {
for (int colidx = 0; colidx < arr->colmax; ++colidx)
printf(" %g",rowptr[colidx]);
printf("\n");
}
}
int
main(void)
{
FILE *f;
f = fopen("WethData.csv", "r");
if (f == NULL)
sysfault("unable to open file -- %s\n",strerror(errno));
arr_t *arr = arrload(f);
fclose(f);
arrprt(arr);
return 0;
}
UPDATE:
After going through your code I still have some uncertainties. For one the use of the arrprt function?
That function just loops through the array and prints the elements. As an example of array element access. More on this below.
For another your use of the "->" opperator?
This is the arrow operator. It is basic C coding. There are other SO questions that detail this. But, I'd look at a good C book (e.g. K&R). Here are some simple examples. They all do the same thing (e.g. print the array element that has index 3):
double data[5];
printf("%g\n",data[3]);
double *dptr = data;
printf("%g\n",dptr[3]);
printf("%g\n",*(dptr + 3));
struct arr {
double data[5];
};
struct arr arr;
printf("%g\n",arr.data[3]);
struct arr *ap = &arr;
printf("%g\n",ap->data[3]);
And lastly how would I access a specific box in the array (e.g. row 300, col 5).
There are a few different ways to do this. I've improved my example code to show the different ways. You can define a few macros with the -D compiler option to get the different ways (e.g. -DUSEMACRO and/or -USEFNC).
You could also use cpp to get the macro output. I've added the USECPP as a convenience. So, to look at macro output (e.g.):
cpp -DUSECPP x.c > xstd.i
cpp -DUSECPP -DUSEMACRO x.c > xmac.i
cpp -DUSECPP -DUSEFNC x.c > xfnc.i
cpp -DUSECPP -DUSEMACRO -DUSEFNC x.c > xmacfnc.i
You can also add -DUSEPRT=n where n is 1-4
Anyway, here is the full code:
#ifndef USECPP
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#endif
// USEMACRO -- select access method
// 0 - index calculation in arrdata function
// 1 - index calculation in ARRDATA macro
//
// USEFNC -- select access method for arrprt2/arrprt3 functions
// 0 - use ARRDATA macro
// 1 - use arrdata
//
// USEPRT -- select arrprt* function to use
// 0-4
#ifndef USEPRT
#define USEPRT 1
#endif
#define sysfault(_fmt...) \
do { \
printf(_fmt); \
exit(1); \
} while (0)
typedef struct {
int rowmax;
int colmax;
double *data;
} arr_t;
// ARRDATA -- access individual array elements
#if USEMACRO
#define ARRDATA(_arr,_rowidx,_colidx) \
(_arr)->data[((_rowidx) * (_arr)->colmax) + (_colidx)]
#else
#define ARRDATA(_arr,_rowidx,_colidx) \
*arrdata(_arr,_rowidx,_colidx)
#endif
// arrdata -- point to given data address
static inline double *
arrdata(const arr_t *arr,int rowidx,int colidx)
{
#if USEMACRO
return &ARRDATA(arr,rowidx,colidx);
#else
return &arr->data[(rowidx * arr->colmax) + colidx];
#endif
}
// ARRDEF -- define 2D array (_advanced_ usage)
#define ARRDEF(_arr,_sym) \
double (*_sym)[(_arr)->colmax] = (__typeof__(_sym)) (_arr)->data
// colcalc -- get number of columns in csv file
#ifndef USECPP
int
colcalc(const char *line)
{
int colmax = 1;
// count the number of commas
while (1) {
line = strchr(line,',');
if (line == NULL)
break;
++line;
++colmax;
}
return colmax;
}
#endif
// arrload -- read in array from .csv file
#ifndef USECPP
arr_t *
arrload(FILE *f)
{
char line[10000];
arr_t *arr;
arr = calloc(1,sizeof(*arr));
if (arr == NULL)
sysfault("calloc failure -- %s\n",strerror(errno));
int rowcap = 0;
double *rowptr;
while (fgets(line, sizeof(line), f) != NULL) {
// dynamically calculate number of columns by probing the first row
if (arr->colmax == 0)
arr->colmax = colcalc(line);
// expand the array size
if (arr->rowmax >= rowcap) {
rowcap += 100;
arr->data = realloc(arr->data,
sizeof(*arr->data) * rowcap * arr->colmax);
if (arr->data == NULL)
sysfault("realloc failure -- %s\n",strerror(errno));
}
// point to the current row we which to fill
#if 0
rowptr = &arr->data[arr->rowmax * arr->colmax];
#else
rowptr = arrdata(arr,arr->rowmax,0);
#endif
char *cp = line;
for (int colidx = 0; colidx < arr->colmax; ++colidx) {
if (*cp == 0)
sysfault("line too short -- rowmax=%d colidx=%d\n",
arr->rowmax,colidx);
// decode the number
rowptr[colidx] = strtod(cp,&cp);
// check the trailing character
switch (*cp) {
case ',': // middle of the line number
++cp;
break;
case '\n': // last number on line
++cp;
break;
case 0: // broken last line (still okay)
break;
default:
sysfault("syntax error -- '%s'\n",cp);
break;
}
}
++arr->rowmax;
}
// trim array to actual size used
rowcap = arr->rowmax;
arr->data = realloc(arr->data,sizeof(*arr->data) * rowcap * arr->colmax);
if (arr->data == NULL)
sysfault("realloc trim failure -- %s\n",strerror(errno));
return arr;
}
#endif
// arrprt1 -- print array (original)
void
arrprt1(const arr_t *arr)
{
const double *rowptr = arr->data;
for (int rowidx = 0; rowidx < arr->rowmax; ++rowidx,
rowptr += arr->colmax) {
for (int colidx = 0; colidx < arr->colmax; ++colidx)
printf(" %g",rowptr[colidx]);
printf("\n");
}
}
// arrprt2 -- print array (use arrdata function and pointers)
void
arrprt2(const arr_t *arr)
{
const double *rowptr;
const double *rowend;
for (int rowidx = 0; rowidx < arr->rowmax; ++rowidx) {
// point to start of the row
rowptr = arrdata(arr,rowidx,0);
// point to one past the end of the row (either of these work)
#if USEFNC
rowend = arrdata(arr,rowidx,arr->colmax);
#else
rowend = rowptr + arr->colmax;
#endif
for (; rowptr < rowend; ++rowptr)
printf(" %g",*rowptr);
printf("\n");
}
}
// arrprt3 -- print array (slow, use arrdata/ARRDATA each time)
void
arrprt3(const arr_t *arr)
{
for (int rowidx = 0; rowidx < arr->rowmax; ++rowidx) {
for (int colidx = 0; colidx < arr->colmax; ++colidx) {
#if USEFNC
printf(" %g",*arrdata(arr,rowidx,colidx));
#else
printf(" %g",ARRDATA(arr,rowidx,colidx));
#endif
}
printf("\n");
}
}
// arrprt4 -- print array (slow, use ARRDEF)
void
arrprt4(const arr_t *arr)
{
ARRDEF(arr,data);
for (int rowidx = 0; rowidx < arr->rowmax; ++rowidx) {
for (int colidx = 0; colidx < arr->colmax; ++colidx)
printf(" %g",data[rowidx][colidx]);
printf("\n");
}
}
#ifndef USECPP
int
main(void)
{
FILE *f;
f = fopen("WethData.csv", "r");
if (f == NULL)
sysfault("unable to open file -- %s\n",strerror(errno));
arr_t *arr = arrload(f);
fclose(f);
switch (USEPRT) {
case 1:
arrprt1(arr);
break;
case 2:
arrprt2(arr);
break;
case 3:
arrprt3(arr);
break;
case 4:
arrprt4(arr);
break;
}
return 0;
}
#endif
UPDATE #2:
Here are the outputs of the modified source, run through cpp from the cpp commands above.
Here is xstd.i:
typedef struct {
int rowmax;
int colmax;
double *data;
} arr_t;
static inline double *
arrdata(const arr_t *arr, int rowidx, int colidx)
{
return &arr->data[(rowidx * arr->colmax) + colidx];
}
void
arrprt1(const arr_t *arr)
{
const double *rowptr = arr->data;
for (int rowidx = 0; rowidx < arr->rowmax; ++rowidx, rowptr += arr->colmax) {
for (int colidx = 0; colidx < arr->colmax; ++colidx)
printf(" %g", rowptr[colidx]);
printf("\n");
}
}
void
arrprt2(const arr_t *arr)
{
const double *rowptr;
const double *rowend;
for (int rowidx = 0; rowidx < arr->rowmax; ++rowidx) {
rowptr = arrdata(arr, rowidx, 0);
rowend = rowptr + arr->colmax;
for (; rowptr < rowend; ++rowptr)
printf(" %g", *rowptr);
printf("\n");
}
}
void
arrprt3(const arr_t *arr)
{
for (int rowidx = 0; rowidx < arr->rowmax; ++rowidx) {
for (int colidx = 0; colidx < arr->colmax; ++colidx) {
printf(" %g", *arrdata(arr, rowidx, colidx));
}
printf("\n");
}
}
void
arrprt4(const arr_t *arr)
{
double (*data)[(arr)->colmax] = (__typeof__(data)) (arr)->data;
for (int rowidx = 0; rowidx < arr->rowmax; ++rowidx) {
for (int colidx = 0; colidx < arr->colmax; ++colidx)
printf(" %g", data[rowidx][colidx]);
printf("\n");
}
}
Here is xmac.i:
typedef struct {
int rowmax;
int colmax;
double *data;
} arr_t;
static inline double *
arrdata(const arr_t *arr, int rowidx, int colidx)
{
return &(arr)->data[((rowidx) * (arr)->colmax) + (colidx)];
}
void
arrprt1(const arr_t *arr)
{
const double *rowptr = arr->data;
for (int rowidx = 0; rowidx < arr->rowmax; ++rowidx, rowptr += arr->colmax) {
for (int colidx = 0; colidx < arr->colmax; ++colidx)
printf(" %g", rowptr[colidx]);
printf("\n");
}
}
void
arrprt2(const arr_t *arr)
{
const double *rowptr;
const double *rowend;
for (int rowidx = 0; rowidx < arr->rowmax; ++rowidx) {
rowptr = arrdata(arr, rowidx, 0);
rowend = rowptr + arr->colmax;
for (; rowptr < rowend; ++rowptr)
printf(" %g", *rowptr);
printf("\n");
}
}
void
arrprt3(const arr_t *arr)
{
for (int rowidx = 0; rowidx < arr->rowmax; ++rowidx) {
for (int colidx = 0; colidx < arr->colmax; ++colidx) {
printf(" %g", (arr)->data[((rowidx) * (arr)->colmax) + (colidx)]);
}
printf("\n");
}
}
void
arrprt4(const arr_t *arr)
{
double (*data)[(arr)->colmax] = (__typeof__(data)) (arr)->data;
for (int rowidx = 0; rowidx < arr->rowmax; ++rowidx) {
for (int colidx = 0; colidx < arr->colmax; ++colidx)
printf(" %g", data[rowidx][colidx]);
printf("\n");
}
}
Here is xfnc.i:
typedef struct {
int rowmax;
int colmax;
double *data;
} arr_t;
static inline double *
arrdata(const arr_t *arr, int rowidx, int colidx)
{
return &arr->data[(rowidx * arr->colmax) + colidx];
}
void
arrprt1(const arr_t *arr)
{
const double *rowptr = arr->data;
for (int rowidx = 0; rowidx < arr->rowmax; ++rowidx, rowptr += arr->colmax) {
for (int colidx = 0; colidx < arr->colmax; ++colidx)
printf(" %g", rowptr[colidx]);
printf("\n");
}
}
void
arrprt2(const arr_t *arr)
{
const double *rowptr;
const double *rowend;
for (int rowidx = 0; rowidx < arr->rowmax; ++rowidx) {
rowptr = arrdata(arr, rowidx, 0);
rowend = arrdata(arr, rowidx, arr->colmax);
for (; rowptr < rowend; ++rowptr)
printf(" %g", *rowptr);
printf("\n");
}
}
void
arrprt3(const arr_t *arr)
{
for (int rowidx = 0; rowidx < arr->rowmax; ++rowidx) {
for (int colidx = 0; colidx < arr->colmax; ++colidx) {
printf(" %g", *arrdata(arr, rowidx, colidx));
}
printf("\n");
}
}
void
arrprt4(const arr_t *arr)
{
double (*data)[(arr)->colmax] = (__typeof__(data)) (arr)->data;
for (int rowidx = 0; rowidx < arr->rowmax; ++rowidx) {
for (int colidx = 0; colidx < arr->colmax; ++colidx)
printf(" %g", data[rowidx][colidx]);
printf("\n");
}
}
Here is xmacfnc.i:
typedef struct {
int rowmax;
int colmax;
double *data;
} arr_t;
static inline double *
arrdata(const arr_t *arr, int rowidx, int colidx)
{
return &(arr)->data[((rowidx) * (arr)->colmax) + (colidx)];
}
void
arrprt1(const arr_t *arr)
{
const double *rowptr = arr->data;
for (int rowidx = 0; rowidx < arr->rowmax; ++rowidx, rowptr += arr->colmax) {
for (int colidx = 0; colidx < arr->colmax; ++colidx)
printf(" %g", rowptr[colidx]);
printf("\n");
}
}
void
arrprt2(const arr_t *arr)
{
const double *rowptr;
const double *rowend;
for (int rowidx = 0; rowidx < arr->rowmax; ++rowidx) {
rowptr = arrdata(arr, rowidx, 0);
rowend = arrdata(arr, rowidx, arr->colmax);
for (; rowptr < rowend; ++rowptr)
printf(" %g", *rowptr);
printf("\n");
}
}
void
arrprt3(const arr_t *arr)
{
for (int rowidx = 0; rowidx < arr->rowmax; ++rowidx) {
for (int colidx = 0; colidx < arr->colmax; ++colidx) {
printf(" %g", *arrdata(arr, rowidx, colidx));
}
printf("\n");
}
}
void
arrprt4(const arr_t *arr)
{
double (*data)[(arr)->colmax] = (__typeof__(data)) (arr)->data;
for (int rowidx = 0; rowidx < arr->rowmax; ++rowidx) {
for (int colidx = 0; colidx < arr->colmax; ++colidx)
printf(" %g", data[rowidx][colidx]);
printf("\n");
}
}
Related
I got this but it I can't seem to make it work, tried everything I could think of.
#include <stdio.h>
#include <stdlib.h>
void alocare_vector(int *v, int nr, int elem)
{
int *v1;
if ((v1 = realloc(v, nr * sizeof(int))) == NULL)
{
printf("Memorie insuficienta");
free(v);
exit(EXIT_FAILURE);
}
v = v1;
v[nr - 1] = elem;
}
int main()
{
int a[100][100];
int n, *v = NULL, i, j, k, l, ok = 0, nr = 0;
printf("Number de elements n:");
scanf("%d", &n);
for (i = 0; i < n; i++)
for (j = 0; j < n; j++)
scanf("%d", &a[i][j]);
for (k = 0; k < n; k++)
{
for (l = 0; l < n; l++)
{
for (i = 0; i < n; i++)
for (j = 0; j < n; j++)
if (a[k][l] == a[i][j] && (k != i && l != j))
ok = 1;
if (ok == 0)
{
nr++;
alocare_vector(v, nr, a[k][l]);
}
ok = 0;
}
}
if (nr > 0)
{
printf("Elements:");
for (i = 0; i < nr; i++)
{
printf("%d ", v[i]);
}
}
free(v);
}
Basically, I need to create a matrix, ans print the elements that appear only once using an array with dynamic memory allocation.
one simple fix is to declare the "int * v" as a global variable and modify the function as alocare_vector(int nr, int elem)
now using a hash table you can store the numbers in the array, below is the your implementation just a bit modified.
#include <stdio.h>
#include <stdlib.h>
int hash[1000]={0};
int * v=NULL;
void alocare_vector(int nr, int elem)
{
int *v1;
if ((v1 = (int*)realloc(v, nr * sizeof(int))) == NULL)
{
printf("Memorie insuficienta");
free(v);
exit(EXIT_FAILURE);
}
v = v1;
v[nr - 1] = elem;
}
int main()
{
int a[100][100];
int n, i, j, nr = 0;
printf("Number de elements n:");
scanf("%d", &n);
for (i = 0; i < n; i++)
{
for (j = 0; j < n; j++)
{
scanf("%d", &a[i][j]);
++hash[a[i][j]];
}
}
for (i = 0; i < n; i++)
{
for (j = 0; j < n; j++)
{
if(hash[a[i][j]]==1)
{
nr++;
alocare_vector(nr, a[i][j]);
}
}
}
if (nr > 0)
{
printf("Elements:");
for (i = 0; i < nr; i++)
{
printf("%d ", v[i]);
}
}
free(v);
}
When calling a your funtion you pass a copy of the pointer. Therfore any modifications to this local copy of the pointer will not affect the copy in main. Therfore you need a refrence or pointer to the pointer in main.
void alocare_vector(int **v, int nr, int elem)
{
...
*v = v1;
}
Here you have brut force example how to generate array of distinct elements of the 2D array:
typedef struct
{
size_t length;
int data[];
}data_t;
data_t *add_element(data_t *arr, int element)
{
size_t newsize = arr ? arr -> length : 0;
arr = realloc(arr, newsize * sizeof(arr -> data[0]) + sizeof(*arr));
if(arr)
{
arr -> length = newsize;
arr -> data[newsize - 1] = element;
}
return arr;
}
int isPresent(size_t rows, size_t cols, size_t vrow, size_t vcol, int (*array)[cols])
{
int val = array[vrow][vcol];
for(size_t row = 0; row < rows; row++)
for(size_t col = 0; col < cols; col++)
{
if(vcol == col && vrow == row) continue;
if(array[row][col] == val)
{
return 1;
}
}
return 0;
}
data_t *distinctElements(size_t rows, size_t cols, int (*array)[cols])
{
data_t *dist = NULL;
for(size_t row = 0; row < rows; row++)
{
for(size_t col = 0; col < cols; col++)
{
if(!isPresent(rows, cols, row, col, array))
{
data_t *tmp = add_element(dist, array[row][col]);
if(tmp) dist = tmp;
else { /* error handling */}
}
}
}
return dist;
}
I have a problem with increasing C[] array from 6 to 10 I've faced with heap corruption problem by realloc(). I have a following code of Big M metod:
#include <stdio.h>
#include <stdlib.h>
int * mnInit(FILE * );
double * * ReadA(FILE * , int, int);
double * ReadVector(FILE * , int);
int * condtxt(FILE *, int );
void Artif_counter(int* , int *, int);
void reallocationA(double**, int* , int , int);
void increaseA(int*, double**, int, int, int);
void increaseC(double *, int);
int main(int argc, char * argv[]) {
FILE * file1 = fopen("C.txt", "r");
FILE * file4 = fopen("A.txt", "r");
FILE * file5 = fopen("Agetmn.txt", "r");
FILE * file6 = fopen("cond.txt", "r");
int * ptr_mn;
ptr_mn = mnInit(file5);
int n = * (ptr_mn);
int m = * (ptr_mn + 1);
double * * A;
A = ReadA(file4, n, m);
double * C;
C = ReadVector(file1, n);
int * cond;
cond = condtxt(file6, m);
for(int i = 0; i < m; i++){
}
//--------------------------------------------------
int BAcounter = 0;
Artif_counter(cond, &BAcounter, m);
printf("\n Basys and Artifical variable = %d", BAcounter);
reallocationA(A, &n, m, BAcounter);
increaseA(cond, A, n, m, BAcounter);
this function dont't working
increaseC(C, n);
When I trying to print arrays: the A[][] was printed right while C[] array was printed by unknown numbers and after the program Mmetod.exe was closed with problem: A heap has been corrupted (parameters: 0x00007FFCA0C1F6B0).
// count of basys and artif
//------------------------------------------------After Adding a new columns:
printf("\n A[][] ARRAY:\n");
for (int i = 0; i < m; i++) {
printf("%d ", i);
for (int j = 0; j < n; j++) {
printf(" %.3f ", A[i][j]);
}
printf("\n");
}
printf("\n\tVECTOR C[]:\n");
for (int i = 0; i < n; i++) {
printf("%lf ", C[i]);
}
fclose(file1);
fclose(file4);
fclose(file5);
fclose(file6);
free(C);
for (int i = 0; i < m; i++) {
free(A[i]);
}
free(A);
printf("\n\n");
system("pause");
return 0;
}
int * mnInit(FILE * file) {
int c;
int digit = 0;
int column = 0;
int * mnArray = malloc(2 * sizeof( * mnArray));
if (file == NULL) perror("Warning!");
else {
while (!feof(file)) {
c = fgetc(file);
if (c == ';') {
column++;
}
if (c == ' ') {
digit++;
}
}
}
* (mnArray) = (digit / column) + 1; * (mnArray + 1) = column;
return mnArray;
}
double * * ReadA(FILE * file, int n, int m) {
double * * A = malloc(m * sizeof( * A));
for (int i = 0; i < m; i++) {
A[i] = malloc(n * sizeof( * A[i]));
}
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
//fscanf(file ,"%lf ", &(*(*(A + i) + j)));
fscanf(file, "%lf ", & A[i][j]);
}
fscanf(file, "\n");
}
return A;
}
double * ReadVector(FILE * file, int m) { // ++++
double * Vector = malloc(m * sizeof( * Vector));
for (int i = 0; i < m; i++) {
fscanf(file, "%lf ", Vector + i);
}
return Vector;
}
int* condtxt(FILE * file, int m){
int * condA = malloc(m * sizeof(*condA));
for(int i = 0; i < m; i++){
fscanf(file, "%d", &condA[i]);
}
return condA;
}
void Artif_counter(int * cond, int *k, int m){
for(int i = 0; i < m; i++){
if(cond[i] == -1){
(*k)++;
}
if(cond[i] == 0){
(*k)++;
}
if(cond[i] == 1){
*k = (*k) + 2;
}
}
}
void reallocationA(double** A, int* n, int m, int k){
double * tmp = NULL;
for(int i = 0; i < m; i++){
tmp = realloc(A[i], ((*n) + k)*sizeof(*A[i]));
if(tmp){
A[i] = tmp;
tmp = NULL;
} else{
printf("Error! Memory isn't reallocated'");
tmp = NULL;
}
}
(*n) = (*n) + k;
}
void increaseA(int* cond, double** A, int n, int m, int k){
int presentcol = n-k;
for(int i = 0; i < m; i++){
if(cond[i] == -1){
for(int j = 0; j < m; j++){
if(j == i){
A[j][presentcol] = 1;
} else {
A[j][presentcol] = 0;
}
}
presentcol++;
}
if(cond[i] == 0){
for(int j = 0; j < m; j++){
if(j == i){
A[j][presentcol] = 1;
} else {
A[j][presentcol] = 0;
}
}
presentcol++;
}
if(cond[i] == 1){
for(int j = 0; j < m; j++){
if(j == i){
A[j][presentcol] = 1;
A[j][presentcol + 1] = -1;
} else {
A[j][presentcol] = 0;
A[j][presentcol + 1] = 0;
}
}
presentcol = presentcol + 2;
}
}
}
When I wanted to increase an array in a simple code by this function it've done and I don't understand why(
A GNU debugger rewiev: 0 warning: Critical error detected c0000374
void increaseC(double * C, int n){
double * tmp;
tmp = realloc(C, (n)*sizeof(*C)); // found out that realloc function caused an error
if(!tmp){
printf("Error");
} else{
C = tmp;
}
tmp = NULL;
}
my output values
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define W 160
#define H 105
struct dungeons {
int x;
int y;
int width;
int height;
};
void randomNumberGenerator(int seed);
void makeGameBoard(int gameBoard[W][H]);
void makeDungeonRooms(struct dungeons d[10]);
void printGame(int gameBoard[W][H]);
int main(int argc, char *argv[]) {
int gameBoard[W][H];
//int gameBoard[160][105] = {2};
struct dungeons d[10];
makeGameBoard(gameBoard);
makeDungeonRooms(d);
printGame(gameBoard);
return 0;
}
void randomNumberGenerator(int seed) {
srand(seed);
}
void makeGameBoard(int gameBoard[160][105]) {
int i;
int j;
for (j = 0; j < 105; j++) {
for (i = 0; i < 160; i++) {
gameBoard[i][j] = 2;
//gameBoard[i][j] = 2;
/*
if (j == 0) {
gameBoard[i][j] = 2;
} else
if (j == 104) {
gameBoard[i][j] = 2;
} else
if (i == 0) {
gameBoard[i][j] = 2;
} else
if (i == 159) {
gameBoard[i][j] = 2;
} else {
gameBoard[i][j] = 4;
}
*/
}
}
gameBoard[0][1] = 2;
gameBoard[0][0] = 2;
gameBoard[159][0] = 3;
}
void makeDungeonRooms(struct dungeons d[10]) {
int i;
for (i = 0; i < W; i++) {
d[i].x = 0;
d[i].y = 0;
d[i].width = 0;
d[i].height = 0;
}
}
void printGame(int g[W][H]) {
int i;
int j;
for (i = 0; i < W; i++) {
for (j = 0; j < H; j++) {
printf("%d", g[i][j]);
/*
if (g[i][j] == 2) {
printf("|");
} else
if (g[i][j] == 1) {
printf("X");
} else {
printf(" ");
}
*/
}
printf("\n");
}
}
I'm making a grid. But the first 5 rows and half of the 6th row, when printed output the value 0. I'm setting everything to 2 in the for loop, and even after when I try to manually change the value, it still doesn't. The last one [159][0] works but nothing in the first 5 rows and half of the 6th seem to work. They stay 0. Why?
The problem is here:
void makeDungeonRooms(struct dungeons d [10]){
int i;
for(i = 0; i< W; i++){
d[i].x = 0;
d[i].y = 0;
d[i].width = 0;
d[i].height = 0;
}
}
where #define W 160. Accessing array out of bound can trigger undefined behavior. It can trigger a segmentation fault, it can remain unnoticed for a long time or alter the output of the program in very strange ways. Here, zeroing the dungeons also partly zeroed the gameBoard. Keep it that way: your game is going to be hilarious!
I have been programming this multiplethreaded matrix multiplication.
Somehow the programm works, but it does not give me the values of the result matrix.
Here it is the code:
#include <stdio.h>
#include <pthread.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
int rowA, rowB, colA, colB;
int myNrThreads = 0;
double **matrixA, **matrixB, **matrixOut;
void *multiplyThread (void *param);
void fillAndCheckMatrice(double **matrix, FILE *myFile, int row, int column) {
char *line = NULL;
char *p;
ssize_t read;
int i = 0, j = 0;
size_t length = 0;
getline (&line, &length, myFile);
p = strtok(line, " ");
row = atoi(p);
p = strtok(NULL, " ");
column = atoi(p);
printf("%d, %d\n", row, column);
matrix = malloc(row * sizeof(double*));
for (j = 0; j < row; ++j) {
matrix[j] = malloc(column * sizeof(double));
}
i = 0;
while ((read = getline (&line, &length, myFile)) != -1) {
j = 0;
p = strtok(line, " ");
while (p != NULL) {
matrix[i][j] = atof(p);
++j;
p = strtok(NULL, " ");
}
++i;
}
free(line);
}
int main (int argc, char* argv[])
{
pthread_t *myThread;
int counter, j, r;
FILE *fileA = fopen("matrixA.txt", "r");
FILE *fileB = fopen ("matrixB.txt", "r");
if (argc!=2)
{
printf("Usage: %s number_of_threads\n",argv[0]);
exit(-1);
}
myNrThreads = (atoi)(argv[1]);
fillAndCheckMatrice(matrixA, fileA, rowA, colA);
fillAndCheckMatrice(matrixB, fileB, rowB, colB);
matrixOut = malloc(rowA * sizeof(double*));
for (counter = 0; counter < rowA; ++counter) {
matrixOut[counter] = malloc (colB * sizeof(double));
}
myThread = malloc(myNrThreads * sizeof(pthread_t));
for (counter = 1; counter < myNrThreads; ++counter) {
r = pthread_create (&myThread[counter], NULL, multiplyThread, (void*)counter);
if (r != 0 ) {
printf ("No threads create!");
free (myThread);
exit(-1);
}
}
multiplyThread(0);
for (counter = 1; counter < myNrThreads; ++counter) {
pthread_join(myThread[counter], NULL);
}
for (counter = 0; counter < rowA; ++counter) {
for (j = 0; j < colB; ++j) {
printf ("%.5f ", matrixOut[counter][j]);
}
printf("\n");
}
fclose(fileA);
fclose(fileB);
free(myThread);
free(matrixA);
free(matrixB);
free(matrixOut);
return 0;
}
/*
* The method gets on the first line the dimensions of the matrice.
* While filling every postion of our matrice, we control
* if the given dimensions are the real dimensions of the matrice.
* Everything is read from the .txt file, produced from our python
* generator.
*
*/
void *multiplyThread(void *param){
int myParam = (int)param;
int limitBegin = (myParam * rowA) / myNrThreads;
int limitEnd = ((myParam + 1) * rowA) / myNrThreads;
int counterI, counterJ, counterK;
for (counterI = limitBegin; counterI < rowA; ++counterI) {
for (counterJ = 0; counterJ < colB; ++counterJ) {
matrixOut[counterI][counterJ] = 0;
for (counterK = 0; counterK < rowB; ++counterK) {
matrixOut[counterI][counterJ] +=matrixA[counterI][counterK] * matrixB[counterK][counterJ];
}
}
}
printf("finished slice %d\n", myParam);
return 0;
}
Any idea why???
Thanx in advance.
PS: at the pthread_create I get a warning at (void*)counter btw
EDIT:
matrixA and matrixB are given through matrixA.txt and matrixB.txt. They are read and the values are taken from that.
One of the txt file would look like this:
2 2 // The dimensions of the matrice
12 14
13 15
EDIT3: The new one. Here I get segmentation fault 11:
#include <stdio.h>
#include <pthread.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
void *multiplyThread (void *param);
int rowA, rowB, colA, colB;
int myNrThreads = 0;
double **matrixA, **matrixB, **matrixOut;
void fillAndCheckMatrice(double **matrix, FILE *myFile, int ID) {
char *line = NULL;
char *p;
int row, column;
ssize_t read;
int i = 0, j = 0;
size_t length = 0;
getline (&line, &length, myFile);
p = strtok(line, " ");
row = atoi(p);
p = strtok(NULL, " ");
column = atoi(p);
printf("%d, %d\n", row, column);
if (ID == 1) {
rowA = row;
colA = column;
} else if (ID == 2) {
rowB = row;
colB = column;
}
matrix = malloc(row * sizeof(double*));
for (j = 0; j < row; ++j) {
matrix[j] = malloc(column * sizeof(double));
}
i = 0;
while ((read = getline (&line, &length, myFile)) != -1) {
j = 0;
p = strtok(line, " ");
while (p != NULL) {
matrix[i][j] = atof(p);
++j;
p = strtok(NULL, " ");
}
++i;
}
free(line);
}
int main (int argc, char* argv[])
{
pthread_t *myThread;
int counter, j, r;
FILE *fileA = fopen("matrixA.txt", "r");
FILE *fileB = fopen ("matrixB.txt", "r");
if (argc!=2)
{
printf("Usage: %s number_of_threads\n",argv[0]);
exit(-1);
}
myNrThreads = (atoi)(argv[1]);
fillAndCheckMatrice(matrixA, fileA, 1);
fillAndCheckMatrice(matrixB, fileB, 2);
matrixOut = malloc(rowA * sizeof(double*));
for (counter = 0; counter < rowA; ++counter) {
matrixOut[counter] = malloc (colB * sizeof(double));
}
for (counter = 0; counter < rowA; ++counter) {
for (j = 0; j < colB; ++j) {
printf ("%.5f ", matrixOut[counter][j]);
}
printf("\n");
}
myThread = malloc(myNrThreads * sizeof(pthread_t));
for (counter = 1; counter < myNrThreads; ++counter) {
printf("%d", counter);
if (pthread_create (&myThread[counter], NULL, multiplyThread, (void*)(intptr_t)counter) != 0) {
printf ("No threads create!");
free (myThread);
exit(-1);
}
}
for (counter = 0; counter < rowA; ++counter) {
for (j = 0; j < colB; ++j) {
printf ("%.5f ", matrixA[counter][j]);
}
printf("\n");
}
multiplyThread(0);
for (counter = 1; counter < myNrThreads; ++counter) {
pthread_join(myThread[counter], NULL);
}
fclose(fileA);
fclose(fileB);
free(myThread);
free(matrixA);
free(matrixB);
free(matrixOut);
return 0;
}
/*
* The method gets on the first line the dimensions of the matrice.
* While filling every postion of our matrice, we control
* if the given dimensions are the real dimensions of the matrice.
* Everything is read from the .txt file, produced from our python
* generator.
*
*/
void *multiplyThread(void *param){
int myParam = (int)param;
int limitBegin = (myParam * rowA) / myNrThreads;
int limitEnd = ((myParam + 1) * rowA) / myNrThreads;
int counterI, counterJ, counterK;
for (counterI = limitBegin; counterI < rowA; ++counterI) {
for (counterJ = 0; counterJ < colB; ++counterJ) {
matrixOut[counterI][counterJ] = 0;
for (counterK = 0; counterK < rowB; ++counterK) {
matrixOut[counterI][counterJ] +=matrixA[counterI][counterK] * matrixB[counterK][counterJ];
}
}
}
printf("finished slice %d\n", myParam);
return 0;
}
There are quite a few problems in the question code. Perhaps the best 'answer' would be to carefully walk through the code and point out some of the issues.
First, consider the following:
int rowA, rowB, colA, colB;
Nothing really wrong with the above line, until (later in main):
fillAndCheckMatrice(matrixA, fileA, rowA, colA);
fillAndCheckMatrice(matrixB, fileB, rowB, colB);
The above lines pass the 'values' of 'rowA', 'colA' 'rowB' and 'colB'. Being that these variables have no established values, it is obvious that there is trouble in the code.
Most likely, the intention is to initialize these values inside the 'fillAndCheckMatrice()' function. However, in order to initialize these variables, the 'address' of the variables must be passed into 'fillAndCheckMatrice()', (not their 'values'). Perhaps something like this:
fillAndCheckMatrice(matrixA, fileA, &rowA, &colA);
fillAndCheckMatrice(matrixB, fileB, &rowB, &colB);
Then, of course, the 'fillAndCheckMatrice()' will have to be modified as well; from:
void fillAndCheckMatrice(double **matrix, FILE *myFile, int row, int column) {
To:
void fillAndCheckMatrice(double **matrix, FILE *myFile, int *row, int *column) {
And then, of course, every reference to 'row' and 'column' will now have to deal with a pointer to a variable, instead of the variable value. Hence these:
row = atoi(p);
column = atoi(p);
printf("%d, %d\n", row, column);
Will have to change to these:
*row = atoi(p);
*column = atoi(p);
printf("%d, %d\n", *row, *column);
...and so forth...
matrix = malloc((*row) * sizeof(double*));
for (j = 0; j < *row; ++j) {
I will proceed debugging the question source upon request.
insdead of my static matrix i try to get 2d dynamic matrics
all i want to do is to change the init function so instead of using the defined heigh and width
it would init dynamicaly - please show me the how
void init(int board[][WIDTH], int rows) {
int x, y;
for (y = 0; y < rows; y++)
for (x = 0; x < WIDTH; x++)
board[y][x] = 0;
/* Scatter some live cells: */
board[10][25] = 1;
board[10][26] = 1;
board[10][27] = 1;
board[11][25] = 1;
board[12][26] = 1;
}
int main(void) {
int board[HEIGHT][WIDTH];
init(board, HEIGHT);
..
..
}
this is the code i wanted to use - please show me the right implamintation
without using #define WIDTH 50 #define HEIGHT 20
int **matrix_dyn(int n, int m)
{
int i = 0;
int j = 0;
printf ("please enter the horizontal size of the board \n");
scanf ("%d", &n);
printf ("please enter the vertical size of the board \n");
scanf ("%d", &m);
int **board = (int**)malloc(n * sizeof(int*));
printf("please enter the 0's or 1's to fill the matrix \n");
for (i = 0; i <= n; i++)
board[i] = (int*)malloc(m*sizeof(int));
for(i = 0; i <= n; i++)
{
for(j = 0; j <= m; j++)
scanf ("%d", &board[i][j]);
}
return board;
}
this is all my code:
#include <stdio.h>
#define WIDTH 50
#define HEIGHT 20
void init(int board[][WIDTH], int rows) {
int x, y;
for (y = 0; y < rows; y++)
for (x = 0; x < WIDTH; x++)
board[y][x] = 0;
/* Scatter some live cells: */
board[10][25] = 1;
board[10][26] = 1;
board[10][27] = 1;
board[11][25] = 1;
board[12][26] = 1;
}
void print(int board[][WIDTH], int rows, int cols)
{
int x, y;
char c;
for (y = 0; y < rows; y++) {
for (x = 0; x < cols; x++) {
if (board[y][x] == 1)
printf("X");
else
printf(" ");
}
printf("\n");
}
printf("Press any key to continue:\n");
getchar();
}
int count_neighbors(int board[][WIDTH], int rows,
int y, int x)
{
int i, j;
int result = 0;
for (i = -1; i <= 1; i++)
if ((y+i >= 0) && (y+i < rows))
for (j = -1; j <= 1; j++)
if ((x+j >= 0) && (x+j < WIDTH))
if ((i != 0) || (j != 0))
result += board[y+i][x+j];
return result;
}
int step(int board[][WIDTH], int rows) { // now returns a bool
int x, y;
int neighbors[HEIGHT][WIDTH];
int changed = 0; // save changes
for (y = 0; y < rows; y++)
for (x = 0; x < WIDTH; x++)
neighbors[y][x] = count_neighbors(board, rows, y, x);
for (y = 0; y < rows; y++)
for (x = 0; x < WIDTH; x++)
if (board[y][x] == 1) { /* Currently alive */
if (neighbors[y][x] < 2)
{
board[y][x] = 0; /* Death by boredom */
changed = 1; // change happened
}
else if (neighbors[y][x] > 3)
{
board[y][x] = 0; /* Death by overcrowding */
changed = 1; // change happened
}
}
else { /* Currently empty */
if (neighbors[y][x] == 3)
{
board[y][x] = 1;
changed = 1; // change happened
}
}
return changed; // return the status (changed yes/no?)
}
int main(void) {
int board[HEIGHT][WIDTH];
init(board, HEIGHT);
while (1) {
print(board, HEIGHT, WIDTH);
if(step(board, HEIGHT) == 0) // no change
break; // leave the loop
}
return 0;
}
Declare & allocate board like so:
int *board = malloc( n * m * sizeof(int) );
Then, anytime you wish to access board[x][y], use the following expression:
board[y*n+x]
Try using a struct, heres a simple implementation I wrote up (compiled using GCC, to support the constructor attribute.
// IntGrid.h
typedef struct intGrid_t {
int **data;
int rows;
int cols;
} *IntGridRef;
struct {
IntGridRef(* create)(int, int);
void (* print)(IntGridRef);
void (* free)(IntGridRef);
int **(* data)(IntGridRef);
int (* rows)(IntGridRef);
int (* cols)(IntGridRef);
} IntGrid;
// IntGrid.c
IntGridRef _intGrid_create(int rows, int cols);
void _intGrid_print(IntGridRef this);
void _intGrid_free(IntGridRef this);
int **_intGrid_data(IntGridRef this);
int _intGrid_rows(IntGridRef this);
int _intGrid_cols(IntGridRef this);
__attribute__((constructor))
static void intGrid_setup()
{
IntGrid.create = _intGrid_create;
IntGrid.print = _intGrid_print;
IntGrid.free = _intGrid_free;
IntGrid.data = _intGrid_data;
IntGrid.rows = _intGrid_rows;
IntGrid.cols = _intGrid_cols;
}
IntGridRef _intGrid_create(int rows, int cols)
{
IntGridRef this = calloc(1, sizeof(struct intGrid_t));
this->rows = rows;
this->cols = cols;
this->data = calloc(rows, sizeof(int *));
for (int i = 0; i < rows; i++) {
this->data[i] = calloc(cols, sizeof(int *));
}
return this;
}
void _intGrid_print(IntGridRef this)
{
printf("{\n");
for (int i = 0; i < this->rows; i++) {
printf(" { ");
for (int j = 0; j < this->cols; j++) {
printf("%i", this->data[i][j]);
if (j != this->cols - 1)
{
printf(", ");
}
}
printf(" }\n");
}
printf("}\n");
}
void _intGrid_free(IntGridRef this)
{
for (int i = 0; i < this->rows; i++) {
free(this->data[i]);
}
free(this->data);
free(this);
}
int **_intGrid_data(IntGridRef this)
{
return this->data;
}
int _intGrid_rows(IntGridRef this)
{
return this->rows;
}
int _intGrid_cols(IntGridRef this)
{
return this->cols;
}
Example Usage:
int main(int argc, char *argv[])
{
IntGridRef grid = IntGrid.create(10, 10);
for (int i = 0; i < IntGrid.rows(grid); i++) {
for (int j = 0; j < IntGrid.cols(grid); j++) {
IntGrid.data(grid)[i][j] = arc4random_uniform(10);
}
}
IntGrid.print(grid);
IntGrid.free(grid);
return 0;
}
You're basically there, but instead of having the compiler generate code to map [x][y] to a specific element in the memory allocated for board, you have to do the mapping yourself: board[x*h+y] or board[y*w+x] (where w is width & h is height); it doesn't matter which you choose, just be consistent (a function or macro would help here).