Hey again.
Thanks to those who helped in that other thread. I've got a more theoretical question now. Basically, I have the following struct:
Code:
typedef struct appl_def {
int id;
char *nick;
char *email;
int stage;
int task;
char *comments;
struct appl_def *next;
} applicant;
I want to read a series of information from a file, into that struct, and add/edit applicants from the file at a later time (in the case of editing, means re-writing the complete file, of which I am aware).
Here's the skeleton code, the structure of which, will probably change once I implement the missing functionality:
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define QUIT '5'
#define MAXBUF 1024
typedef struct appl_def {
int id;
char *nick;
char *email;
int stage;
int task;
char *comments;
struct appl_def *next;
} applicant;
void print_menu(void);
void getApplicants(void);
void addApplicant(void);
void editApplicant(void);
void searchApplicants(void);
void listApplicants(void);
void addNode(int id, char *s);
/*
** tptr - Is a pointer to the top node of the linked list.
** cptr - Is a pointer to the current node of the linked list.
*/
applicant *tptr = NULL, *cptr = NULL;
int main(void)
{
char menu;
getApplicants();
do
{
print_menu();
/*
** Found this use of fflush() in a reply from a senior member to another thread.
** Used when no newline character is printed to stdout.
** Thanks to whoever that was. :) --John
*/
fflush(stdout);
menu = getchar();
if ((menu < '1') || (menu > '5'))
continue;
else
{
switch (menu)
{
case '1':
addApplicant();
break;
case '2':
editApplicant();
break;
case '3':
searchApplicants();
break;
case '4':
listApplicants();
break;
}
}
} while (menu != QUIT);
if (tptr != NULL)
listApplicants();
else
puts("There are currently no applicants.");
return 0;
}
void print_menu(void)
{
puts("\n\n-----Menu-----\n");
puts("1. Add applicant.");
puts("2. Edit applicant.");
puts("3. Search applicants.");
puts("4. List applicants.");
puts("5. Quit.");
printf("\nEnter choice 1-5: ");
}
void getApplicants(void)
{
int id;
FILE *fp;
char buf[MAXBUF];
if ((fp = fopen("applicants.txt", "r")) == NULL)
{
fprintf(stderr, "%s", "applicants.txt not found.\n");
exit(EXIT_FAILURE);
}
for (id = 1; ((fgets(buf, MAXBUF, fp)) != NULL); id++)
addNode(id, buf);
fclose(fp);
}
void addApplicant(void)
{
printf("Adding applicant...\n");
}
void editApplicant(void)
{
printf("Editing applicant...\n");
}
void searchApplicants(void)
{
printf("Searching applicants...\n");
}
void listApplicants(void)
{
puts("\n");
for (cptr = tptr; cptr != NULL; cptr = cptr->next)
printf("%d.) %s", cptr->id, cptr->nick);
}
/*
** nptr - Is a new node for the list.
*/
void addNode(int id, char *s)
{
applicant *nptr;
cptr = tptr;
if ((nptr = (applicant *) malloc(sizeof(applicant))) != NULL)
{
nptr->id = id;
nptr->nick = strdup(s);
nptr->next = NULL;
if (tptr == NULL)
tptr = nptr;
else
{
while (cptr->next != NULL)
cptr = cptr->next;
cptr->next = nptr;
}
}
else
{
fprintf(stderr, "%s", "Not enough memory to add applicant to linked list.\n");
exit(EXIT_FAILURE);
}
}
My question is to do with how to structure this file for reading from/writing to it. If I delimited each 'field' with a \t character, then I'd have to use repeated calls to strchr() to replace tabs in any input, which would subsequently be written back to the file, to stop the reading operation from messing up.
Would I use fscanf() for this? In some of the threads I've been reading through (there's 2,447 (probably 2,448 after posting this) threads if you search on 'file' lol), some people seem to be against the use of this function. I must admit, the error-handling implications of fscanf() are what I'd like to avoid, or at least, fix. I guess that's the reason for posting this thread.
Is there a safer method to do what I'm attempting?
Thanks in advance,
John.