Reading binary integers from a file in C - c

All night I have been looking for answers for this & haven't slept, yet, I can't make it work...
I have a binary file and I want to read it and take the value of each integer...
Here is some code:
FILE *f;
char ch;
char t1[3];
int l, c, grayScale, i, j;
int p =0;
f = fopen(pgm, "rb");
(...)
c = 0;
l = 0;
fscanf(f, "%d", &c);
fscanf(f, "%d", &l);
fscanf(f, "%d", &grayScale);
A = alocar_memoria_matriz(l,c);
for(i = 0; i<l; i++){
for(j=0; j<c; j++){
if(fread(&p,sizeof(int),1,f) !=1){
fprintf(stderr, "\nError!\n");
fclose(f);
free_memoria_matriz(A,l);
return NULL;
}else if(p>grayScale|| p<0){
fprintf(stderr, "\nError!\n");
fclose(f);
free_memoria_matriz(A,l);
return NULL;
}else{
A[i][j] = (tdf_elemento) p;
}
}
}
I did some printf of that p (with %d and %i) and I get values like -1161602550, 1213357911, 994462027...
I really don't know what's going on, I also tried to change p for char[5] but didn't work so far...
Thank you in advance...

The "binary" open mode does not change the way fscanf parses the file. Its only effect is to (perhaps) prevent conversion of \r\n line endings to \n as the file is read by stdio facilities.
To read from a stdio file f into an integer i, you can do fread( & i, sizeof i, 1, f ). But note that this does not respect endianness. Without explicit byte-swapping your binary format will be platform-dependent on endianness.

Related

Reading Rows and Columns from File in C

