C - Can't print dynamic array values - c

For school (yes, school projects) I need to adapt one C program...
I need to make an array with values from a txt file (that I think it was correctly done).
Now I wanted to print the values, and that's the problem! I tried many ways but I'm always seeing memory adress.
Here's the code:
int* init_dados(char *nome,int *m, int *n, int *iter)
{
FILE *f;
int *p, *q;
int i, j,k,contador=0,lixo=0,aux=0,flag=0;
f=fopen(nome, "r");
if(!f)
{
printf("Erro no acesso ao ficheiro dos dados\n");
exit(1);
}
fscanf(f, " %d %d", m,n);
p = malloc(sizeof(int)*(*m)*(*n));
if(!p)
{
printf("Erro na alocacao de memoria\n");
exit(1);
}
q=p;
for (i = 0; i < *m; i++)
{
for (j = 0; j<*n; j++)
{
//se ainda nao leu nada
if (flag == 0)
{
for (contador = 0; contador < *n; contador++)
{
fscanf(f, "%d", &lixo);
}
flag = 1;
break;
}
if (flag == 1)
{
fscanf(f, " %d", &k);
break;
}
for (contador = 0; contador < k; contador++)
{
fscanf(f, " %d", q++);
}
}
}
//PRINTING CODE
for (i = 0; i < *m; i++)
{
printf("\n");
for (j = 0; j < *n; j++)
{
printf("%d ", &q[j]);
q++;
}
}
fclose(f);
return p;
}
Waiting for your thoughts, thanks !
EDIT:
#iharob I've changed this:
for (contador = 0; contador < k; contador++)
{
fscanf(f, " %d", q++);
}
and
for (i = 0; i < *m; i++)
{
printf("\n");
for (j = 0; j < *n; j++)
{
printf("%d ", p[j]);
p++;
}
}
and still not working
EDIT2:
file:
10 10
1 1 1 1 1 1 1 1 1 1
2
1 8
2
5 6
4
1 2 3 4
1
1
4
1 2 5 8
2
6 10
1
9
4
1 2 3 5
1
8
1
7
print of the result so far:

This is wrong
printf("%d ", &q[i]);
change it to p[i] instead of &q[i]
printf("%d ", p[i]);
when you reach printf("%d ", q[i]) q points to the end of the array, so q[0] == q[lengthOfQ] that is past q, you assigned q = p; to keep p pointing to the begining of the array, hence you should use p in printf("%d ", q[i]); instead of q.
I think this code must be what you need
int *init_dados(char *nome,int *m, int *n, int *iter)
{
FILE *f;
int *p, *q;
int i, j, k, contador = 0, lixo = 0, flag = 0;
f = fopen(nome, "r");
if (f == NULL)
{
printf("Erro no acesso ao ficheiro dos dados\n");
exit(1);
}
fscanf(f, " %d %d", m, n);
p = malloc(sizeof(int) * *m * *n);
if (p == NULL)
{
fclose(f);
printf("Erro na alocacao de memoria\n");
exit(1);
}
q = p;
for (i = 0; i < *m; i++)
{
for (j = 0 ; j <* n ; j++)
{
//se ainda nao leu nada
if (flag == 0)
{
for (contador = 0 ; contador < *n ; contador++)
fscanf(f, "%d", &lixo);
printf("----\n");
flag = 1;
break;
}
else if (flag == 1)
{
fscanf(f, " %d", &k);
flag = 2;
break;
}
else if (flag == 2)
{
for (contador = 0 ; contador < k ; contador++)
fscanf(f, " %d", q++);
}
flag = 1;
}
}
}
//PRINTING CODE
for (i = 0; i < *m; i++)
{
for (j = 0; j < *n; j++)
printf("%d ", p[j]);
printf("\n");
}
fclose(f);
return p;
}

this code:
for (contador = 0; contador < k; contador++)
{
fscanf(f, " %d", q++);
}
will never be executed.
It is in a loop code block, where the driving force is 'flag' and flag is only set to 0 and 1, both the 0 case and the 1 case exit the overall 'for' loop.
Have you dumped the resulting 'p' array to assure the values are correct?
When running the program, did you notice that this code is never executed?

this code:
for (i = 0; i < *m; i++)
{
printf("\n");
for (j = 0; j < *n; j++)
{
printf("%d ", p[j]);
p++;
}
}
has the problem that 'p' should not be incremented.
for two reasons:
1) need to keep pointer to malloc'd memory
2) the variable 'j' is indexing off of 'p' so no need to increment 'p'

