How replace a string of a specific person in a file - c

I'm having a bit of problem. I've set the string 'Absent' to all student in a file. However, I want to replace 'Absent' with 'present' when the correct ID assigned to a student is entered. In other words, 'Absent' will only change to 'Present' for a specific person at a time. I'm not sure how to implement this and I'm asking kindly if someone would help. Thanks in advance.
UPDATE::====
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <time.h>
#include <errno.h>
typedef struct record {
char *fname;
char *lname;
int code;
char *stat;
} information;
int main (void) {
int i;
char ffname[28], flname[28], ans, status[15];
int fID, j, id_, x;
FILE *kfile, *ufile;
x = 0;
j = 0;
i = 0;
char buf[150];
time_t curtime;
struct tm* loc_time;
information array[100];
printf(" **********Attendance Recording System**********\n");
printf(" MENU \n");
//Getting current time of system
curtime = time (NULL);
// Converting current time to local time
loc_time = localtime (&curtime);
strftime (buf,150, "%I:%M %p.\n", loc_time);
//prints error message if file cannot be found within the system
if ((kfile = fopen("information.txt", "r")) == NULL) //If the file path is incorrect, an error message is displayed
{
fprintf(stderr, "Error while opening file (%d: %s)\n",errno, strerror(errno)); //Error message that will be displayed if file path is incorrect
return;
}
//while the file is opened and not at the end, the strings are stored into variables which forms an array of strings
for (x = 0; x < 200; x++) {
if (fscanf(kfile, "%s %s %d", ffname, flname, &fID) != 3) //Reads the contents of the file
break;
array[x].fname = strdup(ffname);
array[x].lname = strdup(flname);
array[x].code = fID;
}
fclose(kfile);
ufile= fopen("update.txt","w");
strcpy(status, "Absent");
fprintf(ufile,"First Name Last Name ID Status Time Arrived\n");
for (i = 0; i < x; i++) {
fprintf(ufile,"%-15s%-14s%2d%12s ",(array[i].fname), (array[i].lname), (array[i].code), status);
fprintf(ufile,"%16s",(buf));
}
fclose(ufile);
while(j < x){
printf("Enter you ID: ");
scanf("%d", &id_);
strcpy(status, "Absent");
bool isPresentInFile = false;
for(i=0; i<x; i++)
{
if(array[x].code == id_)
{
printf(" %s %s?", array[x].fname, array[x].lname);
isPresentInFile = true;
break;
}
}
if(isPresentInFile)
{
strcpy(status, "present");
}
j++;
}
fprintf(ufile,"First Name Last Name ID Status Time Arrived\n");
for (i = 0; i < x; i++) {
fprintf(ufile,"%-15s%-14s%2d%12s ",(array[i].fname), (array[i].lname), (array[i].code), status);
fprintf(ufile,"%16s",(buf));
}
fclose(ufile);
getch();
return 0;
}
UPDATE #3
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <time.h>
#include <errno.h>
typedef struct record {
char *fname;
char *lname;
int code;
} information;
int main (void) {
int i;
char ffname[28], flname[28], ans, ans1, status[15];
int fID, j, id_, x;
FILE *kfile, *ufile;
x = 0;
j = 0;
i = 0;
char buf[150];
time_t curtime;
struct tm* loc_time;
information array[100];
printf(" **********Attendance Recording System**********\n");
printf(" MENU \n");
//Getting current time of system
curtime = time (NULL);
// Converting current time to local time
loc_time = localtime (&curtime);
strftime (buf,150, "%I:%M %p.\n", loc_time);
//prints error message if file cannot be found within the system
if ((kfile = fopen("information.txt", "r")) == NULL) //If the file path is incorrect, an error message is displayed
{
fprintf(stderr, "Error while opening file (%d: %s)\n",errno, strerror(errno)); //Error message that will be displayed if file path is incorrect
return;
}
//while the file is opened and not at the end, the strings are stored into variables which forms an array of strings
for (x = 0; x < 200; x++) {
if (fscanf(kfile, "%s %s %d", ffname, flname, &fID) != 3) //Reads the contents of the file
break;
array[x].fname = strdup(ffname);
array[x].lname = strdup(flname);
array[x].code = fID;
}
fclose(kfile);
while(j < x){
Next:
printf("Enter you ID: ");
scanf("%d", &id_);
strcpy(status, "Absent");
bool isPresentInFile = false;
for(i=0; i<x; i++)
{
if(array[i].code == id_)
{
printf("Are you %s %s?", array[i].fname, array[i].lname);
printf("\n");
printf("[y/n only]: ");
scanf(" %c", &ans);
isPresentInFile = true;
break;
}//end of if statement
}//end of for loop
if(isPresentInFile)
{
strcpy(status, "present");
}//end of if statement
switch (ans){
case 'y':
ufile= fopen("update.txt","w");
fprintf(ufile,"First Name Last Name ID Status Time Arrived\n");
for (i = 0; i < x; i++) {
fprintf(ufile,"%-15s%-14s%2d%12s ",(array[i].fname), (array[i].lname), (array[i].code), status);
fprintf(ufile,"%16s",(buf));
}//end of for loop
fclose(ufile);
printf("Continue?\n");
printf("[y/n]: ");
scanf(" %c", &ans1);
if(ans1 == 'y'){
break;
}//end of if statements
else if (ans1 == 'n'){
exit(EXIT_SUCCESS);
}//end of else statement to check if ans1 is equal to 'n'
case 'n':
goto Next;
break;
default:
printf("invalid entry. Try again");
}//end of switch case statememt
j++;
}//end of while
getch();
return 0;
}

