Can't read a structure from text file - C - c

I'm trying to make a function that would read structures from a TEXT file and would print it. However, my while loop doesn't work somehow and I don't know why:
#include <stdio.h>
#include <stdlib.h>
struct data {
char foodName[FILENAME_MAX];
int rating;
double price;
};
FILE* openFile(char antraste[], char rezimas); <--- this function works ant it just opens a text file, so don't look into this
int main() {
FILE* dataText = openFile("Input data file: ", 'r');
struct data food;
while(fread(&food, sizeof(struct data), 1, dataText)) <--- it doesn't go inside the cycle
{
printf ("name = %s rating = %d price = %d\n", food.foodName, food.rating, food.price);
}
fclose(dataText);
printf("Done\n");
return 0;
}
My data.txt file looks like this:
Pasta 4.5 2.5
Soup 3.4 1.4
Pie 4.8 3.5

You should use fscanf and not the fread function.
This because the fread expect to read a binary file, while the fscanf read the text file.
More detailed info on fread and fscanf at this link.

Related

How do I read data from a file from each line and store it into a structure array

Below is my code, I have been working on this part for some structure am create a C socket server that can process data for clients, but I got a problem in file handling. I wanted to pick data from a file and store it into a structure at specific portions and then I erase the file according to data I have picked.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "struct.h"
struct student {
char command[10];
char value[50];
char user[50];
};
int main() {
int size, i;
struct student s1[256];
FILE *file = fopen("file.txt", "r");
if (file == NULL) {
printf("Error in reading student data");
return 1;
}
size = 0;
while(fscanf(file,"%s,%s,%s",
s1[size].command,
s1[size].value,
s1[size].user) != EOF) {
printf("%s%s%s\n",s1[size].command,s1[size].value,s1[size].user);
printf("%s\n",s1[size].command);
size++;
}
fclose(file);
return 0;
}
I wanted to pick data from my file which contains the below information and I store it in specific portions of my structure array
a,w,a
r,e,1
i.e. if I store
a in s1[0].command
w in s1[0].value
a in s1[0].user
and
r in s1[1].command
e in s1[1].value
1 in s1[1].user
But when I try running my code it prints
a, w, a in s1[0].command
and
r, e, 1 in s1[1].command
so I am kindly requesting for help because I have tried googling but I couldn't get a solution.
The "%s" format reads space-separated "words".
If there isn't a space separating the "words" you have to use some other way to parse the input. For example by reading the whole line and then use something like strtok to "tokenize" the string.
Or make sure that the input format is space-separated.

convert Ascii code file into binary file

I have a problem of converting ASCII code file into binary file. The code is able to read file and print data into other file as ASII code ( using fprintf); however, when I try to convert from ASII code to binary file ( using fwrite), and then use (fread) the file again. It doesn't generate the right answer. My doubt is the fwrite function doesn't work probably. Could you please advise on how to fix this problem? Thank you very much.
============================================
Code to convert from ASCII to binary file
===========================================
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
typedef struct _FileData
{
int a;
double b;
char dataStr[56];
}FileData;
int main()
{
// open read file
FILE * infile=fopen("output.txt", "r");
if(infile==NULL)
{
printf("Error opening file");
exit(1);
}
// open write file
FILE * outfile = fopen("out_file.txt","wb");
if( outfile==NULL)
{
printf("Error writting on file");
exit(1);
}
FileData input; // pointer for read file
FileData output; // pointer for write file
while( fscanf(infile,"%d %lf %[^\n]s",&input.a,&input.b,&input.dataStr)==3)
{
/*printf("%d\n",input.a);
printf("%.3lf\n",input.b);
printf("%s\n",input.dataStr);*/
//fprintf(outfile,"%d\n %.3lf\n %s\n",input.a,input.b,input.dataStr);
fwrite(&output,sizeof(FileData),1,outfile);
}
fclose(infile);
fclose(outfile);
return 0;
}
==============================================================
Code to convert from binary file to ASCII code file
=============================================================
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
typedef struct FileData
{
int a;
double b;
char dataStr[56];
}FileData;
int main()
{
FILE * infile=fopen("out_file.txt", "rb");
if(infile==NULL)
{
printf("Error opening file");
}
FileData input;
while(fread(&input,sizeof(struct FileData),sizeof(struct FileData),infile))
{
printf("%d\n",input.a);
printf("%.3f\n",input.b);
printf("%s\n",input.dataStr);
}
return 0;
}
===========================================================
Data
==========================================================
47
34.278
This is a line of text
48
23.678
This a very very long line
fread(&input,sizeof(struct FileData),sizeof(struct FileData),infile)
should be changed to
fread(&input,sizeof(struct FileData),1,infile)
You want to write 1 struct of size sizeof(struct FileData)
Also check the answer of mash5 where he suggests writing variable input instead of output while writing with fwrite.
In your ASCII conversion code, the input file is read into one variable input
fscanf(infile,"%d %lf %[^\n]s",&input.a,&input.b,&input.dataStr)
but a different, uninitialized, variable output is being written to the output file:
fwrite(&output,sizeof(FileData),1,outfile);
Perhaps you should write
fwrite(&input,sizeof(input),1,outfile);
instead?