the following code compiles, but does raise a compiler warning about unused paramter
the code implements the OPs requirements
#include <stdio.h>
#include <stdlib.h>
// the 'iter' parameter is not used, raises compiler warning,
// suggest adding code to use it or remove that parameter
int* init_dados(char *nome,int *m, int *n, int *iter)
{
FILE *f = NULL;
int *p = NULL; // ptr to malloc'd memory
if( NULL == (p = malloc(1) ) )
{ // then, malloc failed
perror( "malloc failed" );
exit( EXIT_FAILURE );
}
// implied else, malloc successful
int *q = p; // steps into malloc'd memory
int j; // group loop index
int k; // group data size
int contador=0; // read loop counter
int lixo=0; // read and discard work area
if(NULL == (f=fopen(nome, "r") ) )
{ // then, fopen failed
perror("fopen failed" );
printf("Erro no acesso ao ficheiro dos dados\n");
exit( EXIT_FAILURE );
}
// implied else, fopen successful
if( 2 != (fscanf(f, " %d %d", m,n) ) )
{ // then, fscanf failed
perror( "fscanf failed for first line of file" );
free(p);
exit( EXIT_FAILURE );
}
// implied else, fscanf for m, n successful
//se ainda nao leu nada
for (contador = 0; contador < *n; contador++)
{
if( 1 != fscanf(f, " %d", &lixo) )
{ // then, fscanf failed for throwaway data
perror("fscanf failed for throwaway data line" );
free(p);
exit( EXIT_FAILURE );
}
// implied else, fscanf successful
} // end for
// for each data group
for (j = 0; j<(*n); j++)
{
if( 1 != fscanf(f, " %d", &k) )
{ // then, fscanf failed
perror( "fscanf failed for count of data in group" );
free(p);
exit( EXIT_FAILURE );
}
// implied else, fscanf successful
// input data from data group, with echo
printf("\nGroup Number: %d with data count: %d\n", j, k);
for (contador = 0; contador < k; contador++, q++)
{
if( 1 != fscanf(f, " %d", q) )
{ // then, fscanf failed
perror( "fscanf failed for data entry in data group" );
free(p);
exit( EXIT_FAILURE );
}
// implied else, fscanf successful
printf("%3d ", *q);
} // end for
} // end for
fclose(f);
return p;
} // end function: init_dados

Related

Sorting structure variables(3 ints) in file from smallest to largest C

