Passing fscanf to struct - c

I'm trying to open a file and pass to struct, I'm using fscanf() with a loop, but it only saves one the struct the last read:
Imagine a file:
JR John Rambo 24353432
JL John Lennon 6435463
I'm using this code:
typedef struct people{
char code[10];
char name[100];
long telephone;
}PEOPLE;
int read(PEOPLE people[], int n_p){
char temp;
FILE *fp;
fp=fopen("example.txt","r");
if(fp==NULL){
printf("Error\n");
return -1;
}
while(!feof(fp)){
fscanf(fp,"%s %s %s %d\n", people[n_p].code,people[n_p].name,
&people[n_p].telephone);
}
}
The Problem is that he only saves the last line of the file...Should I do a if cicle??
Another question is how can I separate a similar file but with ";"

First of all, you are scanning for 3 strings (%s) and one int (%d) when you pass only 3 parameters in your fscanf(). You could add a char first_name[50]; in your struct and then do:
fscanf(fp,"%s %s %s %d\n", people[n_p].code,people[n_p].first_name,
people[n_p].name, &people[n_p].telephone);
You always fscanf() the file until you have nothing more to read (due to the !feof(fp) because of the while. So in the last people[n_p] variable the last line of the file will be saved.
You could remove the while from read() and also add the FILE * as a parameter to the function so that you don't open the file each time you call read().
Something like this maybe:
main()
{
FILE* fp = fopen("example.txt", "r");
int i = 0;
while (!feof(fp)) {
read(people, i, fp);
i++;
}
}
int read(PEOPLE people[], int n_p, FILE* fp){
char temp;
if(fp==NULL){
printf("Error\n");
return -1;
}
fscanf(fp,"%s %s %s %d\n", people[n_p].code,people[n_p].first_name,
people[n_p].name, &people[n_p].telephone);
}
For using the ; as a separator you can change fscanf() to this:
fscanf(fp, "%[^;]; %[^;]; %d\n", people[n_p].code,people[n_p].name,
&people[n_p].telephone);
EDIT I wrote the above code which can be found here and it works fine with this example.txt file as input.

It looks like you're not changing the n_p variable. You need some sort of variable to keep track of which index of the people[] array you're updating.
Additionally, hopefully you've got a large enough people array to hold all the entries in the file.

Related

Trying to fscanf multiple values (3 strings + integer) in a single line

I need to scan 3 strings and an integer from an already existing file, and save them each as an element in an array of structures. The file is formatted as such:
string1 string2 integer string3
string1 string2 integer string3
... and so on.
when fscanf-ing for them, it correctly scans string1, the integer, and string3. However, string2 always appears to create an error when scanning it, and when any of the string2's are printed, they are either cut off short, or have some odd ASCII symbol, like a question mark in a box; it also sometimes triggers the system "bell" sound.
I've tested collecting the strings through fscanf for each different one, and it is only the second one that ever messes up.
A stripped-down version of my code, highlighting the issue
struct carinfo
{
char name[10];
char make[15];
int number;
char color[10];
}car[4];
filepointer = fopen("file.txt", "r");
while(!feof(filepointer))
{
for(i=0;i<4;i++)
{
fscanf(filepointer, "%s %s %d %s", &car[i].name[10],
&car[i].make[15], &car[i].number, &car[i].color[10]);
printf("%s\n", &car[i].make[15]);
}
}
my expected result is that the second string will scan properly, and be stored in its entirety to its element in the array of structures; instead, the value is usually cut off (at around 2-3 characters instead of 15) and contain weird ASCII symbols.
Changing fscanf() function to this, will solve your issue.
Code
fscanf(filepointer, "%s %s %d %s", car[i].name,
car[i].make, &car[i].number, car[i].color);
You can find true way of using fscanf() in cplusplus.com:
char str [80];
FILE * pFile;
pFile = fopen ("myfile.txt","w+");
fscanf (pFile, "%s", str);
But as chris-dodd stated at comment section using feof(filepointer) inside while loop not correct.
This code below i correct it by using fscanf() return value.
I obtain this way in a stack overflow answer by lio
Complete version of your program
main.c
#include <stdio.h>
struct carinfo
{
char name[10];
char make[15];
int number;
char color[10];
}car[4];
int main(){
int i=0;
FILE* filepointer = fopen("file.txt", "r");
if(!filepointer){
printf("can't open file\n");
}
int ret=0;
do {
for(i=0;i<4;i++){
ret=fscanf(filepointer, "%s %s %d %s", &car[i].name,
&car[i].make, &car[i].number, &car[i].color);
printf("%s\n", &car[i].make);
}
} while (ret != EOF);
return 0;
}
file.txt
salam beshoma 10 daram
kee innak 15 inomikhonid!

How to use fscanf to take huge input from file into an struct. ANSI C89(90)

I'm having a problem with some code in my program. I need to read a file and put it's content line by line into a struct. The file is about 800 lines long, and when i try to print my struct, which should now contain the content of the file, it only print about 30 of the lines as they should be. The rest is filed with error or wrong formatting. This is my function as it is now, and i simply call it in main. I am not sure what is wrong but maybe it has something to do with my malloc call?
void read_file(void){
int lines = count_lines(); /*function to count amount of lines in file*/
FILE *file;
int i = 0;
char filename[] = "race.txt";
file = fopen(filename, "r");
race_info *race = malloc(sizeof(race_info));
if (file != NULL) {
while (i < lines) {
fscanf(file, " %[A-Za-z]s %[A-Za-z]s %[A-Z]s %d %[A-Z]s %[A-Z]s %d %d",
race[i].race_name,
race[i].name,
race[i].lastname,
&race[i].age,
race[i].team,
race[i].country,
&race[i].position,
&race[i].time);
i++;
}
}
else {
perror(filename); //print the error message
}
for (i = 0; i < lines; i++) {
printf("%s %s %s %d %s %s %d %d",
race[i].race_name,
race[i].name,
race[i].lastname,
race[i].age,
race[i].team,
race[i].country,
race[i].position,
race[i].time);
}
fclose(file);
}
The struct is setup as following:
#define MAX_CHAR 100
struct race_info{
char race_name[MAX_CHAR];
char name[MAX_CHAR];
char lastname[MAX_CHAR];
int age;
char team[MAX_CHAR];
char country[MAX_CHAR];
int position;
int time;
};
typedef struct race_info race_info;
The lines from the file is setup as:
RaceName "Name LASTNAME" AGE TEAM Country Position TIME
The goal is to print the struct so that all 800 lines are printed with the same formatting as the file. But when printed it does only prints about 200 lines and and it does not go from start of file to the end, but takes content from the middle of it. A lot of the lines also have wrong formatting.
This race_info *race = malloc(sizeof(race_info)); seems to only allocate space for a single race_info.
You should probably have malloc(lines * sizeof(race_info)) for all the lines to fit.

Struct Memory Allocation from File in C, only two variables work

I have to write a program that will read text from a file, break it up into a struct, validate the sections to a certain criteria, then produce two new files; one with the clean data and one with the errors. So far i am up to the stage of breaking up the data from a file and storing it into a struct but it will only work for the first two variables.
the text is separated by colons and i need to put each section into the variables bellow
an example of the text file
0001:0002:0003:0021:CLS
here is my struct
struct packet{
int source;
int destination;
int type;
int port;
char data[50];
};
Bellow is whatworks fine, however as soon as i add another section to add data to the type variable, the program does not work.
fscanf(inFile, "%[^:]: %[^:]:", records[i].source, records[i].destination);
printf("%d - %s _ %s", i+1, records[i].source, records[i].destination);
However this does not work and i need it to. Well i need to expand upon it.
fscanf(inFile, "%[^:]: %[^:]: %[^:]:", records[i].source, records[i].destination, records[i].type);
printf("%d - %s _ %s _ %s", i+1, records[i].source, records[i].destination, records[i].type);
}
if i printf without inputting anything to the struct it displays null as i would expect because nothing is being stored so im thinking that there is something wrong with the fscanf function. As it works for the first two, i dont think that it is a syntax issue so it must be a memory issue. I have used malloc and realloc but ive gotten confused with it and im sure that i have not done it right.
Full Code Listing
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//declaration of function which will print my name and student number
const char * myname();
//declaration of a function that will prompt a user to enter a file and open it if it exists
int openfile();
struct packet{
int source;
int destination;
int type;
int port;
char data[50];
};
int main()
{
int recordCount = 0;
struct packet *records;
records =malloc(sizeof(struct packet));
// printing the my name and student number via the myname function
printf("%s\n", myname());
//executing the openfile function that will open a function
openfile(recordCount, records);
return 0;
}
const char * myname()
{
const char *x = "*************************\nUSERNAME\nUSER NUMBER\nCONTACT NUMBER\n*************************\n";
return x;
}
int openfile(int rCount, struct packet *records)
{
//file pointer which will keep track of the file being accessed
FILE *inFile ;
//creating variable that will hold what the user has entered for a filename to open
char inFileName[100] = { '\0'};
printf("Please Enter the File to open:");
//getting the users input and storing it into the variable just created
scanf("%s", inFileName);
//if the file does not exist, display an appropriate error message
if ((inFile = fopen(inFileName, "r")) == NULL)
{
printf("Cannot Open File **%s**\n", inFileName) ;
exit(1) ;
}
else {
//if the file does exist, process the data
while(fgets(inFileName, 100, inFile)!=NULL)
{
int i =0;
for (i=0; i<30;i++)
{
fscanf(inFile, "%[^:]: %[^:]: %[^:]:", records[i].source, records[i].destination, records[i].type);
printf("%d - %s _ %s _ %s", i+1, records[i].source, records[i].destination, records[i].type);
}
}
//close the file
fclose(inFile);
return 0;
}
};
You're doing it wrong:
fscanf(inFile, "%[^:]: %[^:]:", records[i].source, records[i].destination);
The %[] conversion specifier is for string, but you're passing the values of integers as if they were character pointers. Undefined behavior!
You should be getting heaps of warnings for this from any modern compiler, i.e. one that validates formatting strings.
There's no point in parsing integers as if they were strings, I don't understand why you're not just doing
fscanf(inFile, "%d:%d", &records[i].source, &records.destination);
for the first case.
Also, do note that it's much better to read in whole lines using fgets(), then parsing the line once read using sscanf(), than trying to combine the two steps with fscanf().
Last, you should check the return value of the conversion call to know how many conversion succeeded.