From your question, I didn't get when exactly do you want to change status from "Absent" to "present".
But you can use the same strcpy() method to overwrite your status variable.
...
strcpy(status, "Absent");
if(//condition)
{
strcpy(status, "present");
}
UPDATE 1:
After reading your comment, I understood that you will prompt the user to enter an ID. And if it matches with the ID present in the file, you need to update the status to "present" and then write to the new file.
I can think of something like this:
...
// read from file
.....
int ID;
printf("Enter you ID: ");
scanf("%d", &ID);
strcpy(status, "Absent");
bool isPresentInFile = false;
for(int i=0; i<x; ++i)
{
if(array[x].code == ID)
{
isPresentInFile = true;
break;
}
}
if(isPresentInFile)
{
strcpy(status, "present");
}
...
// write to file
.....
UPDATE 2:
After reading the updated question, I notice that you are writing to the file at the end! But overwriting the status variable each time. This way you end up writing either "Absent" or "Present" for all the entries in the file (Note that it pertains to the last candidate who enters his ID!)
To avoid this, do either of the following:
Write to the file as soon as you know the status of a candidate.
while(j < x)
{
printf("Enter you ID: ");
scanf("%d", &id_);
strcpy(status, "Absent");
bool isPresentInFile = false;
for(i=0; i<x; i++)
{
if(array[x].code == id_)
{
printf(" %s %s?", array[x].fname, array[x].lname);
isPresentInFile = true;
break;
}
}
if(isPresentInFile)
{
strcpy(status, "present");
}
// write to file here
j++;
}
Also have a field called status in the structure information.
By default, keep it "Absent" for all the candidates.
Then make it "Present" only for those who enter their IDs. Finally, write it to the file.

Related

How to give access to text file using if statement?

I am trying to give an if statement to check if a particular name is present in text file, then give access to it otherwise give error message.
#include <stdio.h>
#include <stdlib.h>
int main(){
printf("For person details, please enter the person name: \n");
FILE * fr = fopen("/home/bilal/Documents/file.txt","r");
int catch, i=0, index=0;
char ch[100];
printf("Enter your Name: ");
if (scanf("%s", )){ // Don't know what to put here?
perror("Error while reading!");
return 0;
}
catch = fgetc(fr);
while(catch != EOF){
ch[index] = catch;
if (ch[index] == ' '){
ch[index] = '\0';
printf("Here is your result: %s\n",ch);
index = 0;
i++;
}
else
index++;
catch = fgetc(fr);
}
fclose(fr);
return 0;
}
Simply the program firstly opens a file and asks for a user input and verifies if the provided content is case-sensitively matched with the file. If so, then it'll let the program access the entire file and display on the screen, to do that, we must use another FILE b/c the old *fp is already manipulated and in case it's reused, it may display wrong data.
#include <stdio.h>
#include <string.h>
int main(void) {
FILE *fp = fopen("file.txt", "r"); // for verification
FILE *fp1 = fopen("file.txt", "r"); // for future use
char ch[50], str[50];
short int FLAG = 0;
printf("Enter the string: ");
scanf("%s", &str); // asks for input
while (fscanf(fp, "%s", ch) != EOF) {
if (!strcmp(ch, str)) { // checks if a string matches provided by the user
printf("Found! Here's your details...\n\n");
FLAG = 1;
}
}
if (!FLAG == 1) { // no? exits.
printf("Not found, access denied!\n");
return -1;
}
fclose(fp);
int c = fgetc(fp1); // yes? let's go...
while (c != EOF) {
printf("%c", c); // displays containing data
c = fgetc(fp1);
}
fclose(fp1);
return 0;
}
You'll want to add a variable for your scanf output:
char name[100];
if (scanf("%s", name) != -1)
// ...
Then to compare both you'll use strcmp.
#include <string.h>
//...
if (strcmp(ch, name) == 0)
// both are equal
Note that you can access documentation for scanf and strcmp by typing man scanf or man strcmp in your terminal.
int main()
{
printf("For person details, please enter the person name and id card
number: \n");
printf("Enter your Name: ");
char personName[100];
scanf("%s", personName);
printf("Enter your card number: ");
int cardNumber;
if (scanf("%d", &cardNumber)){
printf("no error detected");
}
else{
printf("error while reading");
}
return 0;
}
The fixed code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
printf("For person details, please enter the person name: \n");
FILE* fr = fopen("/home/bilal/Documents/file.txt", "r");
int catch, i = 0, index = 0;
char ch[100] = { 0 };
if (fr == NULL)
{
perror("Invalid file opening!");
return 1;
}
printf("Enter your Name: ");
fgets(ch, 100, fr);
size_t len = strcspn(ch, "\n");
ch[(len < 100) ? (len) : (99)] = 0; // For file safety checking
if (strlen(ch)) { // Don't know what to put here?
perror("Error while reading!");
return 1;
}
catch = fgetc(fr);
while (catch != EOF) {
ch[index] = catch;
if (ch[index] == ' ') {
ch[index] = '\0';
printf("Here is your result: %s\n", ch);
index = 0;
memset(ch, 0, 100);
i++;
}
else
{
index++;
}
catch = fgetc(fr);
}
fclose(fr);
return 0;
}

Printing out more values from char array then it's suppose to do?

I'm currently working on a program that is suppose to read information from a text-file. The text-file contains a song list and I have created a struct that should be able to hold each song in a song list in my program.
I have divided the program in different files and they look something like this.
main.c
#include "FuncDek.h"
#include <locale.h>
#include <crtdbg.h>
int main()
{
//For swedish and check memory leak
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
setlocale(LC_ALL, "swedish");
//Create with starting size of 5
Song *ptr = (Song *)malloc(sizeof(Song) * 4);
int menuChoice = 0;
int nrOfSongs = 0;
//Read from file
readFromFile(ptr, &nrOfSongs);
system("pause");
do
{
system("cls");
menuChoice = menu();
switch (menuChoice)
{
case 1:
addSong(ptr, &nrOfSongs);
break;
case 2:
showList(ptr, nrOfSongs);
break;
case 0:
break;
default:
printf("\nFelaktigt val, försök igen\n");
system("pause");
break;
}
} while (menuChoice != 0);
free(ptr);
system("pause");
return 0;
}
FuncDek.h
#ifndef FUNCDEK
#define FUNCDEK
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
char title[25];
char artist[25];
char year[4];
} Song;
int menu();
void addSong(Song *ptr, int *nrOfSongs);
void showList(Song *ptr, int nrOfSongs);
void readFromFile(Song *ptr, int *nrOfSongs);
#endif
and finally the FuncDek.c
#include "FuncDek.h"
#pragma warning(disable: 4996)
//Print all from list
void showList(Song *ptr, int nrOfSongs)
{
system("cls");
printf("Låtlista\n");
printf("-------------------------------\n");
for (int i = 0; i < nrOfSongs; i++)
{
printf("Title: %s", ptr[i].title);
printf("Artist: %s", ptr[i].artist);
printf("År: %s \n\n", ptr[i].year);
}
system("pause");
}
//Read from file
void readFromFile(Song *ptr, int *nrOfSongs)
{
FILE *fileOpen;
fileOpen = fopen("song.txt", "r+");
if (fileOpen == NULL)
{
printf("Something went wrong. Could't open file\n");
}
char line[100];
int counter = 0;
int nrOfSongsInList = 0;
/*Read all information to line*/
while (fgets(line, sizeof(line), fileOpen) != NULL)
{
if (counter == 0)
{
nrOfSongsInList = line[0] - '0';
counter++;
}
else if (counter % 2 == 1 && counter == 1)
{
strcpy(ptr[*nrOfSongs].title, line);
counter++;
}
else if (counter % 2 == 0)
{
strcpy(ptr[*nrOfSongs].artist, line);
counter++;
}
else if (counter % 3 == 0)
{
strcpy(ptr[*nrOfSongs].year, line);
counter = 1;
*nrOfSongs += 1;
}
}
fclose(fileOpen);
}
I can now read my text-file and store my songs in my stong struct and I have allocated memory for it.
My problems occure when I'm trying to use the showList function. I can print out the ptr[i].artist and ptr[i].title correct, but for some reason when I print the ptr[i].year it show the year + the title of the next song in the list.
My text-file looks like this and each row is ended with a '\n'.
4
Mr Tambourine Man
Bob Dylan
1965
Dead Ringer for Love
Meat Loaf
1981
Euphoria
Loreen
2012
Love Me Now
John Legend
2016
I can't understand why it prints out more than the year. I noticed that if I make the year array in my struct the same size as the other 2, the problem goes away. But I want to understand.
When I debugg in VS it says that it's stored the right values in the year arr.
Anyone know what I might have missed?