I need to sort my 2 text files for my project. One of the text files is in student id, course id and score format and the other is in student id's format. I wrote the values in both of them with fprintf, so I am using fscanf while reading, but my function is not working correctly, can you tell me where is my mistake?
(I deleted the old code that didn't work because I continued on a different code)
Edit :I tried to create a code snippet based on the solution below, but when I enter the while loop, fscanf starts to get the wrong numbers. Can you look for where my mistake is?
Edit :After editing here, I did the fopen checks. There is no problem with them. The while loop closes after it runs once, I think, in the if fscanf parts, fscanf does not read the number correctly, so it exits the loop with break.
most likely broken part:
FILE *index = fopen("index.txt", "r");
FILE *record = fopen("record.txt", "r");
if (!index)
return;
if (!record)
return;
int array[n][3];
//int *array = (int *)malloc(n *3 sizeof(int));???
int count = 0;
int i=0,temp,id,course,score;
while (1)
{
if(count==n) break;
if (fscanf(record, "%d", &id) != 1) break;
if (fscanf(record, "%d", &course) != 1) break;
if (fscanf(record, "%d", &score) != 1) break;
array[count][0] = id;
array[count][1] = course;
array[count][2] = score;
count++;
}
the rest of the function for you to browse if the error is elsewhere:
void sort_for_bin_search(int n)
{
FILE *index = fopen("index.txt", "r");
FILE *record = fopen("record.txt", "r");
if (!index)
return;
if (!record)
return;
int array[n][3];
//int *array = (int *)malloc(n *3 sizeof(int));???
int count = 0;
int i=0,temp,id,course,score;
while (1)
{
if(count==n) break;
if (fscanf(record, "%d", &id) != 1) break;
if (fscanf(record, "%d", &course) != 1) break;
if (fscanf(record, "%d", &score) != 1) break;
array[count][0] = id;
array[count][1] = course;
array[count][2] = score;
count++;
}
for (i = 1; i < n - 1; i++)
{
for (int j = 0; j < n - 1; j++)
{
if(array[i][0] > array [j][0])
{
temp=array[j][0];
array[j][0] = array[i][0];
array[i][0] = temp;
temp=array[j][1];
array[j][1] = array[i][1];
array[i][1] = temp;
temp=array[j][2];
array[j][2] = array[i][2];
array[i][2] = temp;
}
else if((array[i][0]==array[j][0])&&(array[i][1]>array[j][1]))
{
temp=array[j][0];
array[j][0] = array[i][0];
array[i][0] = temp;
temp=array[j][1];
array[j][1] = array[i][1];
array[i][1] = temp;
temp=array[j][2];
array[j][2] = array[i][2];
array[i][2] = temp;
}
}
}
fclose(record);
fclose(index);
FILE *index2 = fopen("index.txt", "w");
FILE *record2 = fopen("record.txt", "w");
for (i = 0; i < n; i++)
{
fprintf(index2,"%d\n",array[i][0]);
fprintf(record2,"%d %d %d\n",array[i][0],array[i][1],array[i][2]);
//printf("%d %d %d\n",array[i][0],array[i][1],array[i][2]);
}
//free(array);
fclose(record2);
fclose(index2);
}
It looks like you are doing a bubble sort, and in each iteration you read/write from disk. Disk operations are very slow. It is much easier and faster if you read once in to array. And then sort that single array.
Example:
void sort_for_bin_search(int n)
{
//assumes that `n` is the number of lines in this file
if (n < 1) return;
FILE* fin = fopen("index.txt", "r");
if (!fin)
return;
FILE* fout = fopen("record.txt", "w");
if (!fout)
return;
int* arr = malloc(n * sizeof(int));
if (!arr) return;
int count = 0;
while (1)
{
if (count == n)
break;
int id, course, score;
if (fscanf(fin, "%d", &id) != 1) break;
if (fscanf(fin, "%d", &course) != 1) break;
if (fscanf(fin, "%d", &score) != 1) break;
arr[count] = id;
count++;
}
//add code for sorting arr
for (int i = 0; i < count; i++)
fprintf(fout, "%d\n", arr[i]);
free(arr);
fclose(fin);
fclose(fout);
}
Then you can sort, for example using bubble sort.
Use printf to print the data on screen at each step, this will help with debugging.
void sort_for_bin_search(int n)
{
FILE* fin = fopen("input_file.txt", "r");
if (!fin)
{
printf("input error\n");
return;
}
int array[n][3];
int count = 0;
while (1)
{
int id, course, score;
if (count == n) break;
if (fscanf(fin, "%d", &id) != 1) break;
if (fscanf(fin, "%d", &course) != 1) break;
if (fscanf(fin, "%d", &score) != 1) break;
array[count][0] = id;
array[count][1] = course;
array[count][2] = score;
count++;
}
n = count;
printf("reading:\n");
for (int i = 0; i < n; i++)
printf("%d %d %d\n", array[i][0], array[i][1], array[i][2]);
printf("\nsort\n");
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n - 1 - i; j++)
{
if (array[j][0] > array[j + 1][0])
{
int temp;
temp = array[j][0];
array[j][0] = array[j + 1][0];
array[j + 1][0] = temp;
temp = array[j][1];
array[j][1] = array[j + 1][1];
array[j + 1][1] = temp;
temp = array[j][2];
array[j][2] = array[j + 1][2];
array[j + 1][2] = temp;
}
}
}
fclose(fin);
printf("sorted\n");
for(int i = 0; i < n; i++)
printf("%d %d %d\n", array[i][0], array[i][1], array[i][2]);
printf("write to file\n");
FILE* fout = fopen("output_file.txt", "w");
if(!fout)
{
printf("output error\n");
return;
}
for (int i = 0; i < n; i++)
fprintf(fout, "%d %d %d\n", array[i][0], array[i][1], array[i][2]);
fclose(fout);
}

How to save a modified array to a file