Error, expected a ']' when scanning from txt file to struct in C

I'm getting a strange error and I'm not sure why. I am attempted to scan from a txt file to a struct array and I am getting an error. It expects a ']' after SIZE even though I have a closing bracket for the array length.
Heres the snippet of code that the error is happening in. I am brand new to learning structures so if anything is wrong other than the initial question, please let me know.
Here is the struct definition:
struct employData{
char first[7];
char initial[1];
char last[9];
char street[16];
char city[11];
char state[2];
char zip[5];
int age;
char sex[1];
int tenure;
double salary;
};
and then here is the scan function that is not working:
int readData(employData){
int i = 0;
struct employData dataArray[SIZE];
fp = fopen("payfile.txt", "r");
if (fp != NULL){
printf("File opened. Scanning...");
while (!(feof(fp))){
fp = fscanf(fp, "%s %s %s %s %s %s %s %s %d %s %d %lf", dataArray[i].first, dataArray[i].initial, dataArray[i].last, dataArray[i].street, dataArray[i].city, dataArray[i].first, dataArray[i].state, dataArray[i].zip, dataArray[i].age, dataArray[i].sex, dataArray[i].tenure, dataArray[i].salary);
i++;
}
}
else {
printf("File open failed.");
}
}
Thanks!
Edit: Fixed blatant error. Still having intellisense error
You've got %c in your fscanf, which are for single characters, not strings as you seem to have.
Use %s for strings instead.
Edit: as #luk32 pointed out to me, fscanf needs file pointer as first place parametre.
fscanf = (fp, ...);
Source: http://www.manpagez.com/man/3/fscanf/
I'm goint to guess here...
You have somewhere a line such as this one:
#define SIZE 1000;
So the definition of the struct array will expand from:
struct employData dataArray[SIZE];
to:
struct employData dataArray[1000;];
And now the error is obvious.
The solution is easy: remove the semicolon from the macro definition:
#define SIZE 1000