Reading the linux utmp file without using fopen() and fread()

I am trying to open the utmp file in Linux and read the contents into an array of utmp structures. After that I display the ut_user and ut_type from each structure in the array. I have this working when I open the file with File *file and use the fopen() and fread() functions but when I try to do the same task with just a file descriptor int file and the open() and read() functions I get address locations when trying to access members of the utmp structure.
So in the below program you can see I commented out three lines of code which together I could use to successfully perform the task of reading the utmp file into an array of utmp structures and print out two of their members values. But when I try doing the exact same thing with the three lines of code (denoted "new way") in place of the old way that worked I get a bunch of address locations rather than the values of ut_user and ut_id.
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <utmp.h>
void utmpprint(struct utmp *log) {
printf("\n ut_user: %s \n ut_type: %ld \n", log->ut_user, log->ut_type);
}
int main() {
int logsize = 10;
//FILE *file; //Working way
int file; //New way
struct utmp log[logsize];
int i = 0;
//file = fopen("/var/run/utmp", "rb"); //Working way
file = open("/var/run/utmp", O_RDONLY); //New way
if( file < 0 ) { //New way
printf("Failed to open");
return(0);
}
if (file) {
//fread(&log, sizeof(struct utmp), logsize, file); //Working way
read(file, &log, logsize); //New way
for(i = 0; i < logsize; i++) {
utmpprint(&log[i]);
}
close(file); //New way
} else {
return(0);
}
return(0);
}
Here is some of the output for the working way:
And here is the output for the new way that is not working:
I have tried looking online for more information on this matter but I can't seem to find anything that uses the file descriptor and not File. I also tried changing around some of the pointers and references but that did not improve any of the results.
I am very new to C and I think I am probably using the read() function incorrectly in this case because I am passing a simple buffer into the read function when I think I should be somehow passing it the utmp structure array.
You are not reading enough data from the file.
read(file, &log, logsize);
should be:
read(file, &log, sizeof(log));
// or
read(file, &log, logsize * sizeof (struct utmp));
Also, in both cases, you should check the return value to see how many bytes were actually read.
Even though you could manipulate data from the utmp file by using the open() system call or functions derived from open(), it is impractical.
You could include the "utmp.h" header in your project and use predefined functions and data structures.
Here you can find the utmp.h file documentation.
Below is some code to print the ut_user and ut_type using the utmp.h data structures and functions.
#include <utmp.h>
#include <stdio.h>
#include <string.h>
int main()
{
struct utmp* data;
char aux[50];
data = getutent();
//getutent() populates the data structure with information
while(data != NULL )
{
/*make sure to use strncpy
*because most data fiels in the utmp struct
*have ___nonstring___ atribute */
strncpy(aux, data->ut_user, 32);
aux[32] = '\0';
printf("ut_user: %s\n", aux);
printf("ut_type: %hi\n\n", data->ut_type);
data = getutent();
}
return 0;
}
The output of the code is:
ut_user: reboot
ut_type: 2
ut_user: alc
ut_type: 7
ut_user: runlevel
ut_type: 1

Processing each line to be stored as a structure

