Read and write to dynamically allocated array - c

I have a text file containing a matrix N by 3 of float numbers. I need to read the matrix and put the data into a dynamically allocated array. I have the following code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define X_ 0
#define Y_ 0
#define Z_ 0
#define VERTEX_COUNT 3
void read_data(FILE* FILE_POINTER, float **GRID, int N_LINES)
{
int i = 0, j=0;
for(i = 0; i < N_LINES; i++)
{
for(j = 0; j < VERTEX_COUNT; j++)
{
if (!fscanf(FILE_POINTER, "%f", &GRID[i][j]))
break;
}
}
}
int find_length(FILE* FILE_POINTER)
{
int ch = 0;
int length = 0;
if(FILE_POINTER != NULL)
{
while(!feof(FILE_POINTER))
{
ch = fgetc(FILE_POINTER);
if(ch == '\n')
{
length++;
}
}
}
else
{
perror("File not found");
exit(EXIT_FAILURE);
}
return length;
}
int main()
{
/* Define variables needed*/
int i=0,j=0;
float** GRID_GEOM;
float** GRID_TOPO;
/* Open the files containing the data*/
FILE* FILE_GEOM = fopen("temporary_geom.txt","r");
FILE* FILE_TOPO = fopen("temporary_topo.txt","r");
/* Find length of the data set*/
int N_POINTS = find_length(FILE_GEOM);
int N_TRIANG = find_length(FILE_TOPO);
/* Dynamically allocate memory for each data set*/
GRID_GEOM = malloc(N_POINTS * sizeof(float*));
for (i = 0; i < N_POINTS; i++)
{
GRID_GEOM[i] = malloc(VERTEX_COUNT * sizeof(float));
}
GRID_TOPO = malloc(N_TRIANG * sizeof(float*));
for (i = 0; i < N_TRIANG; i++)
{
GRID_TOPO[i] = malloc(VERTEX_COUNT * sizeof(float));
}
/* Read data into the arrays*/
read_data(FILE_GEOM, GRID_GEOM, N_POINTS);
/* Close the files */
fclose(FILE_GEOM);
fclose(FILE_TOPO);
/* Free the memory allocated */
for (i = 0; i < N_POINTS; i++)
{
free(GRID_GEOM[i]);
}
free(GRID_GEOM);
for (i = 0; i < N_TRIANG; i++)
{
free(GRID_TOPO[i]);
}
free(GRID_TOPO);
}
When I try to access any position in the matrix GRID_GEOM, all values seem to be 0. I can't figure out why.

In function find_length, you read the whole file so when you pass the file pointer to read_data, it already points to the end of it.
You can either rewind the pointer, or close the file and reopen it again for parsing data.

Related

Reading a Structure using pointer second time gives segmentation fault error

When I read the second vector using vector_read() function or by intializing it to zero by usign vector_init_zero() I get segementation fault. I have searched it alot still not got the answer why it's happening. If I use only one pointer and don't initiallize it to 0 it works fine. Every other function works fine with single variable of structure pointer.
#include <stdio.h>
#include <stdlib.h>
typedef struct vector_s
{
int dim;
float *data_ptr;
} vector_type;
/* Allocate and initialize to 0 a vector with the given dimension */
void vector_init_zeros(vector_type *v_ptr, int dim)
{
v_ptr->dim = dim;
v_ptr->data_ptr = (float *)calloc(dim, sizeof(float));
#ifdef DEBUG
if (v_ptr->data_ptr == 0)
{
printf("vector_init_zeros error: calloc returned a null ptr\n");
exit(1);
}
#endif
}
/* Free up a vector that was allocated using vector_init_zeros */
void vector_deinit(vector_type *v_ptr)
{
v_ptr->dim = 0;
free(v_ptr->data_ptr);
v_ptr->data_ptr = 0;
}
/* Attempt to read a vector from stdin. */
/* Returns 1 if read successful and 0 otherwise */
int vector_read(vector_type *v_ptr)
{
int i;
float next;
for (i = 0; i < v_ptr->dim; i++)
{
if (scanf("%g\n", &next) != 1)
{
return 0;
}
v_ptr->data_ptr[i] = next;
}
return 1;
}
/* w = u + v */
void vector_add(vector_type *u_ptr, vector_type *v_ptr,
vector_type *w_ptr)
{
int i;
for (i = 0; i < v_ptr->dim; i++)
{
w_ptr->data_ptr[i] = u_ptr->data_ptr[i] + v_ptr->data_ptr[i];
}
}
/* v = cv */
void vector_scalar_mult(vector_type *v_ptr, float c)
{
int i;
for (i = 0; i < v_ptr->dim; i++)
{
v_ptr->data_ptr[i] = v_ptr->data_ptr[i] * c;
}
}
/* print the compondents of the given vector */
void vector_print(vector_type *v_ptr)
{
int i;
for (i = 0; i < v_ptr->dim; i++)
{
printf("%f ", v_ptr->data_ptr[i]);
}
printf("\n");
}
int main()
{
int dim;
int count = 0;
if (scanf("%d", &dim) != 1)
{
printf("Error reading the vector dimension from stdin\n");
exit(1);
}
vector_type *s,*t;
vector_init_zeros(s, dim);
vector_init_zeros(t, dim);
vector_read(s);
vector_read(t);
}
In main() where you declare s and t, you never initialize them. You can either declare them as structure variables and pass their addresses to the functions with the & 'address of' operator or allocate and deallocate them with malloc() and free() or equivalents.
int main(){
...
vector_type s, t;
...
vector_init_zeros(&s, dim);
vector_init_zeros(&t, dim);
vector_read(&s);
vector_read(&t);
}
or
int main(){
...
vector_type *s, *t;
s = (vector_type *) malloc(sizeof(vector_type));
t = (vector_type *) malloc(sizeof(vector_type));
...
free(s);
free(t);
}

