Sorry it was not very clear......with the delete function below which is meant to be delete a record it deletes every record in the file.

void delete_site(struct location site[MAX], int i)
{

	printf("\nYou have reached the delete_site funtion\n\n");

	char name[20];
	int j;
	
	FILE*file;
 
	printf("Please enter the name of the record you would like to delete:\n");
	scanf("%s", name);	

	for(j=0;j<MAX;j++)
	{
		if((strcmp(name, site[j].name)==0)) 
		{
			printf("You have deleted the record for %s", site[j].name);
			site[j].name[0] = '\0';
		}
	
	}
	if(j>=MAX)
	{
		printf("\nThis site does not exist\n");
	}
	                                      
        file = fopen ("sites.txt", "w");
                 
        for(j=0;j<=MAX;j++)
        	fprintf (file,"%s\n",site[j].name);                                    
                                              
        fclose(file);

}

Your function looks very close *EXCEPT*, you are only writing out ONE record, instead of all the records (yes, even the deleted record gets written out, now that's it's marked).

Give that a shot! ;)

Ok but it still does not seem to be working. It deletes the site but the data that is left gets corrupted:

void delete_site(struct location site[MAX], int i)
{

	printf("\nYou have reached the delete_site funtion\n\n");

	char name[20];
	int j;
	
	FILE*file;
 
	printf("Please enter the name of the record you would like to delete:\n");
	scanf("%s", name);	

	for(j=0;j<MAX;j++)
	{
		if((strcmp(name, site[j].name)==0)) 
		{
			printf("You have deleted the record for %s", site[j].name);
			site[j].name[0] = '\0';
		}
	
	}
	if(j>=MAX)
	{
		printf("\nThis site does not exist\n");
	}
	                                      
        file = fopen ("sites.txt", "w");
                 
                     
        for(j=0;j<=MAX;j++)
        	fprintf (file,"%s %s %f %f\n",site[j].name,site[j].place,site[j].east,site[j]. north);

	getchar();
}

Also I now have problems with my previous function add_site() and this function just mentioned delete_site() as I have found my task is to have written these functions as:

int add_site(struct location newsite)

,and

int delete site(index)

where the users input must come from out side the function...I can only do the add_site function using an integer for the counter like this:

int add_site(struct location newsite[MAX], int j)

also another function

int read sites(FILE *fptr)

which must read all the records into the site array (by calling add_site). If the file contains too many records the function return value should be -1, otherwise it should be set to zero.

I guess this is basically a data check?

These additions seem to make everything more confusing for me. Now that add_site() has been changed I don't know how to read the sites in to the array.
Do you understand what I have written? If you do is there any chance you could explain it clearer?

OK, first thing, the corruption. For now, I advise writing out the array as text, which you ARE doing, but are you opening the file or writing to the file, using the binary mode, in some functions? I believe so, so check it. Make it all text mode, for now.

Also, (still on data corruption), you are writing out the data as:
string<space>string<space>float<space>float

Note that there is no newline on the end of the float, so ALL the data could be written out to just ONE line of text, which I'm sure you don't want. So add a newline to the fprintf() line of code, (inside the "%s ...\n" <=like so at the end).

Don't forget that you have this newline char, when you're reading the data file - add that %c right at the end of the input format string "%s %s %f %f%c" fscanf() line of code

Now for the strings themselves - you know every string in C needs an end of string char, or it's just a jumble of letters. So as you are adding data, reading data, and writing data, be consistent, and handle it as a string. Of course. ;)

I'll bet money the original file data, did not have an end of string char in place, however. The way to fix it is to put your data in, from inside your database program. It will automatically add the end of string char, for you, since you're handling it as a string.

For the location, just use a char array (say loc[100]), and pass it to the functions that need it, by referring to it's name:
myfunction(loc);

The receiving function gets:

void myfunction(char loc[100]) {  //plus whatever other parameters it needs

}

Whatever the user puts into loc[], you'll strcat (string concatenate), the file name, onto it:

User location is "C:/mydirectory". You'll strcat(loc, "/filename.txt");, and it becomes loc = "C:/mydirectory/filename.txt". You need to check if the user adds the last '/' char for this, or not. If not, you need to add it with your filename.txt, otherwise, don't. You don't want two // in there.

