Segmentation fault occurring at very straight-forward part of the code - c

When I run the program the first time (the output file is not yet created), it works fine. But when I run it again (output file exists), it gives a segmentation fault after reading the last input.
From looking at the problem, it looks like it has something to do with my file handling, but when I tried to debug, I found out that I get the seg. fault before exiting the for loop in main().
#include <stdio.h>
#define EMPS 3
struct employee
{
char firstname[40];
char lastname[40];
int id;
};
typedef struct employee Employee;
/* Input the employee data interactively from the keyboard */
void InputEmployeeRecord(Employee *ptrEmp);
/* Display the contents of a given Employee record */
void PrintEmployeeRecord(const Employee e);
/* Save the contents of the employee record list to the newly
created text file specified by FileName */
void SaveEmployeeRecord(const Employee e[], const char *FileName);
int id = 0;
int main()
{
Employee employees[EMPS];
for(int i = 0; i < EMPS; i++)
{
InputEmployeeRecord(&(employees[i]));
PrintEmployeeRecord(employees[i]);
}
SaveEmployeeRecord(employees, "employee.dat");
return 0;
}
void InputEmployeeRecord(Employee *ptrEmp)
{
printf("Enter first name\n");
scanf("%s", ptrEmp->firstname);
printf("Enter last name\n");
scanf("%s", ptrEmp->lastname);
ptrEmp->id = ++id;
}
void PrintEmployeeRecord(const Employee e)
{
printf("Employee %d: %s %s\n", e.id, e.firstname, e.lastname);
}
void SaveEmployeeRecord(const Employee e[], const char *FileName)
{
FILE* fptr = fopen(FileName, "r");
/* File doesn't exist */
if(fptr == NULL)
{
fclose(fptr);
// Create the file
FILE* fptr2 = fopen(FileName, "w");
fclose(fptr2);
// continue reading
fptr = fopen(FileName, "r");
}
char firstLetter;
int headerExists = 0;
if(!feof( fptr ))
{
fscanf(fptr, "%c", firstLetter);
if(firstLetter == 'I')
headerExists = 1;
}
fclose(fptr);
FILE* fptr2 = fopen(FileName, "a");
if(!headerExists)
fprintf(fptr2, "ID FIRSTNAME LASTNAME");
for(int i = 0; i < EMPS; i++)
fprintf(fptr2, "\n%d %s %s", e[i].id, e[i].firstname, e[i].lastname);
fclose(fptr2);
}
[ Code originally at http://pastebin.com/tLefJhEH ]

The problem probably lies at the fscanf(fptr, "%c", firstLetter);. %c expects a char* as input while you are giving it a char (which is an integer in c).
To fix it try fscanf(fptr, "%c", &firstLetter);
Also calling fclose on a null pointer is not recommended.

My mistake, it's this line:
68. fscanf(fptr, "%c", firstLetter);
Should be:
68. fscanf(fptr, "%c", &firstLetter);
Argments to fscanf and scanf are addresses of the memory locations to store the data.
You don't need the & for a string because a string is already an address.

Related

Saving data from a file to a struct in c

I have two structs that I have to fill with student data. The data is in the format:
age, name, grade, age, group, turn
and in the header of the file is the number of student in the data.
struct school //school
{
char group; //A,B,C,D,E,F
char turn; //Morning, AFTERNOON
};
struct student
{
char *name;
char *grade;
int age;
struct school *E;
}student[6];
I tried to save first the data from a text with only the age, name, and grade to see if I could do it:
void get_file(const char* file, int *n){ //n is the amount of students
FILE* fptr;
fptr = fopen(file, "r");
if (fptr == NULL){
printf( "\n Error \n");
exit(1);
}
char* temp;
int tam = 0;
fscanf(fptr, "%d", n); //size of the list of students
for(int i= 0; i < *n; i++){
fscanf(fptr, "%d,%s,%s", &student.age[i],temp, student[i].grade);
tam = strlen(temp);
student[i].name = (char*)malloc(tam * sizeof(char));
strcpy(student[i].name, temp);
printf("%s\n", student[i].name);//to see if it's correct the content
}
fclose(fptr);
}
But, student.name store for example "Josh, A+" when it should only be "Josh". How can I fix this?
It's for an assignment.
EDIT:
My data looks like this
4 //size of list
Josh,A,20,D,M
Amber,B,23,E,M
Kevin,C,22,D,A
Adam,A+,21,C,A
Using the Remy Lebeau's solution, I got this
void get_file(const char* file, int *n){
*n = 0;
FILE* fptr = fopen(file, "r");
if (fptr == NULL){
printf( "\n Error \n");
exit(1);
}
char name[80];
char grade[2];
fscanf(fptr, "%d", n); //size of the list of students
for(int i = 0; i < *n; i++){
fscanf(fptr, "%80[^,],%2[^,],%d,%c,%c", &student[i].age, name, grade,&student[i].group, &student[i].turn);
student[i].name = strdup(name);
student[i].grade = strdup(grade);
}
fclose(fptr);
}
But I got a problem, because I made this change
struct student
{
char *name;
char *grade;
int age;
struct school E; //it was struct school *E
}student[6];
to pass the information, but my Teacher said that I couldn't change it, so how can I load information in struct school *E?
There are multiple problems with your call to fscanf():
&student.age[i] needs to be &student[i].age.
temp and student::grade are uninitialized pointers, they don't point anywhere, so reading data to memory pointed by them is undefined behavior. fscanf() will not allocate memory for you, you need to pre-allocate char[] buffers yourself for fscanf() to then read into.
%s reads non-whitespace characters including ',', which is why your code is not stopping on the , following Josh. Try using %[^,] instead of %s for that field.
Try something more like this:
void get_file(const char* file, int *n){
*n = 0;
FILE* fptr = fopen(file, "r");
if (fptr == NULL){
printf( "\n Error \n");
exit(1);
}
char name[256];
char grade[5];
fscanf(fptr, "%d", n); //size of the list of students
for(int i = 0; i < *n; i++){
fscanf(fptr, "%d,%255[^,],%4s", &student[i].age, name, grade);
student[i].name = strdup(name);
student[i].grade = strdup(grade);
printf("%d %s %s\n", student[i].age, student[i].name, student[i].grade);
}
fclose(fptr);
}
UPDATE:
The file data you have now shown does not match the format you described, which your code is expecting. You described (and coded) the file data as:
age, name, grade, age, group, turn (why 2 ages?)
But what you have shown looks more like:
name, grade, age, group, turn
You changed your format string in fscanf() to this new format, but you didn't change the order of the variables being read into to match this format. So, you are reading the name value into your age field, the grade value into the name field, and the age value into the grade field.
Also, you are not even attempting to handle group and turn correctly. They reside in a completely different structure, which you are not allocating any memory for. You need to allocate a school object, read group and turn into it, and then assign it to student[i].E.
With that said, try something more like this:
struct school
{
char group; //A,B,C,D,E,F
char turn; //Morning, AFTERNOON
} school[6];
struct student
{
char *name;
char *grade;
int age;
struct school *E;
}student[6];
void get_file(const char* file, int *n){
*n = 0;
FILE* fptr = fopen(file, "r");
if (fptr == NULL){
printf( "\n Error \n");
exit(1);
}
char name[81];
char grade[3];
fscanf(fptr, "%d", n); //size of the list of students
for(int i = 0; i < *n; i++){
student[i].E = &school[i]; // or, use malloc() instead, if needed...
fscanf(fptr, " %80[^,],%2[^,],%d,%c,%c", name, grade, &(student[i].age), &(student[i].E->group), &(student[i].E->turn));
student[i].name = strdup(name);
student[i].grade = strdup(grade);
}
fclose(fptr);
}

C Input value from .txt to struct

I need to scan values from .txt to a structure so I can work further on with my program. I've been trying various methods from the thread and this is the closes I got to a successful build.
I can NOT get the values to be printed out so I can test if they scanned correctly before working my way further into the program.
I have different values in struct:
struct knyga
{
char vardas[10];
char pavadinimas[50];
int metai;
double kaina;
};
and this is my reading function:
void Skaitymas(struct knyga arr_knyga[]){
FILE *fp;
fp = fopen("duomenys.txt", "r");
int skaicius;
int txt;
txt = fgetc(fp);
while((txt = fgetc(fp)) != EOF){
if(txt == '\n') skaicius++;
txt = fgetc(fp);
}
printf("%d", skaicius);
fp = fopen("duomenys.txt", "r");
for(int i = 0; i < skaicius; i++){
fscanf(fp, "%s %s %d %lf", arr_knyga[i].vardas, arr_knyga[i].pavadinimas, &arr_knyga[i].metai, &arr_knyga[i].kaina);
}
fclose(fp);
}
EDIT:
This is the content of my text file:
Onute Knyga 1999 12.12
Petras Knygute 2001 9.99
EDIT 2:
my main function:
int main() {
struct knyga arr_knyga[10];
Skaitymas(arr_knyga);
return 0;
}
You call txt = fgetc(fp); too often. The two occurrences of this line must be removed.
Especially in the loop you have one call to fgetc that is checked for '\n' and a second call that is not checked, so there is a 50%/50% chance that a '\n' is not counted.
You forgot to initialize the counter variable.
The counting would be correct with this version:
void Skaitymas(struct knyga arr_knyga[]){
FILE *fp;
fp = fopen("duomenys.txt", "r");
int skaicius = 0;
int txt;
while((txt = fgetc(fp)) != EOF){
if(txt == '\n') skaicius++;
}
printf("%d", skaicius);
fclose(fp);
}
But it would be better to omit the line-counting and detect the end-of-file condition in the fscanf loop.
void Skaitymas(struct knyga arr_knyga[]){
FILE *fp;
fp = fopen("duomenys.txt", "r");
int skaicius = 0;
int rc;
while(1)
{
rc = fscanf(fp, "%s %s %d %lf", arr_knyga[skaicius].vardas, arr_knyga[skaicius].pavadinimas, &arr_knyga[skaicius].metai, &arr_knyga[skaicius].kaina);
if(rc == 4)
{
skaicius++;
}
else
{
break;
}
}
if(!feof(fp))
{
fprintf(stderr, "error reading file or wrong data after line %d\n", skaicius);
}
else
{
printf("%d", skaicius);
}
fclose(fp);
}

Im having a problem with reading a file, then assigning it to a struct array and printing it back out

Im currently having to take an input.txt file, where it goes something like
3
Sarah 90 40 30
John 23 55 33
help 34 99 74
as an input file,
and read it into a struct array, then create an output.txt.
I seem to be having a problem with the assignment. I tried fscanf, fgetc, fgets, strtok, delim and everything i could find on the internet, but due to my sloppy pointer knowledge, i seem to be stuck.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
typedef struct studentT{
char *name;
int literature;
int math;
int science;
}studentT;
int main(void)
{
printf("Start of main\n");
FILE *fptr;
int i;
fptr = fopen("input.txt", "r");
//reading first line to dynamically allocate studentT
printf("dynamically allocating studentT\n");
char tempsize[4];
//fgets(tempsize,1,fptr);
//i=atoi(&tempsize[0]);
fscanf(fptr,"%d",&i);
struct studentT* record = malloc(i*sizeof(*record));
printf("i has interger value %d\n", i);
//line counter ignoring line 0; reading 1 and 2.
char line[24];
char buffer[24];
char delim[] = " ";
char *array[4];
int *darray[4];
printf("entering while loop\n");
fgets(buffer,24,fptr);
int idx =0;
while(fgets(line, sizeof(line),fptr)!=NULL &&idx<i)
{
puts(line);
char *buf = strtok(line, delim);
int iter =0;
while(buf!=NULL)
{
if(iter = 0){
array[iter]=buf;
buf = strtok(NULL,delim);
}
for(iter=1;iter<4;iter++){
*darray[iter] =atoi(buf);//
printf("%d,",*darray[iter]);
buf=strtok(NULL, delim);
}
}
record[idx].name=array[0];
record[idx].literature=*darray[1];
record[idx].math=*darray[2];
record[idx].science=*darray[3];
// printf("array value: %s %d %d %d\n",array[0], array[1], array[2], array[3]);
// printf("value after casting: %s %zu %zu %zu\n", array[0], (uintptr_t)array[1], (uintptr_t)array[2], (uintptr_t)array[3]);
//sscanf(buf,"%s %d %d %d",record[idx].name, &record[idx].literature, &record[idx].math, &record[idx].science);
printf("%s\n", line);
//fscanf(fptr,"%s %d %d %d",record[idx].name, &record[idx].literature, &record[idx].math, &record[idx].science);
line[strlen(line)-1]='\0';
printf("in idx loop %d %s %d %d %d\n\n", idx, record[idx].name, record[idx].literature, record[idx].math, record[idx].science);
idx++;
}
//output of file
printf("output commencing\n\n\n");
int tempave;
FILE *fout;
char *str1 = "Name Literature Math Science Ave.\n";
char *str2 = "Ave. ";
char *str3 = "Sarah\t 96\t 90\t 80\t 88.67";
char *str4 = "Minsu\t 55\t 70\t 76\t 67.00";
char *str5 = "Nara\t 88\t 70\t 96\t 84.67";
char *str6 = "79.67 76.67 84.00 80.11";
fout = fopen("output.txt", "w");
fprintf(fout,"%s\n", str1);
for(int idx=0;idx<i;idx++){
tempave = (record[idx].math+record[idx].literature+record[idx].science)/3;
fwrite(&record[idx],sizeof(struct studentT),1,fout);
fprintf(fout, "%d\n",tempave);
}
//fprintf(fout, "%s\n %s\n %s\n %s %s\n",str3,str4,str5,str2,str6);
fprintf(fout,"%s",str2);
float mathave,litave,sciave;
for(int idx=0;idx<3;idx++){
mathave+=record[idx].math;
litave+=record[idx].literature;
sciave+=record[idx].science;
}
mathave=mathave/3;
sciave=sciave/3;
litave=litave/3;
fprintf(fout,"%f %f %f",litave, mathave, sciave);
fclose(fptr);
fclose(fout);
}
edit: colleague mentioned I should malloc arrays so the code now looks uglier:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
typedef struct studentT{
char *name;
int literature;
int math;
int science;
}studentT;
int main(void)
{
printf("Start of main\n");
FILE *fptr;
int i;
fptr = fopen("input.txt", "r");
//reading first line to dynamically allocate studentT
printf("dynamically allocating studentT\n");
char tempsize[4];
//fgets(tempsize,1,fptr);
//i=atoi(&tempsize[0]);
fscanf(fptr,"%d",&i);
struct studentT* record = malloc(i*sizeof(*record));
printf("i has interger value %d\n", i);
//line counter ignoring line 0; reading 1 and 2.
char line[24];
char buffer[24];
char delim[] = " ";
char *array[4];
int darray[4];
printf("entering while loop\n");
fgets(buffer,24,fptr);
int idx =0;
while(fgets(line, sizeof(line),fptr)!=NULL &&idx<i)
{
puts(line);
char *buf = strtok(line, delim);
int iter =0;
while(buf!=NULL)
{
if(iter = 0){
array[iter] = malloc(sizeof(char)*strlen(buf));
strcpy(array[iter],buf);
buf = strtok(NULL,delim);
}
for(iter=1;iter<4;iter++){
darray[iter] = (int*)malloc(sizeof(char)*strlen(buf));
memcpy(&darray[iter],buf,(sizeof(char)*strlen(buf)));//
buf=strtok(NULL, delim);
}
}
record[idx].name=malloc(sizeof(char)*strlen(array[0]));
strcpy(record[idx].name,array[0]);
record[idx].literature=darray[1];
record[idx].math=darray[2];
record[idx].science=darray[3];
// printf("array value: %s %d %d %d\n",array[0], array[1], array[2], array[3]);
// printf("value after casting: %s %zu %zu %zu\n", array[0], (uintptr_t)array[1], (uintptr_t)array[2], (uintptr_t)array[3]);
//sscanf(buf,"%s %d %d %d",record[idx].name, &record[idx].literature, &record[idx].math, &record[idx].science);
printf("%s\n", line);
//fscanf(fptr,"%s %d %d %d",record[idx].name, &record[idx].literature, &record[idx].math, &record[idx].science);
line[strlen(line)-1]='\0';
printf("in idx loop %d %s %d %d %d\n\n", idx, record[idx].name, record[idx].literature, record[idx].math, record[idx].science);
idx++;
}
//output of file
printf("output commencing\n\n\n");
int tempave;
FILE *fout;
char *str1 = "Name Literature Math Science Ave.\n";
char *str2 = "Ave. ";
char *str3 = "Sarah\t 96\t 90\t 80\t 88.67";
char *str4 = "Minsu\t 55\t 70\t 76\t 67.00";
char *str5 = "Nara\t 88\t 70\t 96\t 84.67";
char *str6 = "79.67 76.67 84.00 80.11";
fout = fopen("output.txt", "w");
fprintf(fout,"%s\n", str1);
for(int idx=0;idx<i;idx++){
tempave = (record[idx].math+record[idx].literature+record[idx].science)/3;
fwrite(&record[idx],sizeof(struct studentT),1,fout);
fprintf(fout, "%d\n",tempave);
}
//fprintf(fout, "%s\n %s\n %s\n %s %s\n",str3,str4,str5,str2,str6);
fprintf(fout,"%s",str2);
float mathave,litave,sciave;
for(int idx=0;idx<3;idx++){
mathave+=record[idx].math;
litave+=record[idx].literature;
sciave+=record[idx].science;
}
mathave=mathave/3;
sciave=sciave/3;
litave=litave/3;
fprintf(fout,"%f %f %f",litave, mathave, sciave);
fclose(fptr);
fclose(fout);
}
I have wrote a new version of what you need with comments. Hopefully, you can understand what is happening and fix your code or you can use this as well. You may need to change the name of the inputfile and outputfile to work with your input file.
#include <stdio.h>
#include <stdlib.h>
struct student {
char *name;
int literature;
int math;
int science;
};
typedef struct student Student;
int main(void) {
FILE* inputFile;
FILE* outputFile;
int first_read; //check to see if the number of students value was read
int readNumStudents; //count of how many students are there
int i; //tracking students struct array
Student* students; //array of student structs
readNumStudents = 0;
first_read = 0;
i = 0;
inputFile = fopen("input.txt", "r"); //might have to change to whatever your file name is
outputFile = fopen("output.txt", "w"); //might have to change to whatever you want the output file name to be
//checking for null file pointers
if(inputFile == NULL){
printf("Failed to open input file.\n");
exit(1);
}
if(outputFile == NULL){
printf("Failed to open output file.\n");
exit(1);
}
//read file until end of file is reached
while(!feof(inputFile)){
if (first_read == 0){// check to see if first line was read. if not read, then write the value to readNumStudents variable
fscanf(inputFile, "%d", &readNumStudents);
first_read = 1; //set the value to 1. this means that the number of students was read.
students = (Student*) malloc(sizeof(Student) * readNumStudents);//allocate Student structs for the number of given students fro input file. (ie. 3 structs)
if(students == NULL){//check for null
printf("Failed to allocate memory for students.\n");
break;
}
//If not null, then for every struct allocate memory for the name string because its char* not char name[50]
for(int j = 0; j < readNumStudents; j++){
students[j].name = (char*) malloc(sizeof(char) * 50);
if(students[j].name == NULL){//check for null
printf("Failed to allocate memory for name.\n");
exit(1);
}
}
} else {//this means that the first line was read. now read the names and scors
//since you know the format of the input file (string int int int) you can use fscanf with "%s %d %d %d" and the adress of the struct values
fscanf(inputFile, "%s %d %d %d", students[i].name, &(students[i].literature), &(students[i].math), &(students[i].science));
i++;//used to point to next student structure
}
}
//Go thorugh every struct and write each value to outputfile
for(int j = 0; j < i; j++){
fprintf(outputFile, "%s %d %d %d\n", students[j].name, (students[j].literature), (students[j].math), (students[j].science));
}
//free all the allocated memory and files
fclose(inputFile);
fclose(outputFile);
//you need to free the char array on top of the studnets struct array. so loop through every student to free it
for(int j = 0; j < i; j++){
free(students[j].name);
}
free(students);
return 0;
}

Storing information from a file into a structure in C - running into segmentation fault

I am writing a program to store information from an input file and print out information as selected by the user. I have not gotten to the use selection part yet but I am running into a segmentation fault right off the bat. I know that this means that I am trying to access places in memory that either don't exist or that I cannot access.
I am unsure of what I am doing wrong. I am trying to store the information from the input file into my structure.
The input file is in this format
3
5 Name Name 10 56789
7 Name Name 7 67894
8 Name Name 10 89375
I have tried to access the structures directly as emp[1].id etc instead of emp[i].id and such. This also did not work.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
// structures
struct emp
{
int id;
char firstname[10];
char lastname[10];
int department;
float salary;
} emp[10];
// function prototypes
// nothing here yet
int main(int argc, char *argv[])
{
int i = 0;
int choice;
if(argc != 2){
printf("Usage: %s input.txt\n", argv[0]);
exit(EXIT_FAILURE);
}
FILE* inputFile;
inputFile = fopen("input.txt", "r");
if(inputFile == NULL){
printf("Error opening %s\n", argv[1]);
exit(EXIT_FAILURE);
}
// file is open now
// loop to save information from file into structure
int num;
fscanf(inputFile, "%d", &num);
for(i = 0; i < num; i++){
fscanf(inputFile, "%d", emp[i].id);
fscanf(inputFile, "%s", emp[i].firstname);
fscanf(inputFile, "%s", emp[i].lastname);
fscanf(inputFile, "%d", emp[i].department);
fscanf(inputFile, "%f", emp[i].salary);
}
printf("\n");
printf("Welcome to the Employee Database!\n");
printf("---------------------------------\n");
printf("Choose an option:\n");
printf("1: Print empid\n");
printf("2: Print ALL employees\n");
printf("3: Show ALL employees in department\n");
printf("-1: QUIT\n");
scanf("%d", &choice);
// I have not set up the functions to perform the selection options yet
return 0;
}
This is the output that I am receiving.
c803#cs2:~A5$ gcc A5.c
c803#cs2:~A5$ ./a.out input.txt
Segmentation fault
Here fscanf takes memory address of the variables to store the read data into, just like scanf().
You need to put '&' in front of emp[i].id and all other data memebers except character arrays as array name itself gives address of first array members of the array.
So the code should be::
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
// structures
struct emp
{
int id;
char firstname[10];
char lastname[10];
int department;
float salary;
} emp[10];
// function prototypes
// nothing here yet
int main(int argc, char *argv[])
{
int i = 0;
int choice;
if(argc != 2){
printf("Usage: %s input.txt\n", argv[0]);
exit(EXIT_FAILURE);
}
FILE* inputFile;
inputFile = fopen("input.txt", "r");
if(inputFile == NULL){
printf("Error opening %s\n", argv[1]);
exit(EXIT_FAILURE);
}
// file is open now
// loop to save information from file into structure
int num;
fscanf(inputFile, "%d", &num);
for(i = 0; i < num; i++){
fscanf(inputFile, "%d", &emp[i].id);
fscanf(inputFile, "%s", emp[i].firstname);
fscanf(inputFile, "%s", emp[i].lastname);
fscanf(inputFile, "%d", &emp[i].department);
fscanf(inputFile, "%f", &emp[i].salary);
}
printf("\n");
printf("Welcome to the Employee Database!\n");
printf("---------------------------------\n");
printf("Choose an option:\n");
printf("1: Print empid\n");
printf("2: Print ALL employees\n");
printf("3: Show ALL employees in department\n");
printf("-1: QUIT\n");
scanf("%d", &choice);
// I have not set up the functions to perform the selection options yet
return 0;
}

Reading from two .txt file using fscanf in C, storing in structs and outputitng in .txt file

Description: program read data from 2 files, store them in structs,ask user for (city or place of residence), if city name matches with that stored in file, program displays output(student, national_ID,name) and store in a file.
My question is that, the above code that i wrote does not work. it gives me a "no information" even when i enter a city which is on the file.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX_LEN 20
#define MAX_LINE 7
typedef struct studentdata
{
char NATIONAL_ID[20];
char NAME[20];
char STUDENT_CODE[20];
char CITY[20];
}studentdata;
int main(void)
{
int i;
char x=0, CITY[MAX_LEN];
studentdata y[MAX_LINE];
char temp[20];
char temp1[20];
char count=0;
FILE *fi = fopen("employee1.txt", "r");
if (fi == NULL)
{
printf("error data");
exit(0);
}
FILE *fp = fopen("student1.txt", "r");
if (fp == NULL)
{
printf("error data1");
exit(1);
}
i = 0;
printf("Enter city\n");
scanf("%s",CITY);
//i = 0;
FILE *fa = fopen("student2.txt", "w");
if (fa == NULL)
{
printf("error data2");
exit(2);
}
while(fscanf(fi, "%s %s %s", y[i].NATIONAL_ID, y[i].NAME, y[i].STUDENT_CODE) == 4)
i++;
count=i;
I am sure the error is within this loop but can't just find it.
while(fscanf(fp, "%s %s", temp,temp1) == 2)
{
for(i=0; i< count;i++)
{
if (strcmp(y[i].NATIONAL_ID,temp)==0)
{
strcpy(y[i].CITY,temp1);
if (strcmp(y[i].CITY,CITY)==0)
{
fprintf( "%s\t %s\t %s\t %s\t\n", y[i].NATIONAL_ID, y[i].NAME, y[i].STUDENT_CODE, y[i].CITY);
x++;
}
}
}
}
fclose(fa);
if(!x)
{
printf("no information\n");
}
fclose(fi);
fclose(fp);
return 0;
}
I would say that nothing is being read from file into the in first while loop -
while(fscanf(fi, "%s %s %s", y[i].NATIONAL_ID, y[i].NAME, y[i].STUDENT_CODE) == 4)
i++;
As you match for 3 arguments but checks fscanf's return against 4 which will be false and loop will not iterate and i remains 0 , so as count.
Therefore , your this inner loop won't run-
for(i=0; i< count;i++) //count=0
and thus you don't get your output .
Modify your loop to -
while (fscanf(fi, "%s %s %s", y[i].NATIONAL_ID, y[i].NAME, y[i].STUDENT_CODE) ==3)
/* see fscanf's return is checked against 3 */
i++;
Note that an easy way to spot this problem would be to print the information as it is read, or print the array after the read is complete.

Resources