variable sized object may not be initialized

I am getting the error variable sized object may not be initialized and I don't understand why.
Could someone show me how to fix this line?
int arr[size] = (int *)(augs->one);
Here is my code:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <pthread.h>
#include <assert.h>
int count = 0;
int cmpfunc(const void *a, const void *b) {
return (*(int*)a - *(int*)b);
}
struct structure {
int two;
int *one;
};
void *sort(void *augments) {
struct structure *augs = (struct structure*)augments;
int i = 0;
int size = 1;
size = augs->two;
int arr[size] = (int *)(augs->one);
//int *arr = (int *)data;
//printf("sizeof:%d\n", sizeof(arr));
qsort(arr, size, sizeof(int), cmpfunc);
printf("finaloutput:\n");
for (i = 0; i < size; i++) {
printf("%d ", arr[i]);
}
printf("\n");
return NULL;
}
int main(int argc, char *argv[]) {
FILE *myFile;
myFile = fopen("data.txt", "r");
// number of lines in file
char charicter;
for (charicter = getc(myFile); charicter != EOF; charicter = getc(myFile)) {
if (charicter == '\n') {
count++;
}
}
printf("count is %d\n", count);
int numberArray[count];
int i = 0;
if ((myFile = fopen("data.txt", "r"))) {
while ((fscanf(myFile, "%d", &numberArray[i]) != EOF)) {
++i;
}
fclose(myFile);
}
assert(argv[1] != NULL);
int num = atoi(argv[1]); //num equals number input
int arrayarray[num - 1][(count / num)];
int idx;
for (i = 0; i < (count); i++) {
printf("numberarray[%d]= %d\n", i, numberArray[i] /*[0],numberArray[i][1]*/);
}
for (i = 1; i < num + 1; i++) {
for (idx = 0; idx < (count / num); idx++) {
arrayarray[i - 1][idx] = numberArray[i * idx];
}
}
///*
for (i = 0; i < ((count / num)); i++) {
printf("arrayarray[0]=%d\n", arrayarray[0][i]);
}
//*/
int lastarray[((count / num) + (count % num))];
for (idx = 0; idx < ((count / num) + (count % num)); idx++) {
lastarray[idx] = numberArray[idx + ((count / num) * (num - 1))];
}
for (i = 0; i < ((((count / num) + (count % num)))); i++) {
printf("lastaray[%d]=%d\n", i, lastarray[i]);
}
//*******************
pthread_t thread_id_arr[num];
for (i = 0; i < num; i++) {
pthread_t tid;
struct structure *augs;
if (i != (num - 1)) {
augs = malloc(sizeof(struct structure) + sizeof(int) + sizeof(int) * num);
(*augs).one = arrayarray[i];
(*augs).two = (count / num);
pthread_create(&tid, NULL, sort, augs);
} else {
(*augs).one = lastarray;
(*augs).two = (count / num) + (count % num);
pthread_create(&tid, NULL, sort, augs);
//pthread_create(&tid, NULL, sort, (void*)lastarray);
}
thread_id_arr[i] = tid;
}
for (i = 0; i < num; i++) {
pthread_join(thread_id_arr[i], NULL);
}
return 0;
}
As others pointed out, you can't initialize a Variable Length Array with a pointer, like you are doing. However, you don't actually need a VLA at all. Use this instead :
int *arr = augs -> one;
You want to act directly on the array that is passed into the thread, not make a copy of it.
That being said, I see another problem. In the loop that spawns the sorting threads, you are not allocating a new args on the last loop iteration, it reuses the allocated args from the previous iteration, which can cause disaster for the 2nd-to-last thread. You need to move the malloc() call above the if.
Also, the malloc() is allocating more memory than your threads actually use. You only need to allocate enough memory for just the struct by itself, not for any integers following the struct.
Also, when each thread is done using the allocated args that it is given, it needs to free() the args to avoid leaking memory.