Here's a tricky part though - once you send an array (any array) to a function, the array "decays" into just a reference pointer. Which is great actually, but the programmer has to send whatever size info is needed, along with the array pointer (the name of the array), because the receiving function can't access the size of the array, otherwise). (There are tricks, but let's not stray into the weeds).

Work with that, and post the whole program, and I'll run it, and see what's up, OK?

Ok so I already had a '\n' at the end of the fprintf() so I added an another one and the specified site got deleted. How ever it did not delete it from the file, only the array. I could see this view my view_sites() function. Also I am not sure what fscanf() you are talking about.

Input file:

Ikea Nottingham 0.1 0.2
Tesco Lincoln 0.3 0.4

#include <stdio.h>
#include <string.h>
#define MAX 20
 
struct location
{
	char name[20],place[20];
    float east,north;
     
};struct location site[MAX];
FILE*file;

//Functions//
int menu();
void view_sites(void);
void add_site(struct location site[MAX], int i);
void delete_site(struct location site[MAX], int i);
void find_site(struct location site[MAX], int i);
double separation(struct location site[MAX], int i);
//void view_sites_in_array(struct location site[MAX], int i);
 
//Main Funtion//
int main()
{	
    menu();
   	return 0;
}
 
//Menu Function//
int menu()
{
	struct location site[MAX];
	
    int i=0; //nsites, i is easier to use
	int stored;
    char choice,q;
                 
    file = fopen("sites.txt" ,"r");
 
    //Clean site array
    for(i=0;i<MAX;i++)
    	site[i].name[0] = 0;   
        i=0;
    
	printf("\nCurrent Sites in Inventory:\n\n");
           
    while ( 1 /*!feof(file)*/ )
    {
        stored = fscanf(file,"%s %s %f %f",site[i].name,site[i].place,&site[i].east,&site[i].north);
                              
        if(stored < 4)
        {
        	break;
        }
        else
        {
        	printf("%s %s %f %f\n",site[i].name,site[i].place,site[i].east,site[i]. north);
            i++;
        }
	
    }	
	printf("\nThere are currently %d sites in the inventory\n", i);
    fclose(file);
 	
	do 
    {
 		printf("\nMenu\n\n");
 
        printf("[A]dd a site        [D]elete a site\n");
        printf("[F]ind a record     [S]eparation between sites\n");
        printf("[V]iew all records\n\n");
 
        printf("Your choice [or Q to quit]:\n\n");
 
        scanf(" %c", &choice);
        getchar();
 
        if (choice == 'v') view_sites();                  
        else if(choice == 'a') add_site(site,i);
		else if(choice == 'd') delete_site(site,i);
		else if(choice == 'f') find_site(site,i);
		else if(choice == 's') separation(site,i);
		//else if(choice == 'c') view_sites_in_array(site,i);
        else if(choice == 'q')
        {
    		printf("Would you like to save changes to the locations file?:\n");         
            return;
        }
        //else if(choice == "D") delete_record();
        //else if(choice == "S") search_for_record();
        else
        {
        	printf("Please only select from the above menu");
        	menu();
        }       
	}
    while(choice!='q');  
 
}
 
void view_sites()
{
    struct location site[MAX];
       
    int i=0,stored;
    file = fopen("sites.txt" ,"r");
    printf("\n\nAll Sites:\n\n");
    while ( 1 /*!feof(file)*/ )
    {
        stored = fscanf(file,"%s %s %f %f",site[i].name,site[i].place,&site[i].east,&site[i].north);
                              
        if(stored < 4)
        {
        	break;
        }
        else
        {
        	printf("%s %s %f %f\n",site[i].name,site[i].place,site[i].east,site[i]. north);
            i++;
        }
    }
	printf("\nThere are currently %d sites in the inventory\n", i);
    fclose(file);
}
 
//Add Site Function//
void add_site(struct location site[MAX], int i)
{
//int j;
//printf("\nThere are currently %d sites in the inventory\n", i);
//i = i+1;
//printf("\n%d\n",i);
//scanf("%s %s %f %f", site[i].name,site[i].place,&site[i].east,&site[i].north);
  
int j;      
           
//Search for next empty record   
      for (j=0;j<MAX;j++)
      	if(site[j].name[0] == 0){   break; //j = next empty record
                
       
                 
      	printf("Please enter the name  ");
        scanf("%s", site[j].name);
                 
        printf("Please enter the place  ");
        scanf("%s", site[j].place);
                                              
        printf("Please enter the east  ");
      	scanf("%f", &site[j].east);
                                              
        printf("Please enter the north  ");
        scanf("%f", &site[j].north);
		}
                      
		 //HERE also ERROR Check if j >= MAX !!!!!
		else if(j>=MAX)
		{
			printf("Site array already full");
		}
                        
        file = fopen ("sites.txt", "w");
           
        for(i=0;i<=j;i++)
        	fprintf (file,"%s %s %f %f\n",site[i].name,site[i].place,site[i].east,site[i]. north);
                                            
        fclose(file);
                                                                    
}

/////////////Delete a site function///////////////
void delete_site(struct location site[MAX], int i)
{

	printf("\nYou have reached the delete_site funtion\n\n");

	char name[20];
	int j;
	
	FILE*file;
 
	printf("Please enter the name of the record you would like to delete:\n");
	scanf("%s", name);	

	for(j=0;j<MAX;j++)
	{
		if((strcmp(name, site[j].name)==0)) 
		{
			printf("You have deleted the record for %s", site[j].name);
			site[j].name[0] = '\0';
		}
	}
	if(j>=MAX)
		{
			printf("\nThis site does not exist\n");
		}
	
	                                      
        file = fopen ("sites.txt", "w");
                 
                     
        for(j=0;j<=MAX;j++)
        	fprintf (file,"%s %s %f %f\n\n",site[j].name,site[j].place,site[j].east,site[j]. north);

		fclose(file);

		getchar();
}

///////////Fina a Site Function/////////////////
void find_site(struct location site[MAX], int i)
{

	char name[20];
   	
	do
	{
		printf("Please enter the nane of the record you want to view :");
		scanf("%s", name);
		if(i<MAX)
		{

			for(i=0;i<MAX;i++)
   			{
     			if((strcmp(name,site[i].name))==0)
     			{
	 				printf("\n");
      				printf("%s\n",site[i].name);
	  				printf("%s\n",site[i].place);
	  				printf("%f\n",site[i].east);
	  				printf("%f\n",site[i].north);
	 			}
		
   			}
		}
		else if(i>=MAX)
		{
			printf("\nThis site does not exist\n");
		}
		else if(name == "q") menu;
	}
	while(name!="q");

	getchar();

}

//////////////Distance between 2 Sites/////////////
double separation(struct location site[MAX], int i)
{

	char name1[20],name2[20];
	float  de, dn, e1, e2, n1, n2; 
	//de/dn = difference east/north, e1 = east 1st site, n1 = east 1st site//

	printf("\nPlease enter the name of site 1: ");
	scanf("%s", name1);

	printf("Please enter the name of site 2: ");
	scanf("%s", name2);

	for(i=0;i<MAX;i++)
   	{
    	if((strcmp(name1,site[i].name))==0)
     	{
      		printf("\nSeparation between %s ",site[i].name);	
			e1 = site[i].east;
			n1 = site[i].north;
		}
		else if((strcmp(name2,site[i].name))==0)
			{
      		printf("and %s:\n",site[i].name);
			e2 = site[i].east;
			n2 = site[i].north;
		}
		else
		{
			printf("\nThis site does not exist\n");
		}
		
	}
	de = e1 - e2;
	dn = n1 - n2;
	return de;
	return dn;	
	
	//printf("\nEast Grid Ref: %f km\n", de);
	//printf("North Grid Ref: %f km\n", de);

	getchar();
}

I am also still confused about the other new functions I was talking about before which I have to do. I should have realised earlier but I didn't read what I was given properly...I will learn..anyway:

int add_site(struct location newsite)
int read sites(FILE *fptr)

add_site() must read data from the file into the array and/or read the users input into the array. Then the array must be written to the file on exit. Every line must be read individually and it should return:

0 No errors
-1 Array full
-2 Site already exists

Every time each line is read the counter 'i' should increment by one. Also decrease by 1 when deleting a site.

Sorry if I am asking so much.

You always want to make sure that the data file is updated before the program closes. That's true enough.

In RL, you want the data file updated regularly, if it has any changes in the array, because of the danger of losing power, someone shutting off the computer, or just a crash of the Operating system, from any cause at all.

I'll look over your program in more detail, this evening.

Oh! Ask away! The more the merrier. ;)

