-
Data Structure Eror
This is a Simple Personal Information Manager (PIM) program that i made.
But there is some error in it that i just can't fixed !
Can somebody just check and see where is wrong ?
At First, it works normally, it can add task, delete task, edit task and view task.
but after :
- add 2 or 3 task
- delete one of them
- add another one
- edit one of the task
- and presto ! it can no longer delete any task.
this is my code, it kinda long.... but please just see what is wrong.
I think personally the error is in the Editing part (TaskEdit) or the deleting part (Taskdelete). The problem is, the "temp.dat" file i use as a temporary data holder, Won't close. But anyways... this is my code :
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
/* Function Prototype for Task Manager */
void TaskAdd();
void TaskMainTask ();
void Taskprint();
void TaskView();
void TaskDelete ();
void TaskDeleteTitle ();
void TaskEmpty (FILE *delPtr, char check[], char data[]);
void TaskPrintFile();
void TaskEdit ();
void TaskEditTitle ();
void TaskChange (FILE *editPtr, char check[],char data[]);
void TaskPreview ();
void TaskLook ();
/*initiate structure for Task Manager*/
struct taskManager { // strat of struct
char title[30];
char details[130];
char startDate[80];
char endDate[80];
}TaskManager; // end of struct and assign struct as TaskManager
int main()
{
TaskMainTask();
}
/*Start of Main Task*/
void TaskMainTask()
{//Start of maintask
int choice; //set interger choice
int counter; // set interger counter
counter = 1; // set counter to 1
while ( counter != 0) { // start while
system("cls");
/*Main Menu*/
printf ("Task Manager\n\n");
printf ("What Do You Want To Do ?\n");
printf ("[1]. Add Task/Project\n");
printf ("[2]. Edit Task/Project\n");
printf ("[3]. View Task/Project\n");
printf ("[4]. Print the Task/Project To a File\n");
printf ("[5]. Delete the Task/Project\n");
printf ("[6]. Back to Main Menu\n");
printf ("[7]. Exit The Program\n");
scanf ("%d", &choice);
/*if entry not valid*/
if (choice < 1 || choice > 8) { // start if
printf ("Entry Not Valid !!\n");
printf ("Please Enter 1-7");
getchar();
}//end If
/*if Entry was valid*/
else { // start else
switch (choice) { // start switch
case 1:
TaskAdd(); // go to add
break;
case 2 :
TaskEdit (); // go to edit
break;
case 3 :
TaskLook(); // go to look
break;
case 4 :
TaskPrintFile(); // go to print_file
break;
case 5 :
TaskDelete (); // go to delete
break;
case 6 :
main_menu();
break;
case 7 :
exit (1); // exit program
break;
} // end switch
}// End Else
} // End While
} // End MainTask
/*adding Task*/
void TaskAdd ()
{ // start of add
FILE *cfPtr;//information.dat file pointer
int choice2;//variable for storing the user choice
char buffer[10];
//fopen opens the file; exits if file cannot be opened
if ((cfPtr = fopen ("Task.dat","ab")) == NULL ){ // start of if
printf ("Filed Could not be Opened\n");
}// end if
/*adding information */
else { // start of else
system ("cls");
printf ("=======Add New Task/Project========\n");
printf ("\nEnter The Title :\n");
gets (buffer);
gets (TaskManager.title);
printf ("\nNotes and Details of The Task/Project (130 Character) : \n");
gets (TaskManager.details);
printf ("\nStart Date ( mm/dd/yy ) : ");
gets (TaskManager.startDate);
printf ("Due Date (mm/dd/yy) : ");
gets (TaskManager.endDate);
/*write the record in the file*/
fwrite (&TaskManager, sizeof(TaskManager), 1 , cfPtr);
fclose (cfPtr); // closes the file
printf ("\nProject Saved\n");
printf ("Press [Enter] To Continue\n");
getchar();
system ("cls");
TaskPreview (); // showing the outcome
printf ("Do You want to Add a New Task ?\n[1].Yes\n[2].No\n");
scanf ("%d", &choice2);
if ( choice2 == 1 ) { // start of if
TaskAdd ();
} // end of if
else if (choice2 == 2) { // start of else if
TaskMainTask ();
}// end of else if
}// end of else
} // end of else
/*Function Preview; Printing the result for the user*/
void TaskPreview ()
{ // start of preview
printf ("%43s\n\n","=====Task Preview=====");
printf ("%30s%15s%15s\n","Title","Start Date","Due Date");
printf ("%30s%15s%15s\n",TaskManager.title, TaskManager.startDate, TaskManager.endDate);
printf ("\n%10s\n%10s\n\n", "Notes / Details :", TaskManager.details);
printf ("\n");
} // end of preview
/*Function print; printing the result in diffrent format*/
void Taskprint()
{ // start of print
printf("%30s%15s%15s\n", TaskManager.title, TaskManager.startDate, TaskManager.endDate);
printf("\n");
} // end of print
/*Start of function view*/
void TaskView ()
{ //start of view
FILE *viewPtr; // Task.dat file pointer
/*Opening the file*/
if ((viewPtr = fopen ("Task.dat", "r")) == NULL) { // start of if
printf ("File Could not be Openend.\n");
} // end of if
else {// start of else
rewind(viewPtr); // sets pointer to begining of file
system ("cls");
printf("%30s%15s%15s\n", "Title", "Start Date", "End Date");
/*Resd trough file stream */
while ( !feof(viewPtr)) { // start of while
/*set all the structure memory to NULL */
TaskManager.title[0] = '\0';
TaskManager.details[0]= '\0';
TaskManager.startDate[0]= '\0';
TaskManager.endDate[0]= '\0';
/*Read from file*/
fread (&TaskManager, sizeof(TaskManager), 1, viewPtr);
if (TaskManager.title[0] != '\0') { // start of if
Taskprint ();
} // end of if
else { // start of else
break;
} // end of else
} // end of while
fclose(viewPtr);
}// end of else
getchar();
} // end of view
/*function delete; header to delete*/
void TaskDelete ()
{ // start of delete
int choice;
system("cls");
/*Ask The user*/
printf ("what do you want to do ?\n");
printf ("[1]. Delete Task\n");
printf ("[2]. Return To Main Menu\n");
printf ("Please Choose an Option :\n");
scanf ("%d", &choice );
/*if the input is invalid*/
if (choice < 1 || choice > 2 ) { // start of if
printf( "Invalid Input !\n" );
system("pause");
TaskMainTask();
} // end of if
/*if the input is valid*/
else { // start of else
switch (choice) { // start of switch
case 1 : // return to deleteTitle
TaskDeleteTitle();
break;
case 2 : // back to Main Task
TaskMainTask();
break;
} // end of switch
} // end of else
system("pause");
}// end of delete
/*start of deleteTitle function; part of delete*/
void TaskDeleteTitle ()
{ // start of deleteTitle
FILE *cfPtr; // assign file pointer
/*initiate variables*/
int result;
char checkTitle[20];
int choice1;
int choice2;
system("cls");
/*opening Task.dat file*/
if ((cfPtr = fopen ("Task.dat", "rb+")) == NULL ) { // start of if
printf ("File Couldn't be found");
} // end of if
else { // start of else
TaskView (); // View the current file
printf ("Enter the Title you want to delete :\n");
gets (checkTitle);
/*Read Through the file*/
while (fread(&TaskManager, sizeof(TaskManager), 1, cfPtr)
&& strcmp (checkTitle, TaskManager.title));
/*compareing the strings*/
result = strcmp (checkTitle, TaskManager.title);
if (result != 0) { // start of if
printf("Record Not Found !\n\n");
} // end of if
else { // start of else
system("cls");
printf("Record is found !\n\n");
TaskPreview ();
/*aking the user*/
printf ("Do You want to delete this Note ?\n");
printf ("[1]. Yes\n[2]. No\n");
printf ("Choose an Option : ");
scanf ("%d", &choice1);
/*if the input is invalid*/
if (choice1 < 1 || choice1 > 2 ) { // start of if
printf ("Input Invalid !");
getchar ();
TaskMainTask ();
} // end of if
/*if the input is Valid*/
else { // start of else
switch (choice1) { // start of switch
case 1 : // argument #1
TaskEmpty(cfPtr, checkTitle, TaskManager.title);
printf ("Note Deleted !\n");
break; // break case 1
case 2 : // argument # 2
TaskMainTask();
break; // break case #2
} // end of switch
} //end of else
} // end of outer else
fclose (cfPtr);
} // end the most outer else
} // end of delete Title
/*Start of Function empty*/
void TaskEmpty (FILE *delPtr, char check[], char data[])
{ // start of empty
FILE *temp; // file pointer
temp = fopen ("temp.dat", "w"); // set temp to open file temp.dat
rewind(delPtr); // set pointer to begining of file
while (fread(&TaskManager, sizeof(TaskManager), 1, delPtr)) { // start of while
if (strcmp (check, data)) { // start of if
fwrite ( &TaskManager, sizeof (TaskManager), 1, temp); //write to file
} // end of if
} // end of while
fclose (delPtr); // closing file pointer
fclose (temp); // closing temporary pointer
remove ("Task.dat"); // delete task.dat
rename ("temp.dat", "Task.dat"); // rename temp.dat to task.dat
/*set structure to NULL*/
TaskManager.title[0] = '\0';
TaskManager.details[0] = '\0';
TaskManager.startDate[0] = '\0';
TaskManager.endDate[0] = '\0';
} // end of empty
/*Start of function print_file*/
void TaskPrintFile()
{ // start of print_file
FILE *viewPtr; // Set File Pointer
FILE *printPtr; // set File Pointer
system("cls");
/*if the record cannot be found*/
if((viewPtr=fopen("Task.dat","r"))== NULL){ // start of if
printf("File could not be opened.\n");
}//end if
/*if the record cannot be found*/
if((printPtr=fopen("Task2.txt","w"))== NULL){ // start of if
printf("File could not be opened.\n");
}//end if
else{ // start of else
rewind(viewPtr); // set pointer to the start of file
/*set the array to NULL*/
while(!feof(viewPtr)){ // start of while
TaskManager.title[0] = '\0';
TaskManager.details[0] = '\0';
TaskManager.startDate[0]='\0';
TaskManager.endDate[0] = '\0';
/*read from file*/
fread(&TaskManager, sizeof(TaskManager),1,viewPtr);
if(TaskManager.title[0]!='\0'){ // start of if
fprintf (printPtr,"%43s\n\n","=====Task Print=====");
fprintf (printPtr,"%30s%15s%15s\n","Title","Start Date","Due Date");
fprintf (printPtr,"%30s%15s%15s\n",TaskManager.title, TaskManager.startDate, TaskManager.endDate);
fprintf (printPtr,"\n%10s\n%10s\n\n", "Notes / Details :", TaskManager.details);
fprintf (printPtr,"\n");
} // end of if
else { // start of else
break;
} // end of else
}//end while
printf("The informations have been printed on a file\n\n");
fclose(viewPtr);
fclose(printPtr);
}//end else
getchar();
getchar();
} // end of print_file
/*start of edit*/
void TaskEdit()
{ // start of edit
int choice;
system("cls");
/*Asking for user input*/
printf("\n\n\nWhat Do You Want To do ?\n");
printf("[1]. Edit by title\n");
printf("[2]. Return to menu\n");
printf("\nPlease choose an option : ");
scanf("%d", &choice);
/*if the input was invalid*/
if(choice<1 || choice>2){ // start of if
printf("Please only enter 1-2!\n");
system("pause");
}//end inner if
switch (choice){ // start of switch
case 1 : // case #1
TaskEditTitle();
break;
case 2 : // case #2
system ("cls");
TaskMainTask();
break;
}//end switch
}//end edit function
/*start of e_title*/
void TaskEditTitle()
{ // start of e_title
FILE *cfPtr; // assign a FILE pointer
int result;
char check_task[20];
int choice1;
/*if file can't be opened*/
if((cfPtr = fopen("Task.dat","rb+"))==NULL){
printf("File could not be opened.\n");
}//end if
else{ // start of else
system ("cls");
TaskView ();
printf("Enter the title you wish to change : ");
gets(check_task);
/*Read from file*/
while(fread(&TaskManager,sizeof(TaskManager), 1, cfPtr)
&& strcmp(check_task, TaskManager.title));
/*comparing the strings*/
result = strcmp(check_task, TaskManager.title);
if(result!=0)
{// start of if
system("cls");
printf("==SEARCHING==\n");
system("pause");
system("cls");
printf("Record not found!\n\n");
} // end of if
else{ // start of else
system("cls");
printf("==SEARCHING==\n");
system("pause");
system("cls");
printf("Record found!\n\n");
TaskPreview();
/*ask the user for input*/
printf("Do you want to edit this record?\n");
printf("[1]. Yes / [2]. No\n");
printf("Choose an option : ");
scanf("%d", &choice1);
/*if the input is invalid*/
if(choice1<1 || choice1>2){
printf("Please only enter 1-2!\n");
system("pause");
TaskEditTitle();
}//end inner if
/*If the input is valid*/
else { // start of else
switch (choice1){ // start of switch
case 1 : // case #1
TaskChange(cfPtr, check_task,TaskManager.title);
printf("\nRecord edited!\n");
printf("Press [ENTER] to Continue\n");
system("pause");
break; // break from outer case#1
case 2 : // case #2
TaskMainTask();
break;
}//end switch
}//end inner else
}//end else
fclose(cfPtr); // closing the pointer
}//end else
}// end of e_title
/*start of change*/
void TaskChange(FILE *editPtr, char check[],char data[])
{ // start of change
char buffer[10];
rewind(editPtr); // set the pointer to the start of file
/*reading the file*/
while(fread(&TaskManager, sizeof(TaskManager), 1, editPtr) && strcmp(check,data));
/* Changing the content */
if(!strcmp(check,data)){ // start of if
system("cls");
printf("\nEnter Title : ");
gets(buffer);
gets(TaskManager.title);
printf("\nDetails/Notes : \n ");
gets(TaskManager.details);
printf("\nStart Date ( mm/dd/yy ): ");
gets(TaskManager.startDate);
printf("End Date ( mm/dd/yy ): ");
gets(TaskManager.endDate);
fseek(editPtr, ftell(editPtr) - sizeof(TaskManager),0);
fwrite(&TaskManager, sizeof(TaskManager), 1, editPtr);
}//end if
fclose(editPtr); // close the pointer
} // end of change
/*start of look*/
void TaskLook ()
{
FILE *lookPtr; // set a File pointer
/*Assigning variable*/
int result;
char checkTitle[20];
int choice1;
/* opening the file*/
if((lookPtr = fopen("Task.dat","rb+"))==NULL){ // start of if
printf("File could not be opened.\n");
}//end if
else{ // start of else
system ("cls");
TaskView ();
printf("Enter the title you wish to view :\n");
gets (checkTitle);
/*read through the file*/
while (fread(&TaskManager, sizeof(TaskManager), 1, lookPtr)
&& strcmp (checkTitle, TaskManager.title));
/* comparing the strings */
result = strcmp (checkTitle, TaskManager.title);
if (result != 0) { // start of if; if the string not found
printf("Record Not Found !\n\n");
system("pause");
} // end of if
else {// start of else; if the strings are matched
system("cls");
printf("Record is found !\n");
TaskPreview ();
/*asking user input*/
printf ("Do You want to view another task ?\n");
printf ("[1]. Yes\n[2]. No\n");
printf ("Choose an Option : ");
scanf ("%d", &choice1);
/*if the input invalid*/
if (choice1 < 1 || choice1 > 2 ) {// start of if
printf ("Input Invalid !");
getchar ();
TaskMainTask ();
} // end of if
else { // start of else
switch ( choice1 ) { // start of switch
case 1:// case #1
system ("cls");
TaskLook ();
break;
case 2: // case #2
system("cls");
TaskMainTask ();
break;
} // end of switch
} // end of else
} // end of outer else
fclose(lookPtr);
} // end of outest else
}// // end of look
//---------------------- end task ---------------------------------------
-
compile error: undefined reference to main_menu(). You have it only once in your code. Where is the function actually defined?
-
Code:
if ( choice2 == 1 ) { // start of if
TaskAdd ();
} // end of if
else if (choice2 == 2) { // start of else if
TaskMainTask ();
}// end of else if
You are essentially looping by recursion. Whilst you may not discover any problems with that in your current code, it is definitely not the right way to do things.
Code:
switch (choice) { // start of switch
What makes you think that if the reader can not read "switch (choice) {" that they will understand better from "// start of switch"? Comments are meant to make the code understandable, nor trivially rephrase a the stuff on the left of it.
You may find that having "end if ..." comments are sort of helpful, but really, it should be covered by your indentation, and if the code is so long & complex that it's not clear to see, then you PROBABLY should refactor it so that you make some of the code in a large block into a separate function.
Code:
FILE *cfPtr; // assign file pointer
This comment is absolutely incorrect - there is no assignment, - it's just a variable declaration of a file-pointer. FILE * clearly indicates that, so there is REALLY no reason to have a comment for that. If you really want to have a comment for the cfPtr variable, perhaps you should say "task.dat" file pointer, or some such. Of course, changing the name to "taskFile" would make that comment obsolete too.
Code:
gets (TaskManager.endDate);
I know you are not to blame, but gets() is probably the ABSOLUTELY MOST STUPID function in all of the C runtime library - because if someone falls asleep pressing the 'a' key, an then hits enter, your program will crash.
Code:
while(fread(&TaskManager,sizeof(TaskManager), 1, cfPtr)
&& strcmp(check_task, TaskManager.title));
/*comparing the strings*/
result = strcmp(check_task, TaskManager.title);
if(result!=0)
{// start of if
system("cls");
printf("==SEARCHING==\n");
system("pause");
system("cls");
printf("Record not found!\n\n");
} // end of if
So after you have searched the file, you say "SEARCHING", then wait for the user to press a key... Very meaningful... And if you MUST do this, perhaps only duplicating the code that says "Record [not] found", rather than all four lines of code.
Also, you could put (result = strcmp(...) inside the while, avoiding a second strcmp to see if you ACTUALLY found it...
And it seems to me that you could make a function of "find task with a particular title".
Code:
fseek(editPtr, ftell(editPtr) - sizeof(TaskManager),0);
Does that last zero mean SEEK_CUR?
Code:
TaskEmpty(cfPtr, checkTitle, TaskManager.title);
...
void TaskEmpty (FILE *delPtr, char check[], char data[])
{ // start of empty
...
while (fread(&TaskManager, sizeof(TaskManager), 1, delPtr)) { // start of while
if (strcmp (check, data)) { // start of if
fwrite ( &TaskManager, sizeof (TaskManager), 1, temp); //write to file
...
So, you are comparing TaskManager.title with checkTitle, and if they don't match, you write to the file. Seeing as the Taskmanager.title is the one you found from searching for the user entered title, and the checkTitle is the title the user entered, do you believe it will actually differ very often?
--
Mats
-
On other note, I managed to make your program in a deadlock. I believe you have some bugs in the input method.
Try debugging the program. Like see if it enters the delete functions when you try to delete and it doesn't delete.
If it does try to print various variables (or use debugger) and see from there.