I am writing a program which should do multiple things including prompting the user for the name of the input file which I have done, but I am having troubling implementing a process where the program processes each line from a file, storing it as a struct data structure, finally using the malloc, calloc commands it will store all the valid records in memory to be validated. So any help on how to do this would be helpful.
#include <stdio.h> //library including standard input and output functions
#include <stdlib.h> //library including exit and system functions used below
#include <string.h> //library including string functions used
struct packet{
int source;
int destination;
int type; // Varibles for the structure
int port;
char data[50];
char * filename;
};
int main ()
{
printf("**************Details*******************************\n");
printf("*****Student name: ***********************\n");
printf("*****Course name: *******\n");
printf("*****Student ID: ************************ \n");
printf("\n");
// The program must prompt for the name of the input file. If it doesn't exist the program should stop with an error message
FILE *DataFile;
char filename[10] = { '\0' } ;
char DataLine[70];
printf("Enter the filename you wish to open\n");
scanf("%s", &filename);
if (( DataFile = fopen(filename, "r")) == NULL)
{
printf ("*****file could not be opened. : %s\n", filename);
exit(1);
}
// Read the data from this file
char *fgets(DataLine, 70, (FILE) *DataFile);
system("pause");
return 0;
}
Here is the text file the program should take the data from
0001:0002:0003:0021:CLS
0001:0010:0003:0021:CLS
0001:0002:0002:0080:<HTML>
0005:0002:0002:8080:<BR>
0005:0012:0002:8080:<BR>
0001:0002:0002:0080:<BODY>
0005:0002:0002:8080:<B>HELLO</B><BR>
0002:0004:0002:0090:100000000000000000022
0001:0002:0003:0021:DEL
0002:0004:0002:0010:100000000000000000023
Each colon from the file shows what part of the packet structure it should be a part of, i.e. the first set of 4 numbers is the "source" then "destination and so forth.
One way to do this is :
Use fgets to read the file line by line.
For each line, use strtok to tokenize the string.
For each of the first four tokens, use strtol to convert it to an integer.
A. The line char *fgets(DataLine, 70, (FILE) *DataFile); should probably just read fgets(DataLine, 70, DataFile);
B. If you create a single variable you don't really need malloc since the compiler will allocate it, but if you are planning on creating an array of Data you will only need to call malloc once to create the whole array, something like:
struct packet* packetarr = malloc(sizeof packetarr * DESIRED_ARRAY_SIZE);
C. As downHillFromHere suggested, use strtok to get each part of the string and strtol to convert the read strings to numbers when appropriate.

Displaying information from an external file in C

How do I read in an external file and then either print the whole text or selected lines?
FILE *fp;
fp=fopen("c:\\students.txt", "r");
I understand that reads the file but after that I am lost. Help please!!!
Do I need to read in binary or is text file acceptable?
You get a pointer to the file stream with fopen()
fread() will only return the amount of actual data that the program
could find inside your .txt file - It's very misleading. The main use is getting the number of elements for your loops. You can upload a file into your program, and print it on the screen without ever touching this function, if you know exactly what the file should already have. Only use this if you don't know what's in your file.
getline() is your go-to for printing out a specific line. No way around this one, and you'll need the specific library for it.
Here's an Example Code I wrote while doing a self-study on this, just showing how each of these are used, and printing out on BOTH the program, and a separate txt file outside the program. It doesn't have getline() however.
/*
Goals:
Create an array of 5 values
Input 5 vales from a pre-created file, into the new array
Print out the 5 values into another file.
Close the file.
*/
#include <stdio.h>
#include <stdlib.h>
#define DATAFILE "E:/Data.txt"
#define REPORT "E:/Report.txt"
//prototypes
FILE *Open_File();
void Consolodate_Array(int a_array[], FILE *file_pointer);
void Print_File(int a_array[], FILE *report_pointer);
void end_function(FILE *file_pointer, FILE *report_pointer);
int main(int argc, char *argv[])
{
int array[5];
FILE *Datatext = Open_File();
//Declared "Datatext" to be equal to Open_File's Return value.
//FILE itself is like Int, Double, Float, ect.
FILE *ReportText = fopen(REPORT, "w");
//Did the same as above, just not in a separate function. This gives us a
//Pointer to the REPORT.txt file, in write mode instead of read mode.
Consolodate_Array(array, Datatext);
Print_File(array, ReportText);
end_function(Datatext, ReportText);
system("PAUSE");
return 0;
}
/*----------------------------------------------------------------------*/
//This function should open the file and pass a pointer
FILE *Open_File()
{
return fopen(DATAFILE, "rb");
}
/*----------------------------------------------------------------------*/
//This function should input the variables gotten for the file, into the array
void Consolodate_Array(int a_array[], FILE *file_pointer)
{
for(int i=0; i<5; i++)
fscanf(file_pointer, "%i", &a_array[i]);
}
/*----------------------------------------------------------------------*/
//This function prints out the values into the second file, & at us too.
void Print_File(int a_array[], FILE *report_pointer)
{
for(int i=0; i<5; i++)
{
printf("%i\n", a_array[i]);
fprintf(report_pointer, "%i\n", a_array[i]);
}
}
/*----------------------------------------------------------------------*/
//This function closes the file.
void end_function(FILE *file_pointer, FILE *report_pointer)
{
fclose(file_pointer);
fclose(report_pointer);
//closes both files we worked on.
}

Resources