I am trying to read this input txt file with my C code:
4 3
1.4 4.6 1
1.6 6.65 1
7.8 1.45 0
7 -2 2
and separate them into rows and columns so that I can sort. I tried doing that but I kept getting weird numbers.
So I tried printing out the rows and columns after I read them from the file and the output was zero. I realized then that my code is not reading the numbers from my text file properly. I have tried different means to fix to no avail. Any help or pointers will be highly appreciated.
#include <stdio.h>
#include <string.h>
#include <stdbool.h> //for bool
int main(){
setvbuf(stdout, NULL,_IONBF, 0);
int c;
FILE *file;
FILE *infile;
char filename[99];
char choice;
int rows, columns;
//while(choice == 'y' || choice == 'Y'){
printf("%s", "Enter file name: ");
fgets(filename, 99, stdin);
char *p = strchr(filename, '\n'); // p will point to the newline in filename
if(p) *p = 0;
file = fopen(filename, "r");
if (file) {
while ((c = getc(file)) != EOF)
putchar(c);
fclose(file);
}
else{
puts("FILE NOT FOUND");
}
//read rows and columns from file
printf("%s","\n");
fscanf(file, "%d", &rows);
fscanf(file, "%d", &columns);
printf("%d", rows);
printf("%d", columns);
}
Problem 1
int rows = 0;
int columns = 0;
float matrix[rows][columns];
float sumOfRows[rows];
is not right.
After that, the number of elements in matrix and sumOfRows is fixed. They won't change if you change the values of rows and columns later in your program.
You need to read the values of rows and columns first before you define matrix and sumOfRows.
Problem 2
fscanf(file, "%d", &matrix[rows][columns]);
printf("%f",matrix[rows][columns]);
are not right either. Given the defition of matrix, use of matrix[rows][columns] is not right. They access the array using out of bounds indices.
Remember that given an array of size N, the valid indices are 0 to N-1.
Here's one way to proceed to resolve your problems:
fscanf(file, "%d", &rows); // Use %d, not %f
fscanf(file, "%d", &columns); // Use %d, not %f
// Now define the arrays.
float matrix[rows][columns];
float sumOfRows[rows];
// Read the data of matrix
for (int i = 0; i < rows; ++i )
{
for (int j = 0; j < columns; ++j )
{
fscanf(file, "%f", &matrix[i][j]); // Use %f, not %d
}
}
Your problem (actually, two problems) are in the if (file) {... block. First, you use a loop to read all characters from the file. Because of that, at the end of the loop you are also at the end of the file. Any further calls to fscanf result in undefined behavior.
Second, if the file did not open, you print a message (to the wrong output) and still continue to the fscanf part, which definitely leads to undefined behavior.
Solution: Remove the while loop and fix the error handling code:
if(file) {
// Nothing!
} else {
perror(filename);
return 1; // or return EXIT_FAILURE;
}

Using file handling read integers from file and display data in array

# include <stdio.h>
main()
{
FILE *fp;
int a[10], n, i;
char file_name[20];
printf("enter the file name \n");
scanf("%s", file_name);
printf("enter number of integers \n");
scanf("%d", &n);
fp = fopen(file_name, "rb");
if (fp == NULL) {
printf("Error in opening file \n");
return;
}
fread(a, 1, n, fp);
for (i = 0; i < n; i++) {
printf("%d \n", a[i]);
}
}
Output:
enter the file name /home/n/t1.txt enter number of integers
3 1540736144 1540736144 1540736144..
In file t1.txt , i have entered the intergers {10,20,30,40.50}
and stored in path /home/n/t1.txt..
But in output it is displaying some junk addresses..
Kindly guide me how to display the integers stored in file..
Your file is a text file, which is human-readabla and can be edited in text editors. You treat it like a binary file, which stores data in the same way it is stored in the memory. Such files are compact and fast to read, but not easily editable or readable by humans.
The C standard provides different functions to deal with these file types. fwrite and fread are for binary files. fprintf, fscanf, fgets and so on are for text files.
There are several ways to parse your input and SO is full of examples. A cheap way to read data is fscanf. It ignores new-lines and just treats them as white space. It is not a good way to read input if you have more complex data or if you need good eror handling, but for your small example, it will do. Your input doesn't seem to be organised in lines.
The code below defines the function scan_int, which reads a number of integers from a file. The main function shows how to use this function.
#include <stdlib.h>
#include <stdio.h>
/*
* Read at most max integers from a file and store them in arr.
* Return the number of integers read or -1 on file access error.
* Numbers may or may not be separated with commas.
*/
int scan_int(const char *fn, int arr[], int max)
{
FILE *f = fopen(fn, "r");
int n = 0;
if (f == NULL) return -1;
while (n < max && fscanf(f, "%d,", &arr[n]) == 1) n++;
fclose(f);
return n;
}
int main(void)
{
int a[10];
int i, n;
n = scan_int("data.txt", a, 10);
for (i = 0; i < n; i++) {
if (i) printf(", ");
printf("%d", a[i]);
}
printf("\n");
return 0;
}

fscanf can't read the first integer of my file input in C but reads the rest

My program needs to read input from a file. The file has a format "int int int" and then some asterisks to indicate that you need to stop reading there. I want to store them in an array of struct and I did. But it seems like my program can't read the very first integer of the input file. I checked it with printf and I can't do anything about it. Help please. Here's the code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct points{
int i;
int x;
int y;
};
int main(){
int lines = 0;
char c, e;
int i, j, x ,y, a, b, temp ;
FILE *fp;
fp = fopen("input.txt", "r");
if (fp != NULL){
while ((e = fgetc(fp)) != '*'){
if (c == '\n'){
lines++;
}
fscanf(fp, "%d%d%d", &i, &x, &y);
struct points pt[lines];
for (j = 0; j <= lines; j++){
pt[j].i = i;
pt[j].x = x;
pt[j].y = y;
printf("%d ", pt[j].i);
}
for (a = 0; a<=lines; a++){
for (b = a + 1; b <= lines; b++){
if (pt[a].x > pt[b].x){
temp = pt[a].x;
pt[a].x = pt[b].x;
pt[b].x = temp;
}
}
}
}
}
else{
printf("Cannot open File!\n");
}
printf("lines = %d\n", lines);
return 0;
}
Your code:
while ((e = fgetc(fp)) != '*') {
if (c == '\n'){
lines++;
}
fscanf(fp, "%d%d%d", &i, &x, &y);
will read the first character and throw it away if it is NOT an asterisk, and will then attempt to read 3 integers AFTER that first character it threw away. If that first character was a digit, then it will look like you 'lost' (part of) the first number.
You also have the problem that you seem to be trying to read the values into a block-local array pt that exists for a single iteration of the while loop (so its recreated with no (garbage) contents each iteration), and then you want to use it after the loop where it is out of scope (so this code won't compile).
What you want is probably something more like:
#define MAX_POINTS 100
struct points pt[MAX_POINTS];
int i = 0;
while (i < MAX_POINTS && 3 == fscanf(fp, "%d%d%d", &pt[i].i, &pt[i].x, &pt[i].y)) {
printf("%d ", pt[i].i);
i++;
}
for (int a = 0; a <= i; a++) {
for (int b = a+1; b <= i; b++) {
:
Note that this reads integers up until it finds something that doesn't look like an integer (such as an asterisk, but could be anything else, including an end-of-file), rather than reading until it finds an asterisk. If you want to read until you see an asterisk, you need to decide what to do with anything that is neither an asterisk or an integer.
Edit
for your alternate question of how to read numbers up to *** and then read more numbers after them (and possibly more stars), you could use something like:
int val;
char buffer[20];
do {
/* start of a group */
while (1 == fscanf(fp, "%d", &val)) {
/* read an integer within a group */
}
/* fp is at EOF or something not an integer. */
/* so read it and loop if its '***' */
} while (1 == fscanf(" %19[*]", &buf) && !strcmp(buf, "***"));
Have you tried using the format string "%d %d %d" instead of "%d%d%d" (i.e. with spaces)?
Also, there are several other problems I see:
You use a while loop to find the first '*' in the line, but then you ask fscanf to parse 3 ints starting at that location. It may not be able to find an int by looking at a '*'...
You also declare the variable struct points pt[lines]; in the middle of a block; that is not valid C syntax.
Once you fix these things, the problem may be fixed.

C Read until end of file

I currently have code that reads 4 lines and I want to be able to change that until EOF or my MAX const int value. I can not get the !EOF to work right and was wondering how would I change my code to accomplish this?
Thanks in advance
#include <stdio.h>
struct record{
char name[2];
int arrival_time;
int job_length;
int job_priority;
};
const int MAX = 40;
int main(void)
{
struct record jobs[MAX];
int i = 0;
int j;
FILE *f = fopen("data.dat","rb");
while (fscanf(f, "%s %d %d %d", &jobs[i].name, &jobs[i].arrival_time,
&jobs[i].job_length, &jobs[i].job_priority) == 4 && i < MAX)
i++;
for (j = 0; j < i; j++)
printf("%s %d %d %d\n", jobs[j].name, jobs[j].arrival_time,
jobs[j].job_length, jobs[j].job_priority);
fclose(f);
return(0);
}
Something like
while (fscanf(f, " %s ", &etc) != EOF) {
}
Then use feof(f) to check if it was a fscanf error or actually EOF.
Your code seems to do what you want, except:
char name[2];
Names will probably be longer than 1 character.
FILE *f = fopen("data.dat","rb");
You seem to be reading text ("r") file, not binary ("rb").
&jobs[i].name should be jobs[i].name
You need to change the order of the tests in your while() loop - you must test i < MAX before calling fscanf(), or else you'll potentially call it one too many times (you should also be passing jobs[i].name without the & to fscanf):
while (i < MAX && fscanf(f, "%s %d %d %d", jobs[i].name, &jobs[i].arrival_time,
&jobs[i].job_length, &jobs[i].job_priority) == 4)
Personnaly, I would code like this:
for(i=0 ; i<MAX ; ++i) {
fscanf(f, "%s %d %d %d", &jobs[i].name, &jobs[i].arrival_time,
&jobs[i].job_length, &jobs[i].job_priority);
if(ferror(f) || feof(f)) break;
}
The key point is that, at the best of my knowledge, you cannot know that a file is come to end without trying to read it. That is the reason why I check feof() and ferror() after having read data.
At the end of the loop, the variable i contains the number of read data

Need help reading from a txt file in C

I am working on a project in C which requires me to read in matrix values from a txt file. The first two lines are the number of rows and columns, and the rest is the actual matrix data.
For example, something like this:
2
2
1.0 2.0
3.0 4.0
The code I wrote is giving me some issues. Here's a snippet:
matrix read(char* file){
FILE *fp;
printf("check 1\n");
fp = fopen(file,"r");
printf("file opened\n");
// Make the new matrix
matrix result;
printf("matrix created\n");
int counter = 0;
int i;
int j;
int holdRows;
int holdColumns;
if(counter == 0)
{ // read in rows
fscanf(fp, "%li", holdRows);
printf("here is holdRows: %li\n", holdRows);
counter++;
}
if(counter == 1)
{ // read in columns
fscanf(fp, "%li", holdColumns);
printf("here is holdColumns: %li\n", holdColumns);
counter++;
// Now that I know the dimensions, make the matrix
result = newMatrix(holdRows, holdColumns);
}
// For the rest, read in the values
for(i = 0; i < holdRows; i++)
for(j = 0; j < holdColumns; j++)
fscanf(fp, "%lf", &result->matrixData[i][j]);
fclose(fp);
return result;
}
Whenever I run this, holdRows and holdColumns are not the values stored in the txt file. For example, I tried a 3X4 matrix, and it read that there was one row and three columns.
Can anyone tell me what I'm doing wrong?
Thanks :)
Thanks to suggestions by you all and some sleuth work myself, I solved my problem. First, I was entering the wrong filename (well, now I feel silly), and second, I was reading the data in as the wrong type.
Thanks, everyone, for your help!
You are not passing the address of holdRows and holdColumns to fscanf. You have to change them to fscanf(fp, "%li", &holdRows); and fscanf(fp, "%li", &holdColumns);.
the %li conversion specification requires a long* as matching argument to fscanf(): you're passing a int (int* after correction proposed by dbarbosa).
Try "%i" ... and same for printf().
The %lf expects a double. Is matrix made of doubles?
Try replacing:
for(i = 0; i < holdRows; i++)
for(j = 0; j < holdColumns; j++)
fscanf(fp, "%lf", &result->matrixData[i][j]);
with
double temp;
for(i = 0; i < holdRows; i++)
for(j = 0; j < holdColumns; j++) {
fscanf(fp, "%lf", &temp);
result->matrixData[i][j] = temp;
}
I seem to recall that in C some types of 2D arrays don't play nice with &.

Resources