This is your program with the tweaks I would start out with, (but it's awkward fitting it into the function descriptions you received).

I did not tweak the delete and separation functions, ran out of time.

See what you think. It's all really untested.

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <ctype.h>   //for tolower()
#define MAX 20
 
struct location
{
  char name[20],place[20];
  float east,north;
     
}; 

//Functions  -- now in alphabetical order ;)
int add_site(struct location newsite, struct location site[MAX]); //OK?
void delete_site(struct location site[MAX], int i);
int find_site(struct location newsite, struct location site[MAX]); //OK?
int menu(void); //OK?
int read_file(FILE *file); //OK?
double separation(struct location site[MAX], int i);
void view_sites(struct location site[MAX]); //OK?
 
//Main Funtion//
int main()
{	
    if(menu())
    {
      printf("\nThere was a general error in the program\n");
      return 1;
    }
   	return 0;
}
 
//Menu Function//
int menu()
{
	struct location site[MAX], newsite;
  FILE *file;  //add this
  int i, OK, numsites=0; //i is the standard iterator, and tells you nothing
  int stored;   //about the value it holds. Use var names with meaning
  char choice,q;
                 
  /*file = fopen("sites.txt" ,"rt");
  if(file==NULL) 
  {
    printf("Error opening the data file - terminating\n");
    return 1;
  }
  */  
  //Clean site array
  for(i=0;i<MAX;i++)
    site[i].name[0] = '\0'; 
  newsite.name[0]='\0';

  numsites = add_site(newsite, site); //first time, gets data from file 
                              //and returns numsites
  if(numsites==0)
  {
    printf("\nThere are no sites currently in the data file\n");
  }  
  view_sites(site);

  do 
  {
    choice='\0';
    printf("\nMenu\n%d\n",numsites);
 
    printf("[A]dd a site        [D]elete a site\n");
    printf("[F]ind a record     [S]eparation between sites\n");
    printf("[V]iew all records\n\n");
 
    printf("Your choice [or Q to quit]:\n\n");
 
    scanf(" %c", &choice);
    (void) getchar();

    choice=tolower(choice);
    if (choice == 'v') view_sites(site);                  
    else if(choice == 'a') 
    { 
       OK=add_site(newsite, site); 
       if(OK==0) 
         numsites++; 
    }
    
    else if(choice == 'd') delete_site(site,i);
    else if(choice == 'f') find_site(newsite, site);
    else if(choice == 's') separation(site,i);
    else if(choice != 'q')
    {
       	printf("Please only select from the above menu");
       	//don't CALL menu() again, you simply loop back up to it.menu();
    }       
  }while(choice!='q');  
  file=fopen("sites.txt", "wt"); 
  if(file) 
  {
    for(i=0;i<numsites;i++)
      fprintf(file,"%s %s %f %f\n",site[i].name,site[i].place,site[i].east,site[i].north);
  }else 
  {
    printf("File output error - terminating!");
    return 1;
  }
  return 0;
}
//Add Site Function//
int add_site(struct location newsite, struct location site[MAX])  //return 0,1 or 2
{
  static int first1=0;
  int i, j, OK=0;
  FILE *file;
/* 
first, the assignment wants a search to see if the site already exists
so first, get your data from the user, and then call find_site() to see 
if you need to enter the data into the array, or if the record is a duplicate.
Note: test is ONLY for name of store and place, not east and west
*/           
  if(first1==0) 
  {
    i=0;
    first1 = 1;
    file=fopen("sites.txt", "r");
    if(file==NULL) 
    { 
      printf("\nError opening file. Data not loaded. Returning to menu\n");
      return 1;
    }
    while ( 1 /*!feof(file)*/ )
    {
      OK = fscanf(file,"%s %s %f %f",site[i].name,site[i].place,&site[i].east,&site[i].north);
      if(OK < 4)
      {
     	  break;
      }
      i++;
    }
    return i;
  }

  printf("Please enter the name  ");
  scanf("%s", newsite.name);
  printf("Please enter the place  ");
  scanf("%s", newsite.place);
  printf("Please enter the east  ");
  scanf("%f", &newsite.east);
  printf("Please enter the north  ");
  scanf("%f", &newsite.north);
  OK = find_site(newsite, site);
  if(OK==1) //1==found the site, so it's a duplicate
  { 
     printf("That site is already in the database.\n");
     return 2;
  }  

//Search for next empty record   
  for (j=0;j<MAX;j++)
    if(site[j].name[0] == '\0') break; //j = next empty record
                       
  if(j>=MAX)   //HERE also ERROR Check if j >= MAX !!!!!
  {
			printf("Site array already full - that record could not be entered\n");
      return 1;
	}
  else 
  {
    strcpy(site[j].name, newsite.name);
    strcpy(site[j].place, newsite.place);
    site[j].east=newsite.east;
    site[j].north=newsite.north;
    file = fopen ("sites.txt", "w");
    if(file) 
    {       
       for(i=0;i<=j;i++)
         fprintf (file,"%s %s %f %f\n",site[i].name,site[i].place,site[i].east,site[i]. north);
                                            
       fclose(file);
    }                                                                
  }
  return 0;
}

/////////////Delete a site function///////////////
void delete_site(struct location site[MAX], int i)
{
/*
	printf("\nYou have reached the delete_site funtion\n\n");

	char name[20];
	int j;
	
	FILE*file;
 
	printf("Please enter the name of the record you would like to delete:\n");
	scanf("%s", name);	
  (void) getchar();
	for(j=0;j<MAX;j++)
	{
		if((strcmp(name, site[j].name)==0)) 
		{
			printf("You have deleted the record for %s", site[j].name);
			site[j].name[0] = '\0';
      break;
		}
	}
	if(j>=MAX)
	{
		printf("\nThis site does not exist\n");
	}
                     
  file = fopen ("sites.txt", "wt");
  if(file) 
  {                     
    for(j=0;j<i;j++)
     	fprintf (file,"%s %s %f %f\n\n",site[j].name,site[j].place,site[j].east,site[j].north);

		fclose(file);

		getchar();
*/
}

///////////Find a Site Function/////////////////
int find_site(struct location newsite, struct location site[MAX])
{
  int i;
  
  if(newsite.name[0]=='\0') 
  {
    printf("Please enter the name of the site you want to view: ");
    scanf("%s", newsite.name);
    (void) getchar(); //remove the newline from the keyboard buffer
    printf("\nPlease enter the location of the site you want to view: ");
    scanf("%s", newsite.place);
    (void) getchar();
  }
  for(i=0;i<MAX;i++)
  {
    if((strcmp(newsite.name,site[i].name)==0) && (strcmp(newsite.place,site[i].place)==0))
    {
      printf("\n");
      printf("%s\n",site[i].name);
      printf("%s\n",site[i].place);
      printf("%f\n",site[i].east);
      printf("%f\n",site[i].north);
      break;
    }
  }
  if(i>=MAX)
  {
    printf("\nThis site does not exist\n");
    return 0;
  }
  //never call menu(), except from main(). you return only 
  	
  return 1;

}
//Reads the data file, does not store it//
int read_sites(FILE *file) 
{
   int i=0;
   char text[80];

  file=fopen("sites.txt", "rt");
  if(file==NULL) 
  {
    printf("Error opening data file\n");
    return 1;
  }
  printf("\nCurrent Sites in Inventory:\n\n");
  while((fgets(text, 80, file))!= NULL)
  {
    printf("%s", text);
    if(text[0]!='\n') //eliminates counting rows w/o any data
      i++;
  }
  printf("\nThere are currently %d sites in the inventory\n", i);
  fclose(file);
  return i;
}
//////////////Distance between 2 Sites/////////////
double separation(struct location site[MAX], int i)
{

	char name1[20],name2[20];
	float  de, dn, e1, e2, n1, n2; 
	//de/dn = difference east/north, e1 = east 1st site, n1 = east 1st site//

	printf("\nPlease enter the name of site 1: ");
	scanf("%s", name1);

	printf("Please enter the name of site 2: ");
	scanf("%s", name2);

	for(i=0;i<MAX;i++)
   	{
    	if((strcmp(name1,site[i].name))==0)
     	{
      		printf("\nSeparation between %s ",site[i].name);	
			e1 = site[i].east;
			n1 = site[i].north;
		}
		else if((strcmp(name2,site[i].name))==0)
			{
      		printf("and %s:\n",site[i].name);
			e2 = site[i].east;
			n2 = site[i].north;
		}
		else
		{
			printf("\nThis site does not exist\n");
		}
		
	}
	de = e1 - e2;
	dn = n1 - n2;
	return de;
	return dn;	
	
	//printf("\nEast Grid Ref: %f km\n", de);
	//printf("North Grid Ref: %f km\n", de);

	getchar();
}
void view_sites(struct location site[MAX])
{
/*
  I've set up read_sites() function to read the data file, and 
  this function to store it into the array and display them
*/

  int i=0,stored;
  FILE *file;
  file=fopen("sites.txt", "r");
  if(file==NULL) 
  { 
    printf("\nError opening file. Data not loaded. Returning to menu\n");
    return;
  }
  printf("\n\nAll Sites:\n\n");
  while ( 1 /*!feof(file)*/ )
  {
    stored = fscanf(file,"%s %s %f %f",site[i].name,site[i].place,&site[i].east,&site[i].north);
    if(stored < 4)
    {
      	break;
    }
    else
    {
     	printf("%s %s %f %f\n",site[i].name,site[i].place,site[i].east,site[i]. north);
      i++;
    }
  }
	printf("\nThere are currently %d sites in the inventory\n", i);
  fclose(file);
}



/* Input file:

Ikea Nottingham 0.1 0.2
Tesco Lincoln 0.3 0.4

I am also still confused about the other new functions I was talking about 
before which I have to do. I should have realised earlier but I didn't read 
what I was given properly...I will learn..anyway:

   1. int add_site(struct location newsite) *a new struct be passed to these
      functions, from menu().

int add_site(struct location newsite)  *same as #1, above

   1. int read sites(FILE *fptr)  *FILE needs to be declared in menu() and
      then to these functions - see code above.

int read sites(FILE *fptr) *same as #1, above

add_site() must read data from the file into the array and/or read the users input into the array. 

Then the array must be written to the file on exit. Every line must be read individually and it should return:

*OK:
-0 No errors
-1 Array full
-2 Site already exists

Every time each line is read the counter 'i' should increment by one. Also decrease by 1 when deleting a site.
No. i is the standard iterator for loops. Use nsites instead.

Sorry if I am asking so much. 
*/

Ok that is what I thought.

That's great thanks!

Better, yes.

You're welcome.

How goes it with deletion and separation functions?

Sorry I posted my previous post before I saw the code you had posted.... somehow I don't know.

The program compiled with no errors or warnings and ran perfectly :-). The delete_site function deletes only the name of the site, but I thought this '\0' character would cause the whole line not to show. So do I have to strcmp() for the place as well? How do I compare integers? Or is there an easier way to do this?

