How to read floats from file in c? - c

I am struggling with reading floats from a file which I created during the program lifetime. I was trying to rewind the file, I was trying to open and close file before reading it, I was trying to put values directly in the table and by another variable. Idk what can I do more, what's wrong here?
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void) {
srand(time(NULL));
float *tab;
float x = 0.0;
int i, size;
FILE *fp;
fp = fopen("data.txt", "w+");
if (fp == NULL) {
printf("Error");
system("PAUSE");
exit(1);
}
printf("Size of table: ");
scanf("%d", &size);
tab = (int*)malloc(size * sizeof(int));
for (i = 0; i < size; i++) {
tab[i] = (8.0 - 2.0) * (float)rand() / RAND_MAX + 2.0;
fprintf(fp, "%.2f ", tab[i]);
}
for (i = 0; i < size; i++) {
printf("%.2f ", tab[i]);
}
printf("\n");
fp = fclose;
fp = fopen("data.txt", "w+");
tab = realloc(tab, 2*size);
for (i = 0; i < size * 2; i+=2) {
fscanf(fp, "%f", &x);
printf("%.2f ", x);
//tab[i + 1] = tab[i] / 2;
}
/*for (i = 0; i < size * 2; i++) {
printf("%.2f \n", tab[i]);
}*/
fp = fclose;
printf("\n");
system("PAUSE");
return 0;
}

There are a number of problems in this code. First, as noted in the comments, the initial allocation is wrong. You are allocating space for floats, not ints. You could have avoided this problem entirely if you had written the call to malloc() like this:
tab = malloc(sizeof(*tab) * size);
Here, the result of malloc() is not cast, since it is not necessary in C. Also, note that instead of using an explicit type for the argument to the sizeof operator, the identifier is used instead. This guarantees that whatever the type of tab, which must be a pointer, the result of sizeof will be correct. Also, you should always check to see if an allocation was successful.
fp = fclose is just wrong. This should be fclose(fp). After this, when you open the file again with "w+", the file is truncated to zero length, and you lose the data that was previously written. Since the file has already been opened with "w+", just use rewind(fp) here.
For the reallocation that you do, aside from that the arguments are not quite right here, there is a potential problem that you should be aware of. realloc() can return a null pointer in the event of an allocation error. If this happens, and you are directly assigning the result of realloc() to the pointer for which you are reallocating (tab), then you will lose the reference to previously allocated memory. This is a memory leak, and lost data. The way to do this is to store the result of realloc() in a temporary pointer, which you test. If the temporary pointer is a null pointer, there was an error; otherwise you can safely assign the return value to the original pointer.
And as already noted, when you call fclose() the final time, it needs to be fclose(fp).
Here is a modified code:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void) {
srand(time(NULL));
float *tab, *temp; // added temp for realloc() check
float x = 0.0;
int i, size;
FILE *fp;
fp = fopen("data.txt", "w+");
if (fp == NULL) {
printf("Error");
system("PAUSE");
exit(1);
}
printf("Size of table: ");
scanf("%d", &size);
/* You should always check for allocation errors */
if ((tab = malloc(sizeof(*tab) * size)) == NULL) {
fprintf(stderr, "Error in initial allocation\n");
exit(EXIT_FAILURE);
}
for (i = 0; i < size; i++) {
tab[i] = (8.0 - 2.0) * (float)rand() / RAND_MAX + 2.0;
fprintf(fp, "%.2f ", tab[i]);
}
for (i = 0; i < size; i++) {
printf("%.2f ", tab[i]);
}
printf("\n");
// fclose(fp); // not fp = fclose;
// fp = fopen("data.txt", "w+"); // when you reopen, the file is truncated
rewind(fp); // but just do this
/* Fixed this reallocation */
temp = realloc(tab, sizeof(*tab) * size * 2);
if (temp == NULL) {
fprintf(stderr, "Error in reallocation\n");
exit(EXIT_FAILURE);
}
tab = temp;
for (i = 0; i < size * 2; i+=2) {
fscanf(fp, "%f", &x);
printf("%.2f ", x);
//tab[i + 1] = tab[i] / 2;
}
/*for (i = 0; i < size * 2; i++) {
printf("%.2f \n", tab[i]);
}*/
fclose(fp); // not fp = fclose;
printf("\n");
system("PAUSE");
return 0;
}
Sample interaction:
Size of table: 10
2.65 5.67 5.21 3.22 3.07 4.29 5.96 5.96 5.15 7.36
2.65 5.67 5.21 3.22 3.07 4.29 5.96 5.96 5.15 7.36

