Thread: Deleting / Changing a record in a text file

  1. #1
    Registered User
    Join Date
    May 2006
    Posts
    16

    Deleting / Changing a record in a text file

    Alrighty

    I believe this is my last issue with this assignment I will need the forums help with "Yay!"

    I have two more function to write/complete for this program.

    I have to take in 4 peices of data in my add record function, Course Code, Subject Description, mark 1 and mark 2. They have to appeare in the text file as follows

    CourseCODE
    Subject
    Mark1
    Mark2

    I have my add function checking the file before it writes to make sure this not a duplicate course alredy there.

    In my delete and change funcitons I use this procedure to check to make sure the coursecode is the file before I attempt to delete it.

    my understanding of how the delete is to work, is that I create a temp file (no problem there) and copy the contents of my data file except the "deleted" records to the temp file, then delete the old data file and rename the temp one to that of the deleted file.

    I am not sure how to read from file and write to another while simultaniously avoiding the four fields in the record once I find the record to be deleted or modified.

    so say I select to delete COMP086 from the text file that looks like this
    Code:
    COMP059
    Hardware Fun
    89.99
    70.10
    COMP086
    Programming in C
    98.99
    89.99
    COMP098
    Intro to Microprocessors
    67.00
    76.89
    I can Identify the the field exisits but I am not sure where to go from there. here is my code for this function as it sits now

    Code:
    int delSubject()
    {
    	//declare local variables
    	int j = 0;
    	int duplicate = 0;
    	char courseCODE[8];
    	char buff[BUFSIZ];
    	char *p;
    	FILE *fp;
    	FILE *tp;
    
    	// Get course code from user
    	fp = fopen(MarkFile, "r");
    	do
    	{
    		duplicate = 0;	
    		system ("cls");
    		printf("\n\n	Class Mark Subject Management \n\n");
    		printf("		** Delete Subject ** \n\n");
    		printf("		Please enter the 7 digit course code \n");
    		printf("\n	Please press <Enter> to continue ");
    		getchar();
    		fgets(buff, sizeof buff, stdin);
    		sscanf(buff, "%7s", courseCODE);
    
    		// Check course code for alpha chars and convert them to upper case
    		for(j=0; j<=7; j++)
    		{
    			if(isalpha(courseCODE[j]))
    			{
    				courseCODE[j]=toupper(courseCODE[j]);
    			}
    		}
    
    		//compare input course code to those already on record for matching record
    
    		//Loop through the data to check the fields
    		while (fgets(buff, sizeof(buff), fp))
    		{
    			if ((p = strchr(buff, '\n')) != NULL)
    			{
    				*p = '\0';
    			}
    			if (strcmp(courseCODE, buff) != 0)
    			{
    				duplicate = 1;
    				system ("cls");
    				printf("\n\n\n	Matching course code not found please enter a valid code\n\n");
    				printf("	Press any key to continue.\n");
    				getchar();
    				break;
    			}
    		}
    	}while (duplicate != 0);
    	fclose(fp);
    
    	printf("\n\n	Account successfully deleted press any key to continue ");
    	getchar();
    	getchar();
    
    	return 0;
    }
    
    int changeMark()
    {
    	return 0;
    }
    I assume using

    Code:
    system("del marks.txt");
    system("rename temp.txt marks.txt")
    will work once I have copied the appropriate data over to the temp file.

    TIA for any help

    clearrtc

  2. #2
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    You don't have to have two seperate files. You can just read the whole thing into memory, remove what you want (from memory), close the file, open it for writing, and write out all the data you want.

    You can do it without keeping a list of everything to delete, but it involves more reading and writing.

    1 - Pick what you want to delete.
    2 - Open a file for writing.
    3 - While not at the end of the old file:
    ... 3a - Read a record.
    ... 3b - Compare to what you want to delete.
    ...... 3b1 - If not your record, write it to the new file.
    ...... 3b2 - If your record, skip it.

    If you ever find your record, you can at that point just flat dump the entire remainder of the old file onto the new one, because everything else won't be what you're trying to delete.

    That being said, you should probably just read every record you want into memory, remove your stuff you want to delete, then write it all back out.

    If you want to have a list of stuff to delete, then do all of your changes at once, you do everything as above, but subsitute the 'compare' section with something that checks your list of stuff to delete. You will also not be able to do the flat dump of the remainder of the file. You may want to add a 'remove from delete list' feature to that, so whenever you find a match with something you're deleting, you remove it from the list of stuff you're comparing with, so you stop looking for that item once you've deleted it.


    Quzah.
    Hope is the first step on the road to disappointment.

  3. #3
    Registered User
    Join Date
    May 2006
    Posts
    16
    Thanks quzah

    That was kinda what I thinking

    my problem is I know what the first record is I don't want to write and can probably skip it, how ever how do I skip the following 3 records, I wont' know what data is there to compare it to, but I know the following three field (lines) belong to that record.

    Kick me if I missed your point

    clearrtc

  4. #4
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Well a "record" looks to be a total of four lines. The first of which is what you're "keying to", ie: searching for.
    Code:
    void onerecord( FILE *fp )
    {
        char buf[ BUFSIZ ] = { 0 };
        size_t recordsize = 4; /* lines per record */
        size_t x;
    
        for( x = 0; x < recordsize; x++ )
        {
            if( fgets( buf, BUFSIZ, fp ) == NULL )
            {
                /* end of file reached, break from the loop */
                puts( "Error, end of file before end of record." );
                break;
            }
            printf( "record line %d is: %s", x, buf );
        }
    }
    This should show you all four lines of a record, unless of course it reaches the end of the file before it finds the end of a record. In a nut shell, you just read four lines at a time, since each record is four lines. Read the first line, and decide if you need to delete this record. Then read (skip) the next three lines. Or, if you're not deleting them, copy the next three to the new file along with the first one.

    In theory, it's possible for you to fill the buffer with a really long line, and not actually have the full line in the buffer, therefore it wouldn't actually have read a whole line. However, since all of your records are small (line length) you can probably not worry about that. But if you really are concerned, check the buffer for a newline, and if it's not there, make one more call for this record to try and grab the rest of this line. To do this, simply decrement x once.


    Quzah.
    Last edited by quzah; 08-20-2006 at 08:00 PM.
    Hope is the first step on the road to disappointment.

  5. #5
    Registered User
    Join Date
    May 2006
    Posts
    16
    Quzah,

    I have been mulling over your code and I am sure it is what I need, but I can't figure out how it works exactly.

    I am sure it is really simple but I am lost. I may need a little more of a dumbed down explination, i have been writing this program nonstop for 2days now and it is due at 12:00est.

    sorry to be a pain just not getting it.

    thanks

    Carl

  6. #6
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    All it does is read four lines from your file. fgets reads a line of text from a file. All my function does is loop four times, since each of your records is four lines long. There's a FAQ on how to read a line that will explain fgets in more detail.

    Since each record of yours has four lines, you need to read all four lines to read the entire record. Therefore, read the first line, decide what you want to do with it: keep it, or discard it. If you are keeping it, copy it some place (like to your other file), and do the same with the next three lines. If you are discarding it, just read the next three lines to discard them, and don't bother copying them any place.


    Quzah.
    Hope is the first step on the road to disappointment.

  7. #7
    Registered User
    Join Date
    May 2006
    Posts
    16
    Ok ok,


    I think I have it now

    Thanks a million.

    clearrtc

  8. #8
    Registered User
    Join Date
    May 2006
    Posts
    16

    Help one last time please!

    Hello to who ever might be on at this time,

    I have successfully made the delete function work and I am so close to having the change function work.

    when I run the program and edit the file it all appears to work until the very end when it writes the file... well perhaps after that becuase the function preforms the dos commands to copy the file etc.

    here is the error message I am getting

    Code:
    Run-Time Check Failure #2 - Stack around the variable 'recordUPDATE' was corrupted.
    This is my "completed" function

    Code:
    int changeMark()
    {
    	//declare local variables
    	int i = 0;
    	int j = 0;
    	int duplicate = 0;
    	char courseCODE[8];
    	char buff[BUFSIZ];
    	char *p;
    	char recordUPDATE[4][BUFSIZ];
    	FILE *fp;
    	FILE *tp;
    
    	// Get course code from user
    	fp = fopen(MarkFile, "r");
    	do
    	{
    		duplicate = 0;	
    		system ("cls");
    		printf("\n\n	Class Mark Subject Management \n\n");
    		printf("		** Modify Subject ** \n\n");
    		printf("		Please enter the 7 digit course code \n");
    		printf("\n	Please press <Enter> to continue ");
    		getchar();
    		fgets(buff, sizeof buff, stdin);
    		sscanf(buff, "%7s", courseCODE);
    		
    		// Check course code for alpha chars and convert them to upper case
    		for(j=0; j<=7; j++)
    		{
    			if(isalpha(courseCODE[j]))
    			{
    				courseCODE[j]=toupper(courseCODE[j]);
    
    			}
    		}
    		sscanf(courseCODE, "%7s", recordUPDATE[1]);
    
    // Get input for subjectNAME from user
    	system ("cls");
    	printf("\n\n	Class Mark Subject Management \n\n");
    	printf("		** Modify Subject ** \n\n");
    	printf("		Please enter the subject name \n");
    	printf("\n	Please press <Enter> to continue ");
    	fgets( buff, sizeof buff, stdin );
    	sscanf(buff, "%31s", recordUPDATE[2]);
    
    
    	// Get input for the firstMARK from user
    	system ("cls");
    	printf("\n\n	Class Mark Subject Management \n\n");
    	printf("		** Modify Subject ** \n\n");
    	printf("		Please enter the first mark \n");
    	printf("\n	Please press <Enter> to continue ");
    	fgets(buff, sizeof buff, stdin);
    	sscanf(buff, "%5s", recordUPDATE[3]);
    
    	// Get input for the secondMARK from user
    	system ("cls");
    	printf("\n\n	Class Mark Subject Management \n\n");
    	printf("		** Modify Subject ** \n\n");
    	printf("		Please enter the second mark \n");
    	printf("\n	Please press <Enter> to continue ");
    	fgets(buff, sizeof buff, stdin);
    	sscanf(buff, "%5s", recordUPDATE[4]);
    
    		//compare input course code to those already on record for duplicate or for quit condition
    
    		//Loop through the data to check the fields
    		tp = fopen (TempFile, "a");
    		while (fgets(buff, BUFSIZ, fp) != NULL)
    		{
    			i = 0;
    			if ((p = strchr(buff, '\n')) != NULL)
    			{
    				*p = '\0';
    			}
    			//Looking for Data to be deleted
    			if (strcmp(courseCODE, buff) == 0)
    			{
    				//Remove the data to be deleted from the buffer
    				for( i = 0; i < 4; i++ )
    				{	
    					fprintf(tp, "%s\n",recordUPDATE[i]);
    					fgets(buff, BUFSIZ, fp);
    				}	
    			}else{
    				fprintf(tp, "%s\n",buff);
    			}
    		}
    	}while (duplicate != 0);
    	fclose(fp);
    	fclose(tp);
    	fclose(fp);
    	fclose(tp);
    
    	system("del marks.txt");
    	system("rename temp.txt marks.txt");
    
    
    	printf("\n\n	Course successfully modified press any key to continue ");
    	getchar();
    
    	return 0;
    }
    Thanks for any help

    clearrtc

  9. #9
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    > sscanf(buff, "%5s", recordUPDATE[4]);
    C arrays index from 0 upwards, not 1 upwards.
    This is off the end of the array, trashing the stack.


    fclose(fp);
    fclose(tp);
    fclose(fp);
    fclose(tp);
    You only need to close each file once.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  10. #10
    Registered User
    Join Date
    May 2006
    Posts
    16
    OMG

    I can't believe I did that.... ok yes i can its l8 and I have been at this to long.

    The most unfortunate circumsatnce is I subbmitted my assignment literally 30 seconds before I checked here one last time before I went to bed.

    DOH!

    Holly crap it worked....

    Its really done now

    I am resubbmitting it


    Thanks to ALL

    clearrtc

    Carl

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Deleting text from a file???
    By 00Sven in forum C Programming
    Replies: 4
    Last Post: 04-01-2006, 12:26 AM
  2. A bunch of Linker Errors...
    By Junior89 in forum Windows Programming
    Replies: 4
    Last Post: 01-06-2006, 02:59 PM
  3. Replies: 3
    Last Post: 03-04-2005, 02:46 PM
  4. what does this mean to you?
    By pkananen in forum C++ Programming
    Replies: 8
    Last Post: 02-04-2002, 03:58 PM
  5. can someone check this out and let me know ?
    By javaz in forum C Programming
    Replies: 5
    Last Post: 01-21-2002, 02:13 PM