Sorry I posted my previous post before I saw the code you had posted.... somehow I don't know.

The program compiled with no errors or warnings and ran perfectly :-). The delete_site function deletes only the name of the site, but I thought this '\0' character would cause the whole line not to show. So do I have to strcmp() for the place as well? How do I compare integers? Or is there an easier way to do this?

Running "perfectly" is a good start! ;)

If you are printing out the name and place, as strings, then '\0' in the first char's place, will cause nothing to be printed. Note that '\0' is not the same as '0' or 'O' (zero or oh)

In your view loop, just add this inside your loop:

if(site[i].name)  //in pseudo code
   print the name, the place, the east, and the west

so deleted records will not be viewed - but leave it OUT of any printing to the file, because you WANT those deleted records, to remain in the file. You may write out all zeroes for east and west values if you want to - don't know why you'd need to, but you can. You can also write out a '\0' value into the first char of the place field. Again, don't know why, but you can. Your program just needs a certain placeholder, if the number of records is to be correct as you loop through the array.


You compare integers like you compare any numbers - by subtracting one from the other. Aren't east and west in the program floats, though?

If you get a negative "difference", you obviously need to multiply it by -1, because a distance can't be negative. ABS() will do that for you, if needed, since it returns the absolute value.

Ok I managed to get the program to delete a site from the file but the loop does not work for the the view_sites(). Also it is asking that I pass the variable index to the delete_site function:

int delete_site(index)

Would I just do this by passing the nsites value (number of sites)? and then decreasing it by 1?

Not quite.

Before you can delete a record, you have to find out what the index number for that record is.

So when delete a record is called from the menu, you need to first call find_sites(), and return the index number to menu(), then call delete_site() and do the actual "deletion", there.

The return from find_sites() should be either:
* the index number of the record, if found

or

* zero, indicating that the record was not found

if((OK=find_site(whatever)) > 0) 
 //site was found and OK is the index number

Similar to that.
Of course, you're not actually deleting a record, you've just nullifying it with a simple assignment of one char to the name field. The efficiency is a plus, to the simplicity.

As always, you change a record in the array, and then write out the entire array to the file. You can change a record on the file itself, but that involves more file handling, and usually is hazardous to the data, for beginners to attempt.

Ok I will have a go and post my code. :-) thanks

Ok so this is my code so far:

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <ctype.h>   //for tolower()
#define MAX 20
 
struct location
{
	char name[20],place[20];
	float east,north; 
}; 
 
//Functions//
int add_site(struct location newsite, struct location site[MAX]); 
void delete_site(struct location site[MAX], int i);
int find_site(struct location newsite, struct location site[MAX]); 
int menu(void); 
int read_file(FILE *file); 
double separation(struct location site[MAX], int i);
void view_sites(struct location site[MAX]); 
 