Related

Saving integers from a file into an array

I was hoping to get a bit of help, I am implementing an inversion counter algorithm to take in 50,000 intergers and display the inversions and time it took to run the algorithm, I am having a hard time allocating and saving the integers from the file into an array. My code complies and runs but nothing happens
here is what I have:
int main(int argc, char** argv)
{
int n, i;
int inversions=0;
int *A;
FILE *file;
char filename[100];
clock_t start, end;
double totalTime;
printf("Enter filename: ");
scanf("%s", filename);
file = fopen(filename, "r");
if(file == NULL)
{
printf("Error opening file!\n");
return 0;
}
fscanf(file, "%d", &n);
A = (int*) malloc(n * sizeof(int));
for(i = 0; i < n; i++) {
fscanf(file, "%d", &A[i]);
}
start = clock();
inversions = countInversionsBruteForce(A, n);
end = clock();
totalTime = (double) (end - start) / CLOCKS_PER_SEC;
printf("Brute Force Algorithm\n");
printf("Number of inversions: %d\n", inversions);
printf("Execution time: %f\n", totalTime);
I think I have noth allocated array size and saved it properly
Your program is incomplete so I was not able to compile it. Minimized the problem to just loading the data into your array:
Formatted code for readability.
Generated a suitable input file. Most likely this is your problem but you have not shared your input sample with us.
Added missing include files.
Remove argc, argv as you not using them.
Minimize scope of variables. Use size_t instead of int for unsigned values.
Max string size on obtaining file name
Check return value for scanf(), fopen(), fscanf().
Printing out the data read to demonstrate it's working.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main() {
printf("Enter filename: ");
char filename[100];
if(scanf("%99s", filename) != 1) {
printf("scanf failed\n");
return 1;
}
FILE *file = fopen(filename, "r");
if(!file) {
printf("Error opening file!\n");
return 1;
}
size_t n;
fscanf(file, "%zu", &n);
if(!n) {
printf("n must be positive");
return 1;
}
int *A = malloc(n * sizeof(*A));
for(size_t i = 0; i < n; i++)
if(fscanf(file, "%d", &A[i]) != 1) {
printf("fscanf() failed\n");
return 1;
}
printf("n = %zu\n", n);
printf("A = ");
for(size_t i = 0; i < n; i++)
printf("%d%s", A[i], i + 1 < n ? ", " : "\n");
}
with 1.txt as:
4
1
2
3
4
a sample session looks like this:
Enter filename: 1.txt
n = 4
A = 1, 2, 3, 4

Fscanf Seg Error