How to read in string input from the user and allocate it?

So I've been working on this code for a while now and I can't figure out why it's not working. Basically I'm suppose to create a program using functions to read in string input from the user which is the filename for “data.txt”. I need a function to determine the number of rows that are in the file in order to allocate an array of character pointers. Then my program should print out the strings read from the file. Finally the program should free the allocated memory.
This is my non-working code.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX_WIDTH 144
void getFileName(char* array1);
int getLineCount(FILE* data, int max);
char** createArryOfPtrs(int rows);
int main(void)
{
int max = 0;
int rows;
char array1[MAX_WIDTH];
FILE* data = fopen(array1, "r");
getFileName(array1);
getLineCount(data, max);
createArryOfPtrs(rows);
fclose(data);
return 0;
}
void getFileName(char* array1)
{
printf("Enter filename: ");
fscanf(stdin, "%144[^\t]", array1);
}
int getLineCount(FILE* data, int max)
{
int i = 4;
char *array1[MAX_WIDTH];
if(data != NULL)
{
while(fgets(*array1, MAX_WIDTH, data) != NULL)
{
i+=1;
}
}
return i;
}
char** createArryOfPtrs(int rows)
{
int r = 4, c = 9, i, j, count;
char *array1[r];
for(i =0; i < r; i++)
{
array1[i] = (char*)malloc(c * sizeof(char));
}
count = 0;
for(i = 0; i < r; i++)
{
for(j = 0; j < c; j++)
{
array1[i][j] = ++count;
}
}
for(i = 0; i < r; i++)
{
for(j = 0; j < c; j++)
{
printf("%c", array1[i][j]);
}
}
return 0;
}
This is the text file.
larry snedden 123 mocking bird lane
sponge bob 321 bikini bottom beach
mary fleece 978 pasture road
hairy whodunit 456 get out of here now lane
I'm still new to C so I'm very confused. Appreciate any help I can get.
Order matters! You get the name of the file to open after you call fopen. That means the data in array1 will be uninitialized and indeterminate (and seem random).
You need to read the name of the file first.
This issue should have been very clear if you did a little rubber duck debugging.

Is it possible to dynamically allocate 2-D array in c with using calloc() once?

All the solutions I have seen online has calloc() function used twice, is it possible to do with only using it once?
The below code is not printing the correct array elements
int **ptr;
//To allocate the memory
ptr=(int **)calloc(n,sizeof(int)*m);
printf("\nEnter the elments: ");
//To access the memory
for(i=0;i<n;i++)
{
for(j=0;j<m;j++)
{
scanf("%d",ptr[i][j]);
}
}
Since C99 you can use pointers to VLAs (Variable Length Arrays):
int n, m;
scanf("%d %d", &n, &m);
int (*ptr)[m] = malloc(sizeof(int [n][m]));
for (i = 0; i < n; i++)
{
for (j = 0; j < m; j++)
{
scanf("%d", &ptr[i][j]); // Notice the address of operator (&) for scanf
}
}
free(ptr); // Call free only once
If it's just about minimising the number of calls to memory allocation functions you can created such a jagged array like this:
#include <stdlib.h>
#include <stdio.h>
int ** alloc_jagged_2d_array_of_int(size_t n, size_t m)
{
int ** result = NULL;
size_t t = 0;
t += n * sizeof *result;
t += n*m * sizeof **result;
result = calloc(1, t);
if (NULL != result)
{
for (size_t i = 0; i < n; ++i)
{
result[i] = ((int*) (result + n)) + i*m;
}
}
return result;
}
Use it like this:
#include <stdlib.h>
#include <stdio.h>
int ** alloc_jagged_2d_array_of_int(size_t, size_t);
int main(void)
{
int result = EXIT_SUCCESS;
int ** p = alloc_jagged_2d_array_of_int(2, 3);
if (NULL == p)
{
perror("alloc_jagged_2d_array_of_int() failed");
result = EXIT_FAILURE;
}
else
{
for (size_t i = 0; i < 2; ++i)
{
for (size_t j = 0; j < 3; ++j)
{
p[i][j] = (int) (i*j);
}
}
}
/* Clean up. */
free(p);
return result;
}