//Main Funtion//
int main()
{	
	if(menu())
    {
      printf("\nThere was a general error in the program\n");
      return 1;
    }
   	return 0;
}
 
//Menu Function//
int menu()
{
	struct location site[MAX], newsite;
 	FILE *file;  //add this
  	int i, OK, nsites=0;
  	int stored;   //about the value it holds. Use var names with meaning
  	char choice,q; 
  
	//Clean site array
  	for(i=0;i<MAX;i++)
    	site[i].name[0] = '\0'; 
  		newsite.name[0]='\0';
 
  	nsites = add_site(newsite, site); //first time, gets data from file and returns nsites

  	if(nsites==0)
  	{
    	printf("\nThere are no sites currently in the data file\n");
  	}  
  	view_sites(site);
 
  	do 
  	{
    	choice='\0';
    	printf("\nMenu\n\nNo. of Sites = %d\n\n",nsites);
 
    	printf("[A]dd a site        [D]elete a site\n");
    	printf("[F]ind a record     [S]eparation between sites\n");
    	printf("[V]iew all records\n\n");
 	
    	printf("Your choice [or Q to quit]:\n\n");
 	
    	scanf(" %c", &choice);
    	(void) getchar();
 
    	choice=tolower(choice);//allows upper and lower case input
    	if (choice == 'v') view_sites(site);                  
    	else if(choice == 'a') 
    	{ 
    		OK=add_site(newsite, site); 
       		if(OK==0)
         		nsites++;//new site added
    	}
    	else if(choice == 'd') 
		{
			delete_site(site,i);	
         		nsites--; 
		}    	
		else if(choice == 'f') find_site(newsite, site);
    	else if(choice == 's') separation(site,i);
    	else if(choice != 'q')
    	{
       		printf("Please only select from the above menu");
       		//don't CALL menu() again, you simply loop back up to it.menu();
    	}       
 	}
	while(choice!='q');  
  	file=fopen("sites.dat", "wt"); 
  	if(file) 
  	{
    	for(i=0;i<nsites;i++)
      		fprintf(file,"%s %s %f %f\n",site[i].name,site[i].place,site[i].east,site[i].north);
  	}
	else 
 	{
    	printf("File output error - terminating!");
    	return 1;
  	}
  	return 0;
}
//Add Site Function//
int add_site(struct location newsite, struct location site[MAX])  //return 0,1 or 2
{
	static int first1=0;
  	int i, j, OK=0;
  	FILE *file;
/* 
first, the assignment wants a search to see if the site already exists
so first, get your data from the user, and then call find_site() to see 
if you need to enter the data into the array, or if the record is a duplicate.
Note: test is ONLY for name of store and place, not east and west
*/           
  	if(first1==0) 
  	{
    	i=0;
    	first1 = 1;
    	file=fopen("sites.dat", "r");
    	if(file==NULL) 
    	{ 
    		printf("\nError opening file. Data not loaded. Returning to menu\n");
      		return 1;
    	}
    	while ( 1 /*!feof(file)*/ )
    	{
      		OK = fscanf(file,"%s %s %f %f",site[i].name,site[i].place,&site[i].east,&site[i].north);
      		if(OK < 4)
      		{
     	  		break;
      		}
      		i++;
    	}
   	 	return i;
  	}
 
  	printf("Please enter the name:  ");
  	scanf("%s", newsite.name);
  	printf("Please enter the place:  ");
  	scanf("%s", newsite.place);
  	printf("Please enter the east:  ");
  	scanf("%f", &newsite.east);
  	printf("Please enter the north:  ");
  	scanf("%f", &newsite.north);
  	//OK = find_site(newsite, site);
  	if(OK==1) //1==found the site, so it's a duplicate
  	{	 
    	printf("Duplicate site name\n");
     	return -2;
  	}  
 
	//Search for next empty record   
  	for (j=0;j<MAX;j++)
    	if(site[j].name[0] == '\0') break; //j = next empty record
 
  		if(j>=MAX)   //HERE also ERROR Check if j >= MAX !!!!!
  		{
			printf("Site array already full - that record could not be entered\n");
      		return -1;
		}
  		else 
  		{
    	strcpy(site[j].name, newsite.name);
    	strcpy(site[j].place, newsite.place);
    	site[j].east=newsite.east;
    	site[j].north=newsite.north;
    	file = fopen ("sites.dat", "w");
    	if(file) 
    	{       
       		for(i=0;i<=j;i++)
         	fprintf (file,"%s %s %f %f\n",site[i].name,site[i].place,site[i].east,site[i]. north);
 
       		fclose(file);
    	}                                                                
  	}
  	return 0;
}
 