i am getting some unreported values in my program

My program is to ask the user to enter the name and age of the person in his group. The number of person is not known to the user in the beginning of the program. The user keeps on entering the data till the user enters the age zero. The program finally prints the average age.
The source code is below
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
typedef struct group {
char user_Name[21];
int user_age;
}Group;
int main()
{
Group *REC1;
FILE *out_file, *read_file;
int count_age=0, age, sum_age, i;
float avg_age;
char name[21]="", str[21]= "details.txt";
char sample_chr;
//opening a file in writing mode
out_file = fopen(str, "a");
// test for files not existing.
if (out_file == NULL)
{
printf("Error! Could not open file\n");
exit(-1); // must include stdlib.h
}
printf("\nEnter the Details of the person:\n\n");
do
{
printf("Enter the User Name:\n");
fflush(stdin);
scanf("%[^\n]",name);
printf("Enter the Age:\n");
fflush(stdin);
scanf("%d",&age);
if(age == 0)
{
break;
}
else
{
// write to file
fprintf(out_file,"%s,%d\n", name, age);
}
}while(1);
read_file = fopen(str,"r");
//counting the number of lines present in the above file
sample_chr = getc(read_file);
while (sample_chr != EOF)
{
if (sample_chr == '\n')
count_age = count_age +1;
sample_chr = getc(read_file);
}
rewind(read_file);
//allocating space for array of structure dynamically
printf("\n%d\n",count_age);
count_age = count_age - 1;
REC1 = (Group*)malloc(count_age*sizeof(Group));
//storing the values in array of structures
for(i=0; i<=count_age; i++)
fscanf(read_file, "%s,%d", REC1[i].user_Name, &REC1[i].user_age);
fclose(read_file);
fclose(out_file);
for(i =0; i<=count_age; i++)
printf("\n%s %d\n", REC1[i].user_Name, REC1[i].user_age);
for(i=0, sum_age=0; i<=count_age; i++)
sum_age = sum_age + REC1[i].user_age;
avg_age = (float)sum_age/(count_age);
printf("\n\nThe average age is %f\n\n\n", avg_age);
system("pause");
return 0;
}
while i am compiling it doesn't shows any error. When i am running it shows exe file stopped working.
the following is working
there had to be changed the format in scanf() of name[] ( http://www.cplusplus.com/reference/cstdio/scanf/ )
, the fclose(out_file) had to be moved and the ending condition of the while loop had to be changed ...
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
typedef struct group {
char user_Name[21];
int user_age;
}Group;
int main()
{
Group *REC1;
FILE *out_file, *read_file;
int count_age=0, age, sum_age, i;
float avg_age;
char name[21]="", str[21]= "details.txt";
char sample_chr;
//opening a file in writing mode
out_file = fopen(str, "w");
// test for files not existing.
if (out_file == NULL)
{
printf("Error! Could not open file\n");
exit(-1); // must include stdlib.h
}
printf("\nEnter the Details of the person:\n\n");
do
{
printf("Enter the User Name:\n");
scanf("%21s[^\n]",name);
printf("Enter the Age:\n");
scanf("%d",&age);
if(age == 0)
{
break;
}
else
{
// write to file
fprintf(out_file,"%s , %d \n", name, age);
}
}while(age != 0);
fclose(out_file);
read_file = fopen(str,"r");
//counting the number of lines present in the above file
sample_chr = getc(read_file);
while (sample_chr != EOF)
{
if (sample_chr == '\n')
count_age = count_age +1;
sample_chr = getc(read_file);
}
rewind(read_file);
//allocating space for array of structure dynamically
printf("\n Number of group members : %d \n",count_age);
count_age = count_age - 1;
REC1 = (Group*)malloc(count_age*sizeof(Group));
//storing the values in array of structures
for(i=0; i<=count_age; i++)
fscanf(read_file, "%s , %d", REC1[i].user_Name, &REC1[i].user_age);
fclose(read_file);
for(i =0; i<=count_age; i++)
printf("\n Name : %s Age : %d \n", REC1[i].user_Name, REC1[i].user_age);
for(i=0, sum_age=0; i<=count_age; i++)
sum_age = sum_age + REC1[i].user_age;
avg_age = (float)sum_age/(count_age);
printf("\n\nThe average age is %f\n\n\n", avg_age);
return 0;
}

Program doesnt write to file and crashes when loading

So i need to write and read to and from a binary file, but cant seem to do it, and when using readFromFile, the program crashes. I need help write to binary file, and then reading from it and resuming my work later after turning off the program.I have no idea what i am doing wrong, and i have googled for a long time now, but with no results. Here is the code of my program:
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
typedef struct{
char *subjName;
char *lectName;
char *lectSurname;
int credits;
int num_students;
}Subject;
typedef struct{
Subject **subjs;
int num_subjs;
}Subjects;
int numOfSubjs=0;
void listInput();
void listEdit();
void listDelete();
void listPrint();
int userChoice(int select);
int enterNumber(char *name);
void saveToFile(Subjects *subjects);
void readFromFile(Subjects *subjects);
int main() {
Subjects *subjects = malloc(sizeof(Subjects));
subjects->num_subjs = 0;
subjects->subjs = NULL;
readFromFile(subjects);
int r=1;
while(r!=0){
int select=userChoice(select);
switch(select){
case 1:
listPrint(subjects);
break;
case 2:
listInput(&subjects);
break;
case 3:
listDelete(subjects);
break;
case 4:
listEdit(subjects);
break;
case 0:
r=0;
break;
}
}
saveToFile(subjects);
return 0;
}
int userChoice(int select){ // menu options
int choice,input=0;
printf("(1). View all the data\n");
printf("(2). Enter new data\n");
printf("(3). Delete data\n");
printf("(4). Edit data\n");
printf("(0). Exit\n");
printf("-----------------------------\n");
while(input!=1){
choice = enterNumber("menu");
if(choice>4 || choice<0){
printf("Invalid input \n");
}
else
input = 1;
}
return choice;
}
void listPrint(Subjects *subjects){ // print data
int i;
for(i=0; i< numOfSubjs; i++){
printf("%d, %s, %s, %s, %d, %d\n",i+1, subjects->subjs[i]->subjName, subjects->subjs[i]->lectName, subjects->subjs[i]->lectSurname, subjects->subjs[i]->credits, subjects->subjs[i]->num_students);
}
printf("Number of entries: %d \n", numOfSubjs);
}
char *getln() //dynamically allocate input string
{
char *line = NULL, *tmp = NULL;
size_t size = 0, index = 0;
int ch = 1;
while (ch) {
ch = getc(stdin);
if (ch == '\n')
ch = 0;
if (size <= index) {
size += 1;
tmp = realloc(line, size);
if (!tmp) {
free(line);
line = NULL;
break;
}
line = tmp;
}
line[index++] = ch;
}
return line;
}
void saveToFile(Subjects *subjects){
FILE *data;
data = fopen("data.bin","wb");
printf("%s", subjects->subjs[0]);
for(int i=0; i<numOfSubjs; i++){
fwrite(&subjects->subjs[i],sizeof(Subject*),1,data);
}
fclose(data);
}
void readFromFile(Subjects *subjects){
FILE *data;
int i=0;
data = fopen("data.bin","rb");
while(!feof(data))
{
fread(&subjects->subjs[i],sizeof(Subject*),1,data);
i++;
}
fclose(data);
}
int isText(char *str,char *name){ // check if is text
for(int i = 0; i < strlen(str);i++){
if((str[i]<'A' || str[i]>'z') && str[i]!=' '){
printf("Error, %s must be a text \n",name);
return 0;
}
}
return 1;
}
int enterNumber(char *name){ // enter number and check if is number
int input=0, crash=0, num=0;
while(input!=1)
{
crash=0;
printf("Enter the number of %s\n", name);
scanf("%d", &num);
while(getchar()!='\n')
{
crash++;
}
if(crash>0 || num<0)
printf("Error, enter a not negative number of %s\n", name);
else if(crash==0)
input=1;
}
return num;
}
void listInput(Subjects **p_subjects){ // input new data
Subject *new_subj = malloc(sizeof(Subject));
new_subj->subjName = NULL;
new_subj->lectName = NULL;
new_subj->lectSurname = NULL;
new_subj->credits = 0;
new_subj->num_students = 0;
do{
printf("Enter the name of the subject \n");
new_subj->subjName = getln();
}while(!isText(new_subj->subjName,"Subject name"));
do{
printf("Enter the name of the lecturer \n");
new_subj->lectName = getln();
new_subj->lectName[0] &= '_';
}while(!isText(new_subj->lectName,"Lecturer's name"));
do{
printf("Enter the surname of the lecturer\n");
new_subj->lectSurname = getln();
new_subj->lectSurname[0] &= '_'; //Convert to uppercase if lowercase
}while(!isText(new_subj->lectSurname,"Lecturer's name"));
new_subj->credits = enterNumber("credits");
new_subj->num_students = enterNumber("students");
(*p_subjects)->subjs = realloc((*p_subjects)->subjs,sizeof(Subject*)*(++(*p_subjects)->num_subjs));
(*p_subjects)->subjs[(*p_subjects)->num_subjs-1] = new_subj;
numOfSubjs++;
printf("Added a new entry.\n\n");
}
void listDelete(Subjects *subjects){ // delete entries
int del;
if(numOfSubjs==0)
printf("Number of entries is 0, can't delete anything\n");
else{
printf("Enter 0 to exit. Number of subjects : %d \n", numOfSubjs);
while(1){
del = enterNumber("entry which you would like to delete");
if(del<=numOfSubjs && del>0){
for(int i = del-1; i<numOfSubjs-1; i++){
subjects->subjs[i]=subjects->subjs[i+1];
subjects->subjs = realloc(subjects->subjs,sizeof(Subject*)*(--subjects->num_subjs));
}
numOfSubjs--;
break;
}
if(del>numOfSubjs)
printf("Error, input a number between 1 and %d (or enter 0 to exit)\n", numOfSubjs);
else
break;
}
}
}
void listEdit(Subjects *subjects){ // edit entries
int choice=0, editEntry=0, editSubj=0;
if(numOfSubjs == 0)
printf("Number of entries is 0, can't edit anthing\n");
else{
while(1){
printf("Number of entry must be between 1 and %d \n", numOfSubjs);
choice = enterNumber("entry you would like to edit.");
if(choice>0 && choice<=numOfSubjs){
while(1){
editEntry = enterNumber("what would you like to edit\n 1 - Subject name\n 2 - Lecturer's name\n 3 - Lecturer's surname\n 4 - Number of credits\n 5 - Number of students");
if(editEntry>0 && editEntry <=5){
switch(editEntry){
case 1:
do{
printf("Enter the name of the subject \n");
subjects->subjs[choice-1]->subjName = getln();
}while(!isText(subjects->subjs[choice-1]->subjName,"Subject name"));
break;
case 2:
do{
printf("Enter Lecturer's name \n");
subjects->subjs[choice-1]->lectName = getln();
}while(!isText(subjects->subjs[choice-1]->lectName,"Lecturer's name"));
break;
case 3:
do{
printf("Enter Lecturer's surname \n");
subjects->subjs[choice-1]->lectSurname = getln();
}while(!isText(subjects->subjs[choice-1]->lectSurname,"Lecturer's surname"));
break;
case 4:
subjects->subjs[choice-1]->credits = enterNumber("credits");
break;
case 5:
subjects->subjs[choice-1]->num_students = enterNumber("students");
break;
}
}
break;
}
}
break;
}
}
}
&subjects->subjs[i], This is Undefined behavior. Accessing garbage value. You need to properly initialize it proper memory address. You ddin't do it anywhere.
(*subjects).subjs or subjects->subjs -> This is not pointing anywhere. It is NULL.
Also here you don't need the double pointer. A single pointer would do the thing you want to do.
typedef struct{
Subject *subjs;
int num_subjs;
}Subjects;
For single pointer this would be like
Subjects *subjects = malloc(sizeof(Subjects));
subjects->num_subjs = 10;
subjects->subjs = malloc(subjects->num_subjs * sizeof Subject);
subjects->subjs[0].subjName = malloc(40);
Each of the malloc should be checked with it's return Value. If it's NULL then it would be error to proceed further or access it.
And free() it accordingly when you are done working with it.
Some basic things:-
typedef struct{
Subject *subjs;
int num_subjs;
}Subjects;
Now let's look a bit in the code.
Op asked why OP should initialize and isn;t subjects->num_subjs = 0;
subjects->subjs = NULL; not enough?
A pointer is a variable that is supposed to hold address. here Subject* will hold the address of the variables of type Subject.
Now here initially you initialized it.
You have allocated a memory and assigned it's address to the Subject* variable subjects.
Now let's see what else you do.
subjects->num_subjs = 0;
subjects->subjs = NULL;
You initialized it. And then you try to access it(subjects->subjs[i]). Can you tell me where it points to? (subject->subjs)?
Answer is nope. It is pointing to nowhere. It contains NULL value now. Don't you think you should tell it how many subject you want to hold and allocate accordingly? Yes you should and that's what I did precisely in the example shown.
Whenever you have a pointer variable ask yourself what it contains - and if the value is something you know about, not some random garbage value.

Search file and compare strings it contains with inputted variable

I'm trying to search a file containing information on a group of people, for example: their first name, last name and ID.
I'm prompting the user to enter their ID code. The program should search the text file and ensure that their code matches the one within the file so that the program can continue by comparing the string from the file and the variable inputted by the user.
I'm not sure how to implement this. Below is a snippet of the code:
#include <stdio.h>
#include <conio.h>
#include <string.h>
typedef struct record {
char (fname[3])[20];
char (lname[3])[20];
int code[3];
} information;
int main (void) {
char ffname[20], flname[20];
int fID, i;
FILE *kfile;
if ((kfile = fopen("C:\\Users\\Student\\Downloads\\information.txt","r")) == NULL) {
perror("Error while opening file");
} else {
printf("%-20s %-20s %s\n", "First Name", "Last Name", "ID");
fscanf(kfile, "%19s %19s %d", ffname, flname, &fID);
printf("\n");
while (!feof(kfile)) {
printf("%-20s %-20s %04d\n", ffname, flname, fID);
fscanf(kfile, "%19s %19s %d", ffname, flname, &fID);
}
fclose(kfile);
}
information info;
for (i = 0; i < 3; i++) {
printf("Please enter your ID.");
scanf("%04d", &info.code);
}
getch();
return 0;
}
I'm not sure I understand your problem, but you can try this:
typedef struct record {
char *fname;
char *lname;
int code;
} information;
int main (void) {
char ffname[28], flname[28];
int fID, i, id_;
information array[3];
FILE *kfile;
i = 0;
if ((kfile = fopen("C:\\Users\\Student\\Downloads\\information.txt","r")) == NULL) {
perror("Error while opening file");
} else {
while (!feof(kfile)) {
fscanf(kfile, "%s %s %d", ffname, flname, &fID);
array[i].fname = strdup(ffname);
array[i].lname = strdup(flname);
array[i].code = fID;
i++;
}
fclose(kfile);
}
printf("Please enter your ID: ");
scanf("%d", &id_);
for (i = 0; i < 3; i++) {
if (array[i].code == id_) {
// print the record
printf("%s %s \n", array[i].fname, array[i].lname);
}
}
return 0;
}

Resources