Thread: Structuring a file for I/O

  1. #1
    Registered User
    Join Date
    Aug 2002
    Posts
    55

    Smile Structuring a file for I/O

    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.

  2. #2
    Registered User
    Join Date
    Jan 2003
    Posts
    78
    You are getting into trouble due to binding. Break out the list and data structure into two separate structures. Make the list node so it has one pointer which will point to an applicant structure. Make the applicant structure fixed length by changing the pointers to char strings of the max required length. Use fread/fwrite to load and store the structures.

    Rog

  3. #3
    Registered User
    Join Date
    Aug 2002
    Posts
    55
    Hey Rog,

    Thanks ever so much for the reply. I think you've got a good point with the data structure. I think the only place I *should* have a pointer, is for the comments, i.e. char *comments; but other than that, you're right.

    One other thing I realise this morning, is that I don't necessarily need to keep one applicant per line in the file, which is what I was thinking originally. I could spread it over several lines.

    Anyway, thanks for the suggestion, I'll have a bash at it in a little while.

    John.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Unknown Memory Leak in Init() Function
    By CodeHacker in forum Windows Programming
    Replies: 3
    Last Post: 07-09-2004, 09:54 AM
  2. Making a LIB file from a DEF file for a DLL
    By JMPACS in forum C++ Programming
    Replies: 0
    Last Post: 08-02-2003, 08:19 PM
  3. Hmm....help me take a look at this: File Encryptor
    By heljy in forum C Programming
    Replies: 3
    Last Post: 03-23-2002, 10:57 AM
  4. Need a suggestion on a school project..
    By Screwz Luse in forum C Programming
    Replies: 5
    Last Post: 11-27-2001, 02:58 AM