/////////////Delete a site function///////////////
void delete_site(struct location site[MAX], int i)
{

	printf("\nYou have reached the delete_site funtion\n\n");
 
	char name[20];
	int j;
 
	FILE*file;
 
	printf("Please enter the name of the record you would like to delete:\n");
	scanf("%s", name);	
  (void) getchar();
	for(j=0;j<MAX;j++)
	{
		if((strcmp(name, site[j].name)==0)) 
		{
			printf("You have deleted the record for %s", site[j].name);
			site[j].name[0] = '\0';
      break;
		}
	}
	if(j>=MAX)
	{
		printf("\nThis site does not exist\n");
	}
                     
  file = fopen ("sites.txt", "wt");
  if(file) 
  {                     
    for(j=0;j<i;j++)
     	fprintf (file,"%s %s %f %f\n\n",site[j].name,site[j].place,site[j].east,site[j].north);
 
		fclose(file);
 
		getchar();

	}
 }
///////////Find a Site Function/////////////////
int find_site(struct location newsite, struct location site[MAX])
{
  	int i;
 
  	if(newsite.name[0]=='\0') 
  	{
    	printf("Please enter the name of the site you want to view: ");
    	scanf("%s", newsite.name);
    	(void) getchar(); //remove the newline from the keyboard buffer
    	printf("\nPlease enter the location of the site you want to view: ");
    	scanf("%s", newsite.place);
    	(void) getchar();
  	}		
  	for(i=0;i<MAX;i++)
  	{
    	if((strcmp(newsite.name,site[i].name)==0) && (strcmp(newsite.place,site[i].place)==0))
    	{
      		printf("\n");
      		printf("%s\n",site[i].name);
      		printf("%s\n",site[i].place);
      		printf("%f\n",site[i].east);
      		printf("%f\n",site[i].north);
      		break;
    	}
  	}
  	if(i>=MAX)
  	{
    	printf("\nThis site does not exist\n");
    	return -1;
  	}
  //never call menu(), except from main(). you return only 
 
  	return 1;
 
}
//Reads the data file, does not store it//
int read_sites(FILE *file) 
{
	int i=0;
   	char text[80];
 
  	file=fopen("sites.dat", "rt");
  	if(file==NULL) 
  	{
    	printf("Error opening data file\n");
    	return 1;
  	}
  	printf("\nCurrent Sites in Inventory:\n\n");
  	while((fgets(text, 80, file))!= NULL)
  	{
    	printf("%s", text);
    	if(text[0]!='\n') //eliminates counting rows w/o any data
      		i++;
  	}
  	printf("\nThere are currently %d sites in the inventory\n", i);
  	fclose(file);
  	return i;
}
//////////////Distance between 2 Sites/////////////
double separation(struct location site[MAX], int i)
{
 
	char name1[20],name2[20];
	float  de, dn, e1, e2, n1, n2; 
	//de/dn = difference east/north, e1 = east 1st site, n1 = east 1st site//
 
	printf("\nPlease enter the name of site 1: ");
	scanf("%s", name1);
 
	printf("Please enter the name of site 2: ");
	scanf("%s", name2);
 
	for(i=0;i<MAX;i++)
   	{
    	if((strcmp(name1,site[i].name))==0)
     	{
      		printf("\nSeparation between %s ",site[i].name);	
			e1 = site[i].east;
			n1 = site[i].north;
		}
		else if((strcmp(name2,site[i].name))==0)
			{
      		printf("and %s:\n",site[i].name);
			e2 = site[i].east;
			n2 = site[i].north;
		}
		else
		{
			printf("\nThis site does not exist\n");
		}
 
	}
	de = e1 - e2;
	dn = n1 - n2;
	return de;
	return dn;	
 
	//printf("\nEast Grid Ref: %f km\n", de);
	//printf("North Grid Ref: %f km\n", de);
 
	getchar();
}
//view_sites function stores sites into the array and displays 
void view_sites(struct location site[MAX])
{
 
	int i=0,stored;
  	FILE *file;
  	file=fopen("sites.dat", "r");
  	if(file==NULL) 
  	{ 
    	printf("\nError opening file. Data not loaded. Returning to menu\n");
    	return;
  	}
  	printf("\n\nAll Sites:\n\n");
  	while ( 1 /*!feof(file)*/ )
  	{
    	stored = fscanf(file,"%s %s %f %f",site[i].name,site[i].place,&site[i].east,&site[i].north);
    	if(stored < 4)
    	{
      		break;
    	}
    	else
    	{
     		printf("%s %s %f %f\n",site[i].name,site[i].place,site[i].east,site[i]. north);
      		i++;
    	}
  	}
	printf("\nThere are currently %d sites in the inventory\n", i);
  	fclose(file);

	if(site[i].name)  
   		printf("%s %s %f %f",site[i].name,site[i].place,site[i].east,site[i]. north);
}

If there's a question about your program, post it up.

Busy (playoffs) weekend! ;)

Playoffs? sorry I am not living in America..is this football?

So if you have an index number of say a site how do you then get this information of the site in the struct so you could say print it or alter it? if that makes sense?

Playoffs? sorry I am not living in America..is this football?

So if you have an index number of say a site how do you then get this information of the site in the struct so you could say print it or alter it? if that makes sense?

Yes, American football. ;) It's the kind of football where you don't fall asleep watching it on the TV. <lol>

You get the index number by a return, from find_site. Say I want to delete a site - not any site, of course. Just one site. So I need the index number of the site I want to delete.