Working on a project where I have to have a file that is generated numbers. First line is a generated int. Followed by a floats (separate lines). (I'm doing it separate lines because I feel it makes more sense as I have to read it two different ways for the bin packing problems which I need this for... Like one way of reading one at a time and another storing it in an array.. But want to get this down first)
Getting a seg fault when I try to read my file for a float after reading an int. Edit: Error occurs in readOffline.
int randomFunction()
{
FILE *fp;
int i;
fp = fopen("theItems.txt", "w" );
if (fp == NULL)
printf("Error: file can't be opened.\n");
srand(time(NULL) );
int random_number = rand();
printf("Random Number %d\n", random_number);
fprintf(fp,"%d",random_number);
fclose(fp);
fp = fopen("theItems.txt", "a");
int numberOfItems = rand();
printf("NumberOfItems: %d\n",numberOfItems);
for(i = 0; i < 10; i++)
{
fp = fopen("theItems.txt", "a");
float number = (float)rand()/(float)(RAND_MAX);
fprintf(fp,"%f",number);
fprintf(fp,"%s", "\n");
fclose(fp);
}
return numberOfItems;
}
void readOffline( int numberOfItems)
{
FILE *fp;
int n = 0,i;
float nu = 0.00;
fp = fopen("theItems.txt", "r");
if (fp == NULL)
printf("Error: file can't be opened.\n");
fseek(fp,SEEK_SET,0);
fscanf(fp,"%d",&n);
printf("Number read: %d\n", n);
float array[numberOfItems];
// for(i = 0; i < 3; i++)
// {
fscanf(fp,"%f",&nu);
// array[i] = nu;
// }
fclose(fp);
printf("Int:%d\n", n);
int j;
// for(j = 0; j < 3; j++)
// printf("Float Number:%f\n", array[j]);
}
int main()
{
int numberOfItems = randomFunction();
readOffline(numberOfItems);
return 0;
}
Just trying to get an understanding why it causes a seg error when I // it out I can get it to read my int but sometimes it isn't the right int read. But yeah.
Please let me know if I need any more details or need to be more clear anywhere
You have multiple issues in your code:
You open the output file multiple times in randomFunction(), you even leak a stream handle and leave it open.
You do not exit the function when fopen() returns NULL. The rest of the code invokes undefined behavior if fp == NULL.
The same problem is present in readOffline(): if fp == NULL, you should return from the function immediately.
you do not output a linefeed after the first random number in the output file.
you always output 10 random numbers.
most importantly: the random number returned by the randomFunction() is potentially huge, allocating an array with local storage larger than a few megabytes is likely to cause undefined behavior. Try and reduce the maximum random number of values.
Here is a proposed correction:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int randomFunction(void) {
FILE *fp;
int i;
fp = fopen("theItems.txt", "w");
if (fp == NULL) {
printf("Error: file can't be opened.\n");
return -1;
}
srand(time(NULL));
int random_number = rand();
printf("Random Number %d\n", random_number);
fprintf(fp, "%d\n", random_number);
int numberOfItems = 1 + rand() % 100; /* between 1 and 100 */
printf("NumberOfItems: %d\n", numberOfItems);
for (i = 0; i < numberOfItems; i++) {
float number = rand() / (float)(RAND_MAX);
fprintf(fp, "%f\n", number);
}
fclose(fp);
return numberOfItems;
}
void readOffline(int numberOfItems) {
FILE *fp;
int n = 0, i;
fp = fopen("theItems.txt", "r");
if (fp == NULL) {
printf("Error: file can't be opened.\n");
return;
}
fscanf(fp, "%d", &n);
printf("Number read: %d\n", n);
float array[numberOfItems];
for (i = 0; i < numberOfItems; i++) {
if (fscanf(fp, "%f", &array[i]) != 1)
break;
}
fclose(fp);
printf("Int:%d\n", n);
for (int j = 0; j < i; j++) {
printf("Float Number %d: %f\n", j, array[j]);
}
}
int main(void) {
int numberOfItems = randomFunction();
readOffline(numberOfItems);
return 0;
}
Note that I kept your semantics: the random number at the start of the file is not the number of floating point values that follow. I suspect it should be?
I would say that depending on the particular compiler that you are using, then this could be a problem in setting up the actual array. This is (as an example) discussed in Variable Sized Arrays vs calloc in C From the discussions, you should use calloc and free. Another point is that you need to make sure that your value is greater than 3 and not too big. Since the array is only in the local scope of readOffline(), you should not connect it to the variable numberOfItems.
float array[3];
for(i = 0; i < 3; i++)
{
fscanf(fp,"%f",&nu);
array[i] = nu;
}

Reading a dynamic array from a file with function

I have the following code:`
#include <stdio.h>
#include <stdlib.h>
void load_from_file(int A[], int *n);
int main()
{
int *A;
A = (int*)malloc(0);
int count = 0;
int i;
load_from_file(A, &count);
for(i = 0; i < count; i++)
{
printf("A[%d]=%d ", i, A[i]);
printf("\n");
printf("&A[%d]=%p \n\n", i, &A[i]);
}
return 0;
}
void load_from_file(int A[], int *n)
{
FILE* fp;
int temp, i;
fp = fopen("data.txt", "r");
if (fp == NULL)
{
printf("error!!");
exit (1);
}
fscanf(fp, "%d", &temp);
*n = temp;
A = (int*) realloc(A, temp * sizeof(int));
if (*A == NULL)
{
printf("error realloc!!");
exit(1);
}
for(i = 0; i < temp; i++)
{
fscanf(fp, "%d", &A[i]);
}
for(i = 0; i < temp; i++)
{
printf("A[%d]=%d ", i, A[i]);
printf("\n");
printf("&A[%d]=%p \n\n", i, &A[i]);
}
fclose(fp);
}
I'm trying to read a text file into an array.
First line of the file has the number of elements of the array, and second line the numbers-elements.
We create the array through realloc.
But something is going wrong.....
I have some patches, printing the address of array's elements.
But unfortunatelly they are different(not all the times) inside the function, and outside the function, although an array is passed by reference (as I think...)
Please, tell me where is the mistake, and how can I fix the problem.
Thanks in advance...
Dimitri
Call:
int *A = load_from_file(&count);
Function:
int *load_from_file(int *n)
{
FILE* fp;
int temp,i;
int *A = 0;
fp=fopen("data.txt","r");
if (fp==NULL){fprintf(stderr, "error!!\n");exit (1);}
fscanf(fp,"%d",&temp);
*n=temp;
A = (int*) realloc(A,temp * sizeof(int));
if (A == NULL) {fprintf(stderr, "error realloc!!\n");exit(1);}
for(i=0;i<temp;i++)
fscanf(fp, "%d",&A[i]);
for(i=0;i<temp;i++)
{
printf("A[%d]=%d ",i,A[i]);
printf("\n");
printf("&A[%d]=%p \n\n",i,&A[i]);
}
fclose(fp);
return A;
}
This is a totally minimal set of changes; the code needs a lot more work. In particular, the fscanf() calls should be error checked. There's a subtle but important change in the allocation test: if (A == NULL) rather than the original if (*A == NULL).
With somewhat more complete error checking:
int *load_from_file(int *n)
{
FILE *fp;
int temp, i;
int *A = 0;
const char file[] = "data.txt";
fp = fopen(file, "r");
if (fp == NULL)
{
fprintf(stderr, "Failed to open file %s for reading\n", file);
exit(1);
}
if (fscanf(fp, "%d", &temp) != 1)
{
fprintf(stderr, "Failed to read number of entries\n");
exit(1);
}
*n = temp;
A = (int *) realloc(A, temp * sizeof(int));
if (A == NULL)
{
fprintf(stderr, "Failed to reallocate %zu bytes of memory\n",
temp * sizeof(int));
exit(1);
}
for (i = 0; i < temp; i++)
{
if (fscanf(fp, "%d", &A[i]) != 1)
{
fprintf(stderr, "Failed to read entry number %d\n", i);
exit(1);
}
}
for (i = 0; i < temp; i++)
printf("A[%d]=%d: &A[%d]=%p\n", i, A[i], i, &A[i]);
fclose(fp);
return A;
}
I have a library of error reporting functions that I use which would reduce the error handling from 4 lines to 1 line per error. I strongly recommend creating and using such a library for yourself.

double dimensional array as return value

For my homework, I have to read data from an input file and to store it in a double dimensional array and then pass this array to another function. This is what I have tried so far, but I don't know when I call this function in main it gives the error:
Access violation writing location 0x00000000.
I have tried to dynamically allocate memory and it gives the same error. What I am doing wrong?
The last update of the code:
#include<stdio.h>
#include<stdlib.h>
int *a[2];
void getData(void)
{
FILE *fp = fopen("input.txt", "r");
int number;
fscanf(fp, "%d", &number);
for (int i = 0; i < number; i++)
{
a[i]=(int*)malloc(number * sizeof (int));
fscanf(fp, "%d %d", &a[i][0], &a[i][1]);
}
fclose(fp);
}
int main()
{
getData();
for(int i=0;i<8;i++)
{
printf("%d %d\n",a[i][0],a[i][1]);
}
}
You need to allocate memory for a
Before the for loop
a = (int **)malloc(number * sizeof(int *))
You are not allocating the first dimension, ie a is a null pointer when you are trying to dereference it.
#include <stdlib.h>
a = malloc(number * sizeof *a);
BTW, sizeof(int) is not sufficient to store two numbers.
#include <stdlib.h>
a[i] = malloc(2 * sizeof *a[i]);
fscanf(iFile, "%d %d", &a[i][0], &a[i][1]);
Here is a whole correct code (although not perfect, as long as a is an hugly global variable):
int (*a)[2] = NULL;
void getData(void)
{
FILE *fp = fopen("input.txt", "r");
int number;
fscanf(fp, "%d", &number);
a = malloc(number * sizeof *a);
for (int i = 0; i < number; i++)
fscanf(fp, "%d %d", &a[i][0], &a[i][1]);
fclose(fp);
}

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