So I created an array which is saved in a file. I have the number 4 printed out 100 times in the file. Now everytime the an element in the array is accessed it the value will decrease by 1. So if A[1] = 4 is accessed then it will become A[1] = 3 and be saved on the file. The thing is I can't save the modified array to the file.
I already tried moving the placement of FILE pointer.
void buildingB4()
{
system("CLS");
FILE *input, *output;
int i, B4[100], room;
input = fopen("B4.txt", "r");
if (input == NULL)
{
output = fopen("B4.txt", "w");
for (i = 1; i <= 100; i++)
{
B4[i] = 4;
fprintf(output, "%d\n", B4[i]);
}
fclose(output);
for (i = 1; i <= 100; i++)
{
if (i % 10 == 0)
{
printf("\n\n");
}
printf("B-4-%d(%d)\t", i, B4[i]);
}
}
else
{
for (i = 1; i <= 100; i++)
{
fscanf(input, "%d\n", &B4[i]);
if (i % 10 == 0)
{
printf("\n\n");
}
printf("B-4-%d(%d)\t", i, B4[i]);
}
fclose(input);
printf("\nPlease choose a room:B-4-");
scanf("%d", &room);
B4[room] = B4[room] - 1;
output = fopen("B4.txt", "a");
fprintf(output, "%d\n", B4[i]);
studentDetails();
}
}
say if A[1] = 4
and when user input is 1, 1 is saved in a variable called room.
so A[room] = A[room] -1
so the result would be A[1] = 3 and it modify the A[1] saved in the file.
Use fclose after the line
fprintf(output, "%d\n", B4[i]);
I've found little mistakes in your code and here is your fixed code:
#define HOME_SIZE 100
void show_rooms(int B[]){
for (int i = 0; i < HOME_SIZE; i++){
if (i % 10 == 0){
printf("\n\n");
}
printf("B-4-%3d(%d) ", i + 1, B[i]);
}
}
void buildingB4()
{
FILE *input, *output;
input = fopen("B4.txt", "r");
unsigned int B[HOME_SIZE], room;
if (input == NULL){
fclose(input);
// Setting all homes to 4.
for (int i = 0; i < HOME_SIZE; ++i){
B[i] = 4;
}
output = fopen("B4.txt", "w");
for(int i = 0; i < HOME_SIZE; ++i)
fprintf(output, "%d\n", B[i]);
fclose(output);
show_rooms(B);
}
else{
for (int i = 0; i < HOME_SIZE; ++i){
fscanf(input, "%d", &B[i]);
}
fclose(input);
show_rooms(B);
printf("\nPlease choose a room:B-4-");
scanf("%d", &room);
if (room > 0 && room <= HOME_SIZE)
B[room - 1] -= 1;
output = fopen("B4.txt", "w");
for(int i = 0; i < HOME_SIZE; ++i)
fprintf(output, "%d\n", B[i]);
}
}
Notice that :
In C index starts from 0 not 1.
close using file after your work in order to save it properly.
Don't use '%d\n' format for scanf, it will ignore ' ' and '\n' automatically.
Tips for future development :
Try using feof function to know if your file is ended or not instead of using constant size for your inputs.

Reading two dimensional array from file and printing it

I have some problems with my code. Everything is fine; gcc shows no errors or warnings; valgrind says no memory leaks, but my array isn't printed and I'm not sure why. Is fscanf() not working correctly or am I printing it incorrectly?
#include <stdio.h>
#include <stdlib.h>
int arrsize (FILE *file)
{
if (file == NULL) {
printf("Error: file pointer is null.");
return 0;
}
int sizer;
fscanf(file, "%d", &size);
return size;
}
int main()
{
int i = 0, j = 0, k = 0,a=0;
FILE *fp;
if ((fp = fopen("matrix.txt", "r")) == NULL)
{
printf("Error: file pointer is null.\n");
return 1;
}
int size = arrsize(fp);
printf("Array size is %d x %d \n", size, size);
double **array = (double **)malloc(size * sizeof(double *));
for (i; i < size; i++)
array[i] = (double *)malloc(size * sizeof(double));
for (i; i < size; i++)
{
for (j = 0; j < size; j++)
{
fscanf(fp, " %lf", &array[i][j]);
printf(" %lf ",array[i][j]);
}
}
for (k ; k < size; k++) {
free(array[k]);
}
free(array);
fclose(fp);
return 0;
}
Check the return of fscanf and malloc to make sure of success.
Add fflush ( stdout); to the print loops since the format string does not have a newline.
#include <stdio.h>
#include <stdlib.h>
int arrsize (FILE *file)
{
if (file == NULL) {
printf("Error: file pointer is null.");
return 0;
}
int size;
if ( 1 == fscanf(file, "%d", &size)) {
return size;
}
return -1;
}
int main()
{
int i = 0, j = 0, k = 0;
FILE *fp;
if ((fp = fopen("matrix.txt", "r")) == NULL)
{
printf("Error: file pointer is null.\n");
return 1;
}
int size = arrsize(fp);
if ( -1 == size) {
fprintf( stderr, "Error: problem parsing array size.\n");
return 1;
}
printf("Array size is %d x %d \n", size, size);
double **array = NULL;
if ( NULL != ( array = malloc(size * sizeof(double *)))) {
for (i = 0; i < size; i++) {
if ( NULL == ( array[i] = malloc(size * sizeof(double)))) {
fprintf ( stderr, "problem allocation array[]\n");
while ( i) {
i--;
free ( array[i]);
}
free ( array);
return 1;
}
}
}
else {
fprintf ( stderr, "problem allocation array\n");
return 1;
}
for (i = 0; i < size; i++)
{
for (j = 0; j < size; j++)
{
if ( 1 == fscanf(fp, "%lf", &array[i][j])) {
printf(" %lf ",array[i][j]);
}
else {
fprintf ( stderr, "problem parsing double\n");
break;
}
}
fflush ( stdout);
}
for (k = 0; k < size; k++) {
free(array[k]);
}
free(array);
fclose(fp);
return 0;
}