Reading a data file and storing into array of structures

I'm attempting to read a data file and to store the information into an array of course structures (or an array of pointers to course structures). This assignment requires maintaining a database using an array of pointers to the student structures.
I'm getting a segmentation fault when I attempt to scan the data file into the array. How can I properly store the information from the file into the array?
#define SIZE 30
#define fieldLength 300
#define diskFile "diskFile.dat"
#define courseFile "course.dat"
struct student
{
char name[fieldLength];
int age[fieldLength];
char course1[fieldLength];
char course2[fieldLength];
char remarks[fieldLength];
}*sp[SIZE];
struct course
{
char name[fieldLength];
char number[fieldLength];
char instructor[fieldLength];
char date[fieldLength];
char starting[fieldLength];
char ending[fieldLength];
char location[fieldLength];
};
int main(int argc, char *argv[])
{
int i, count;
struct course course_arr[SIZE]; // an array of ten structs
FILE * in; /*FILE pointer to do the stream IO*/
in = fopen(courseFile, "r+");
count = 0;
while ((fscanf(in, "%s %s %s %s %s %s %s",
&course_arr[count].name,
&course_arr[count].number,
&course_arr[count].instructor,
&course_arr[count].date,
&course_arr[count].starting,
&course_arr[count].ending,
&course_arr[count].location)) != EOF)
{
count++;
}
/* print the menu */
printf("\n-----------------------------------------------------------------\n");
printf("|\t%-20s","(N)ew record");
printf("%-20s","(U)pdate record");
printf("Swa(p) records\t|\n");
printf("|\t%-20s","(S)ort database");
printf("%-20s","(C)lear database");
printf("(D)isplay db\t|\n");
printf("|\t%-20s","(L)oad disk");
printf("%-20s","(W)rite disk");
printf("(E)mpty disk\t|\n");
printf("|\t%-20s", "(V)iew courses");
printf("%-20s","(R)emove record");
printf("(Q)uit \t|\n");
printf("-----------------------------------------------------------------\n");
printf("choose one: ");
Routine fscanf never returns EOF.
Test fscanf to be less than the number of expected fields:
count = 0;
while((fscanf(in, "%s %s %s %s %s %s %s", &course_arr[count].name, &course_arr[count].number, &course_arr[count].instructor, &course_arr[count].date, &course_arr[count].starting, &course_arr[count].ending, &course_arr[count].location)) < 7){
count++;
}
i think that it is better to work with
while(getline(string_variable,,)!=EOF).(look on the net on which argumentsto put in the getline)
Then work with the string_variable. Look at the format that the data is stored into the txt file. eg: name(blank)number(blank)instructor(blank)date(blank)starting(blank)endinglocation
Start looking for blanks in the string_variable. when you see the first blank copy the substring from position 1 to position blank-1 to the course_arr[count].name variable.then delete the substring from position 1 to position blank. Look again for the first blank and store the substring to course_arr[count].number and so on.
Sorry for my English hope u got the meaning
You should loose all the &s in the fscanf call. The char arrays are already passed as pointers. If you'd used the -Wall option on gcc (or a similar option for any other compiler) it will warn you for this as well.
Have you checked the file what you are reading is present or not.
add bellow
in = fopen(courseFile, "r+");
if(in == NULL)
{
printf("exit");
exit(0);
}
I guess it might be the problem.

Resources