Passing argument makes a pointer without cast?

I'm having an issue with compling the code.
I keep getting these errors.
"C: 194 warning passing argument 3 of 'matrix_column_subtract' makes pointer from integer without a cast"
"C: 12 note: expected 'double**' but argument is type 'int'
"C: 194 error too few arguments to function 'matrix_column_subtract'
I think I know what is going on I'm calling matrix_column_multiply is a void and I need to be calling it a pointer pointer I think and I don't know how to chage that. If anyone has some idea on how I can get this to compile that would be highly appreciated!!
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define DEBUG 0
#define MAX_ITER 10000
double *eigen (int n, double **A);
void qr_decomp (int n, double **A, double **Q, double **R);
void matrix_copy_column(double **msrc, int col1, double **mdst,int col2, int rows);
void matrix_column_subtract(double **m1, int c1, double **m2, int c2, int rows);
void matrix_column_multiply(double **m, int c, double k, int rows);
int main() {
int i, n = 126;
double *eig, **Am;
FILE *BinInp, *TxtOut;
/* Input Code: Reads bv, Am in binary form from CGrad.bin */
if ( (BinInp = fopen("CGrad.bin","r")) == NULL ) {
fprintf(stderr, "Cannot open matrix binary file INPUT... exiting\n");
exit(-1);
}
Am = (double**)malloc (n*sizeof(double*));
Am[0] = (double*)malloc (n*n*sizeof(double));
for (i = 1; i < n; ++i) {
Am[i] = Am[0] + i*n;
}
for (i = 0; i < n; i++) {
if (i==0) { /* Read one extra line that is discarded (bv is still in bin file) */
if (!fread(Am[i], sizeof(double), n, BinInp)) {
fprintf(stderr, "Cannot read row Am[%03d] of matrix... exiting\n", i+1);
exit(1);
}
}
if (!fread(Am[i], sizeof(double), n, BinInp)) {
fprintf(stderr, "Cannot read row Am[%03d] of matrix... exiting\n", i+1);
exit(1);
}
}
if (fclose(BinInp) == EOF) {
fprintf(stderr, "Cannot close matrix binary file INPUT... exiting\n");
exit(-1);
}
/* COMPUTE EIGENVALUES HERE USING FUNCTIONS. RETURN EIGENVALUES (AS 1D VECTOR) TO eig. */
if (DEBUG) printf ("Calling eigen\n");
eig = eigen (n, Am);
/* Output Code: Writes eig in text form to Eigs.txt */
if ( (TxtOut = fopen("Eigs.txt", "w")) == NULL ) {
fprintf(stderr, "Cannot open matrix text file OUTPUT... exiting\n");
exit(-1);
}
for (i = 0; i < n; i++) {
fprintf (TxtOut, "%18.14e ", eig[i]);
}
if (fclose(TxtOut) == EOF) {
fprintf(stderr, "Cannot close matrix text file INPUT... exiting\n");
exit(-1);
}
return 0;
}
double* eigen (int n, double **Acur)
{
double err = 1, eps = 1e-2;
double ndenom, nnumer, temp;
double *eig, **Anex, **Qsub, **Rsub;
int i, j, k, iters = 1;
/* Malloc memory for the three matricies */
Anex = malloc (n*sizeof(double*));
Anex[0] = malloc (n*n*sizeof(double));
for (i = 1; i < n; ++i) {
Anex[i] = Anex[0] + i*n;
}
Qsub = malloc (n*sizeof(double*));
Qsub[0] = malloc (n*n*sizeof(double));
for (i = 1; i < n; ++i) {
Qsub[i] = Qsub[0] + i*n;
}
Rsub = malloc (n*sizeof(double*));
Rsub[0] = malloc (n*n*sizeof(double));
for (i = 1; i < n; ++i) {
Rsub[i] = Rsub[0] + i*n;
}
/* Malloc memory for the return eig vector */
eig = malloc (n*sizeof(double));
for (i = 0; i < n; i++) {
eig[i] = 0;
}
/* Enter main iteration loop for eigenvalues */
while (err > eps && iters < MAX_ITER) {
/* QR Decompose Acur then find next iterate value in Anex */
qr_decomp (n, Acur, Qsub, Rsub);
// FIND NEXT ITERATE VALUE, PUT IN Anex.
/* Determine relative error change, reset "old" iterate value. */
ndenom = 0;
nnumer = 0;
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++) {
temp = Anex[i][j]-Acur[i][j];
ndenom += temp*temp;
nnumer += Anex[i][j]*Anex[i][j];
Acur[i][j] = Anex[i][j];
}
}
err = sqrt(ndenom)/sqrt(nnumer);
/* Increment the iteration count and report error */
if (iters % 25 == 0) {
printf ("Error at end of iteration %05d = %14.10f %%\n", iters, 100*err);
}
++iters;
}
printf ("Error at end of iteration %05d = %14.10f\nCONVERGED.\n", iters-1, err);
if (iters == MAX_ITER) {
printf ("WARNING: MAX_ITER iterations reached!...\n");
}
/* Copy diagonal entries of Acur into eig for return to main */
for (i=0; i<n; i++) {
eig[i] = Acur[i][i];
}
return eig;
}
void qr_decomp (int n, double **Adec, double **myQ, double **myR)
{
int i, j, k; /* Loop Variables: this is all you should need! */
double **T, **S;
double r;
T = malloc (n*sizeof(double*));
T[0] = malloc (n*n*sizeof(double));
for (i = 1; i < n; ++i) {
T[i] = T[0] + i*n;
}
S = malloc (n*sizeof(double*));
S[0] = malloc (n*n*sizeof(double));
for (i = 1; i < n; ++i) {
S[i] = S[0] + i*n;
}
/* Main loop for decomposition */
for (i=0; i<n; i++) {
/* Column i of Q is initially column i of A */
matrix_copy_column(Adec,i,myQ,i,n);
/* For j < i-1, Perform the dot product between the j row of Q and the
i row of A to determine the R(j,i) value, then insure the Q i column
is orthogonal to all other Q columns by subtracting existing Q columns
from it. */
for (j = 0; j < i; j++) {
//r[j,i] = Qj^T * Ui
matrix_copy_column(myQ,j,T,0,n);
matrix_copy_column(Adec,i,S,0,n);
for (k=0; k<n; k++) {
r += T[k][0] * S[k][0];
}
/* Determine the R diagonal as the magnitude of the Q column, then
normalize the Q column (make it a unit vector). */
//Qi = Ui
myR[j][i] = r;
// Something wrong here.
// There is one parameter missing, as matrix_column_subtract needs 5 parameters and
// only 4 are given.
// Also, matrix_column_multiply is defined as returning a void, whereas the 3rd parameter
// of matrix_column_subtract should be a double **
matrix_column_subtract(myQ,i,matrix_column_multiply(T,0,r,n),j);
}
}
}
/* Copies a matrix column from msrc at column col1 to mdst at column col2 */
void matrix_copy_column(double **msrc, int col1, double **mdst,int col2, int rows) {
int i = 0;
for (i=0; i<rows; i++) {
mdst[i][col2] = msrc[i][col1];
}
}
/* Subtracts m2's column c2 from m1's column c1 */
void matrix_column_subtract(double **m1, int c1, double **m2, int c2, int rows) {
int i = 0;
for (i=0; i<rows; i++) {
m1[i][c1] -= m2[i][c2];
}
/*return m1;*/
}
void matrix_column_multiply(double **m, int c, double k, int rows) {
int i = 0;
for (i=0; i<rows; i++) {
m[i][c] *= k;
}
/*return m;*/
}
A problem is here.
matrix_column_subtract(myQ,i,matrix_column_multiply(T,0,r,n),j);
The relevant function signatures are:
void matrix_column_subtract(double **m1, int c1, double **m2, int c2, int rows);
void matrix_column_multiply(double **m, int c, double k, int rows);
Note that matrix_column_multiply returns void, but you're passing it in as if it were double **. I'm guessing the compiler is desperately trying to make it work and returned some sort of garbage integer.
These functions return void because they do their work directly on the matrix in question. matrix_column_multiply alters m. matrix_column_subtract alters m1.
To make it work, call matrix_column_multiply on T then pass T (now modified by the multiplication) into matrix_column_subtract.
matrix_column_multiply(T, 0, r, n);
matrix_column_subtract(myQ, i, T, j, ...rows...);
You're still missing the fifth argument, rows. I'm going to guess that's n, same as has been used for the rows in every other matrix_column_blah call.

Resources