Printed Array table comes out multiple times

When I execute my code I keep getting the right answers but it is printed multiple times? I want it display a table with with 5 columns and 3 rows and there should be 4 of these tables but I get three times too many and I don't know why?
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main(){
int w;
int n = 1;
int i;
for(w = 1; w < 5; w++){
FILE *myFile;
float numberArray[1];
if(n == 4){
myFile = fopen("input4.txt", "r");
n++;
}
if(n == 3){
myFile = fopen("input3.txt", "r");
n++;
}
if(n == 2){
myFile = fopen("input2.txt", "r");
n++;
}
if(n == 1){
myFile = fopen("input1.txt", "r");
n++;
}
if (myFile == NULL)
{
printf("Error Reading File\n");
exit (0);
}
printf("Enter 3 numbers between 0 and 9.999:\n");
printf("Number sin cos tan atan\n");
printf("-------------------------------------------\n");
for (i = 0; i < 3; i++)
{
fscanf(myFile, "%f,", &numberArray[i] );
}
for (i = 0; i < 3; i++)
{
printf("%.6f %.4f %.4f %.4f %.4f\n",numberArray[i], sin(numberArray[i]), cos(numberArray[i]), tan(numberArray[i]), atan(numberArray[i]));
}
fclose(myFile);
}
return 0;
}
You are reading and writing in unallocated memory space when accessing numberArray.
You defined numberArray[1] with a size of 1, yet you are accessing numberArray[1..2] in your loops here :
for (i = 0; i < 3; i++)
{
fscanf(myFile, "%f,", &numberArray[i] );
}
for (i = 0; i < 3; i++)
{
printf("%.6f %.4f %.4f %.4f %.4f\n",numberArray[i], sin(numberArray[i]), cos(numberArray[i]), tan(numberArray[i]), atan(numberArray[i]));
}
I have not tested your code, but this seems to be the most obvious culprit.

fscanf() doesn't want to read values after the first two are read

Basically, I'm reading a bunch of values from a text file, which has them in the following layout:
4 1 1 2 3 4
But the following block of code doesn't want to read the double type value following the first two int type values:
int matrix_read(struct matrep *mat, const char *filename)
{
FILE *fptr;
unsigned m, n;
double *ptr = NULL;
int i, j;
double x;
if ((fptr = fopen(filename, "r")) == NULL)
{
fprintf(stderr, "Cannot Open File %s\n", filename);
return -1;
}
if(fscanf(fptr, "%u", &m) != 1)
{
fprintf(stderr, "Failed to read number of rows\n");
return -1;
}
if(fscanf(fptr, "%u", &n) != 1)
{
fprintf(stderr, "Failed to read number of columns\n");
return -1;
}
mat->matrix = (double *)malloc(sizeof(double) * m * n);
if (mat->matrix == 0)
{
fprintf(stderr, "Failed to allocate %d*%d matrix\n", m, n);
return -1;
}
ptr = mat->matrix;
for (i = 0; i < m; i++)
{
for (j = 0; j < n; j++)
{
double x;
if (fscanf(fptr, "%f", &x) != 1)
{
fprintf(stderr, "Failed to read element matrix[%d,%d]\n", i, j);
free(mat->matrix);
mat->matrix = 0;
mat->cols = 0;
mat->rows = 0;
return -1;
}
*ptr++ = x;//Here it reads nothing, it just gives me: -9.2559604281615349e+061
}
}
fclose(fptr);
mat->cols = m;
mat->rows = n;
return 0; // Success
}
What am I doing wrong?
fscanf(fptr, "%f", &x)
For scanning doubles, you need the %lf format. %f scans a float. Using the wrong format invokes undefined behaviour, what probably happens is that the scanned value is converted to a float and then stored in the first four bytes of the pointed-to double.

Resources