I call find_site() and it looks for the site. If it's found, find_site() returns the index number to the site. Now I call delete_site(), and make the assignment to name that deletes that site (actually, I will re-use that index number, but that's later on, and with new data).

If find_site() can't find the site, then it returns 0. That's how it's normally done.

Yes, American football. ;) It's the kind of football where you don't fall asleep watching it on the TV. <lol>

Haha well I prefer real contact sports...i.e. Rugby <lol>

I seem to be having a problem with the delete site function. It just deletes the last line in the file instead of the specified one. My file is:

Ikea Nottingham 0.100000 0.200000
Sainsburys Birmingham 0.300000 0.700000
Tesco Lincoln 0.500000 0.700000
Topman Birmingham 0.600000 0.800000

and if I want to delete:

Tesco Lincoln 0.500000 0.700000

it deletes the last line instead:

Topman Birmingham 0.600000 0.800000


My code for the function is:

void delete_site(struct location site[MAX], int i)
{

	printf("\nYou have reached the delete_site funtion\n\n");
 
	char name[20];
	int j;
 
	FILE*file;
 
	printf("Please enter the name of the record you would like to delete:\n");
	scanf("%s", name);	
  (void) getchar();
	for(j=0;j<MAX;j++)
	{
		if((strcmp(name, site[j].name)==0)) 
		{
			printf("You have deleted the record for %s", site[j].name);
			site[j].name[0] = '\0';
      break;
		}
	}
	if(j>=MAX)
	{
		printf("\nThis site does not exist\n");
	}
                     
  file = fopen ("sites.dat", "wt");
  if(file) 
  {                     
    for(j=0;j<i;j++)
     	fprintf (file,"%s %s %f %f\n\n",site[j].name,site[j].place,site[j].east,site[j].north);
 
		fclose(file);
 
		getchar();

	}
 }

Could you help asap?

Looks like you have a "one off" error with i. If i was started at 0, then you need
j <= i in the for loop stop condition, instead of j < i.

Remember, you deleted record will have all the data as before, except the Name field will be look like "". The empty string.

You're not using the index number from find_site(). Are you supposed to use it?

What is the variable i holding for a value in delete_site()?

I got rid of the nsites--; and that stopped it deleting the last line for some reason

else if(choice == 'd') 
		{
			delete_site(site,i);	
         		//nsites--;//site deleted, decrement total sites by 1 
		}

Ok it works now although both name and place get deleted but east and north get changed to 0.

void delete_site(struct location site[MAX], int i)
{
 
	printf("\nYou have reached the delete_site funtion\n\n");
 
	char name[20];
	int j=0;
 
	FILE*file;
 
	printf("Please enter the name of the record you would like to delete:\n");
	scanf("%s", name);	
  (void) getchar();
	for(j=0;j<MAX;j++)
	{
		if((strcmp(name, site[j].name)==0)) 
		{
			printf("You have deleted the record for %s", site[j].name);
			site[j].name[0] = '\0';
			site[j].place[0] = '\0';
			site[j].north = '\0';
			site[j].east = '\0';
			
      break;
		}
	}
	if(j>=MAX)
	{
		printf("\nThis site does not exist\n");
	}
 
  //file = fopen ("sites.txt", "wt");
  //if(file) 
  //{                     
    //for(j=0;j<=i;j++)
     	//fprintf (file,"%s %s %f %f",site[j].name,site[j].place,site[j].east,site[j].north);
 
		//fclose(file);
 
		//getchar();
 
	//}
 }

So if my file is:

Ikea Nottingham 0.100000 0.200000
Sainsburys Birmingham 0.300000 0.700000
Tesco Lincoln 0.900000 0.800000
Topman Birmingham 0.600000 0.800000

and I delete a site I get:

Ikea Nottingham 0.100000 0.200000
Sainsburys Birmingham 0.300000 0.700000
0.000000 0.000000
Topman Birmingham 0.600000 0.800000

How do I just get rid off the line?....also how can I decrease nsites by 1 as doing it the way i did before caused errors?

It would be better to change it to this:

site[j].name = "";
site[j].city = "";
site[j].north = 0;  //just plain zero for numbers

etc.

The thing is, you're NOT deleting a record, you're marking it as "deleted", and making it available for a complete overwrite by a new record that you add.

Your output (to the screen), should not show this kind of a deleted record, at all, unless you ask to show deleted records for some reason.

ALL records, including the deleted one's, are always written out to the data file, however.

When I do that I get an error saying:


inventory.c:192: error: incompatible types when assigning to type ‘char[20]’ from type ‘char *’
inventory.c:193: error: incompatible types when assigning to type ‘char[20]’ from type ‘char *’

Sorry, yes. Use site[j].name[0] = '\0';

Zero's are better for the numbers, although '\0' is a zero, in char form.

ok so how do I remove the line as it shows:

0.00000 0.00000

This causes some garbage to be produced if you now try and add a site because of this line.

You don't REMOVE the line. The line should stay put.

The line has a full record, even if it's not visible for every field. (A string field of '\0' may show up as "", or may show up as nothing.

Use your debugger and see what's going on. Make sure you're printing out all the records, even the empty one's, to the file.

You should not be showing empty records on screen, normally, but they should be printed out to a file, for future use.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.