I have to create a database with the data stored in a .txt file. Each record is for a company with the following fields:
Name, Place, East(km), North(km). Each record from the file needs to be read into a struct array. I have managed to read the records into a struct array but I need to create several other functions:
Add_Company() - To add a company to the struct array
Read_Companies() - Read each company record by calling the function Add_Company
List_Distance() - Distance Between two specified companies
Delete_Company() - Deletes a company record

A user menu would be needed calling the specific function when required. When the user quits the file must be updated.

I have posted before about this and did not get any straight answer or I did not really understand, so please could someone help?

Here is my code:

#include <stdio.h>
#define MAX 20

int main(void)
{
struct company
{
float east,north;
char name[20],place[20];
};
struct company site[MAX];

FILE*file;
int i=0;

file = fopen("companies.txt" ,"r");

while ( 1 /*!feof(file)*/ )
{
fscanf(file,"%s %s %f %f",&site.name[0],&site.place[0],&site.east,&site.north);
if(!feof(file))
{
printf("%s %s %f %f\n",site.name,site.place,site.east,site. north);
i++;
}
else
{
break;
}
}
fclose(file);

return 0;
}

My input file is:

Ikea Nottingham 0.1 0.1
Tesco Lincoln 0.2 0.2
Asda Leicester 0.3 0.4

When you don't use code tags, your code looks like the dog's breakfast, and is generally ignored.

Always highlight your code, and click on the [CODE ] icon in the top bar of the forum editor, to make your code easily readable.

First thing I see wrong is the & operator, in front of strings that you're fscanf()'ing. Strings shouldn't have the & in front of them - the name of the string is the address you want, and the right type.

If you know how to bring in data from a file, you should be able to send the data back out to a file, as well. Any problems with that?

To remove a record, first, find the record you want to remove, then zero out: ('\0'), the first char of the name of the company. Then adjust your output (to file and to printing on the screen), so that records that have companies with no name, are not shown or output to a file. (very easy).

Adding a company is just a matter of finding a record with no name if(strlen(record[i].name)== 0)

Record names must not be allowed to contain garbage values in the first char of their name, ever. They either have a valid name, or they have a '\0' (end of string char marker), as their first char.

Edited 3 Years Ago by happygeek: fixed formatting

Ok thank you for the tip. I have just starting using this site.

Thank you for the tips and yes I know how to send data back to a file.

Any other comments from other users would be helpful thanks!

You'll want to define your struct above main() (make the definition global in scope), so other functions can easily make a temp struct, for editing purposes, etc.

Can you narrow down what you're stuck on doing, more precisely?

Basically I have a database stored in a text file with information about several companies. Each record contains 4 fields:

Name, Place, East, North

I want to do basic database functions (which would be listed in a menu):

1. Add a new record (in this case a company)
2. Delete a record
3. Find a specified record

etc.

I have sent you an email with a document attached telling you exactly what I need to do.

Thanks for your patience.

Basically I have a database stored in a text file with information about several companies. Each record contains 4 fields:

Name, Place, East, North

I want to do basic database functions (which would be listed in a menu):

1. Add a new record (in this case a company)
2. Delete a record
3. Find a specified record

etc.

I have sent you an email with a document attached telling you exactly what I need to do.

Thanks for your patience.

All the above is a repeat of what you've already posted.

I read all that - all very standard.

My question is: "What are you stuck on?" Not "What do you have to do?"

Basically, you have main() function. Before the main function, you'll prototype your struct:

struct mystruct {
   char name[30];
   char place[30];
   float or int east
   float or int north
}

;
(size of name and place are up to you) I suggest you put the name and location or place, first and second in the struct, because that's the way the data is, in the file.

At the top part of main(), you'll declare the array of structs, a char called choice, and a few other variables.

You'll have a do{ }while(choice!=q);

and inside that do while loop, you'll print up a cheery little header, then the menu options, and get the user's input into "choice":

[A]dd a record        [D]elete a record
[E]dit a record       [S]earch for a record
[V]iew all records 

Your choice [or Q to quit]:

Whatever their choice, the letter may be switched to lower case with tolower() (so include <string.h>).

Something along those lines. Beneath the menu display, each choice made will call the appropriate Add, Search, or whatever, functions. When the immediate choice is done, the program will return to the menu() function, and again, post up it's little header, and give the user these same choices. The program will return to main() only when the user chooses q to quit.

These kinds of programs are more time consuming when you first do them, than you might expect, so get cracking. Post up what you have, and be specific about what has you stopped.

Please don't send me emails. The forum is here to help everybody, and please ALWAYS use code tags around your code!

Edited 5 Years Ago by Adak: n/a

Ok this is the code that I have now. My problem is with the add_site. How do I write the struct array to the file? What am I doing wrong here? bare with me as my knowledge of programming is very low.

#include <stdio.h>
#include <string.h>
#define MAX 20

struct location
    {
	char name[20],place[20];
        float east,north;
      
    };
    
//Functions//
void menu();
void view_sites();
void add_site();
//void delete_record();
//void search_for_record();

//Main Funtion//
int main(void) 
{

    menu();
    
return 0;
}

//Menu Function//
void menu()
{
    struct location site[MAX];
    FILE*file;
    int i=0;
    char choice;
    char q;

    file = fopen("locations.txt" ,"r");

    while ( 1 /*!feof(file)*/ )
    {
        fscanf(file,"%s %s %f %f",&site[i].name[0],&site[i].place[0],&site[i].east,&site[i].north);
        if(!feof(file))
        {
            //printf("%s %s %f %f\n",site[i].name,site[i].place,site[i].east,site[i]. north);
            //i++;
        }
        else
        {
            break;
        }
    }
    fclose(file);

	do
	{ 

		printf("\nMenu\n\n");

		printf("[A]dd a record        [D]elete a record\n");
		printf("[E]dit a record       [S]earch for a record\n");
		printf("[V]iew all records\n\n"); 

		printf("Your choice [or Q to quit]:\n\n");

		scanf(" %c", &choice);

		if (choice == 'v') view_sites();		
		else if(choice == 'a') add_site();
		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];
	FILE*file;
    int i=0;
	file = fopen("locations.txt" ,"r");
	printf("\n\nAll Sites:\n\n");
    while ( 1 /*!feof(file)*/ )
    {
        fscanf(file,"%s %s %f %f",&site[i].name[0],&site[i].place[0],&site[i].east,&site[i].north);
		
        if(!feof(file))
        {
			
            printf("%s %s %f %f\n",site[i].name,site[i].place,site[i].east,site[i]. north);
            i++;
        }
        else
        {
            break;
        }
    }
    fclose(file);
}

//Add Site Function//
void add_site()
{
	struct location site[MAX];
	int i=0;
	FILE*file;

	if(strlen(site)== 0)
	printf("Please enter the name, place, east and north of new site:\n");
	scanf("%s %s %f %f", &site[i].name[0],&site[i].place[0],&site[i].east,&site[i].north);
	
	file = fwrite(&site[MAX], sizeof(site), 1, file);
}

Edited 5 Years Ago by Hey90: n/a

fscanf(file,"%s %s %f %f",&site[i].name[0],&site[i].place[0],&site[i].east,&site[i].north);

name and place are strings (the names of which serve as a constant pointer of the right type to the array, so remove the & from the above, for those variables. Also, remove the [0], from them, as well.

Keep the & (ampersand), for the east and north members.

feof() doesn't work as you'd like it to - frequently causing a repeat of the last data in the data file, to be entered into the array.

To avoid that, remove feof() and use the return value of fscanf(). It returns the number of objects it has stored.

stored = fscanf(file, ... etc.);
if(stored < 4)
  break;  //out of the read data loop

After scanf() in menu(), add:

getchar();  //or (void) getchar();

Which will "clean up" the newline char from the keyboard buffer (badly needed here).

Use a for loop to write out the array records to the file.

Open the data file for writing, with binary mode

#define MAX 25
for(i=0;i<MAX;i++) {  //(a define for the size of your array which you should have just below your list of include files) 

  fwrite(&array[i], sizeof(NameOfStruct), 1, file); //writes out 1 entire record to the file
                                               //pointed to by "file"

While you're learning, it might be better to use text mode, and fprintf(), and write out each struct.member, individually.

Edited 5 Years Ago by Adak: n/a

Ok thanks for that...but I do not have that error with feof.....I did originally with this code:

while (!feof(file))
{
    fscanf(file,"%s %s %f %f",  &site[i].name[0] , &site[i].place[0]  ,  &site[i].east, &site[i]. north);
    printf("%s %s %f %f\n",site[i].name,site[i].place,site[i].east,site[i]. north);
}

Edited 5 Years Ago by Hey90: n/a

Ok :-)

So the code below doesnt have any errors but when I look at the file after the name has not been written...why is this?

void add_site()
{
	struct location site[MAX];
	int i=0;
	FILE*file;
	
	file = fopen("locations.txt" ,"r");

	if(strlen(site[i].name)== 0)
		
		printf("Please enter the name");
		scanf("%s", site[0].name);

		for(i=0;i<MAX;i++) 
		{  
 		    fwrite(&site[i].name, sizeof(site), 1, file);
		}
                                               
}

You're missing braces on the if statement, and you didn't close the file. Unless MAX is 1, you're writing garbage in the for loop for indices [1,MAX) as well.

Unless MAX is 1, you're writing garbage in the for loop for indices [1,MAX) as well.

I don't understand this?

I don't understand this?

You have one string, but try to print MAX strings. The loop is totally unnecessary with your code as it is.

Don't declare a new array in add(). You should use an empty position in the array of records, you already have. Pass the array into the add function, as a parameter.

You need to close the data file, then reopen it, in "r+w" mode, rather than read mode only. This will erase the current data in the file, which you want.

Now you're ready to write all the data into it, which of course, includes the new record. There are better schemes for this, but this will do nicely for a very small database.

That's why you have no data going into the file yet - you opened it in read mode.

Edited 5 Years Ago by Adak: n/a

#include <stdio.h>
#include <string.h>
#define MAX 20

struct location
    {
		char name[20],place[20];
        float east,north;
      
    };struct location site[MAX];


    
//Functions//
void menu();
void view_sites();
void add_site(struct location site[], int i);
//void delete_record();
//void search_for_record();

//Main Funtion//
int main(void) 
{

    menu();
    
return 0;
}

//Menu Function//
void menu()
{
	struct location site[MAX];
	FILE*file;
    int i=0;
	char choice;
	char q;

    file = fopen("locations.txt" ,"r");

    while ( 1 /*!feof(file)*/ )
    {
        fscanf(file,"%s %s %f %f",site[i].name,site[i].place,&site[i].east,&site[i].north);
        if(!feof(file))
        {
            //printf("%s %s %f %f\n",site[i].name,site[i].place,site[i].east,site[i]. north);
            //i++;
        }
        else
        {
            break;
        }
    }
    fclose(file);

	do
	{ 

		printf("\nMenu\n\n");

		printf("[A]dd a record        [D]elete a record\n");
		printf("[E]dit a record       [S]earch for a record\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(struct location site[], int 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];
	FILE*file;
    int i=0, stored;
	file = fopen("locations.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++;
        }
    }
    fclose(file);
}

//Add Site Function//
void add_site(struct location site[], int i)
{
	
	FILE*file;
	
	file = fopen("locations.txt" ,"r");
	fclose(file);

	file = fopen("locations.txt" ,"r+w");

	if(strlen(site[i].name)== 0)
	{
		
		printf("Please enter the name");
		scanf("%s", site[0].name);

 		fwrite(&site[i].name, sizeof(site), 1, file); 

	}

	fclose(file);      	                                         
}

I get errors with line 71:

else if(choice == 'a') add_site(struct location site[], int i);

Saying:

error: expected expression before ‘struct’
error: too few arguments to function ‘add_site’

I am really confused with all this.

Although this is a very simple "flat file" database, you have to have all the basics of struct (record) and array handling, in order, to make it come together. There are a lot of parts to it, and trust me, you'll learn a LOT by working on this exercise.

else if(choice == 'a') add_site(struct location site[], int i);

this line includes the word "struct", "location", and "int", which shouldn't be included in the call to add_site().

else if(choice == 'a') add_site(site, i);

Where you use those terms like "struct", "location" and "int", is on the parameter list for the add_site() function itself:

void add_site(struct location site[MAX], int i) {
  //function code in here
}

Yes I am learning a LOT aha.

I seem to have a problem now with the choice in menu function...when I press a it just prints the menu again.

In your called functions, just add a little line of code that will show you that the program did go there:

printf("\n You reached the add_site function\n");

and don't clear your screen. This is just for debugging, of course, but something like the above, in every function you are concerned with, will help.

Looks like you have some upper case choices, and some lower case choices in your menu. You know C is case sensitive, so I'd change everything to one kind of case, and change all answers to that case, with toupper() or tolower() (part of string.h, IIRC).

Still hexed? Post up your latest code, and I'll study it some more.

Ok here is my code so far:

#include <stdio.h>
#include <string.h>
#define MAX 20

struct location
    {
        char name[20],place[20];
        float east,north;

    };struct location site[MAX];



//Functions//
void menu();
void view_sites();
void add_site(struct location site[MAX], int i);
//void delete_record();
//void search_for_record();

//Main Funtion//
int main(void) 
{

    menu();

return 0;
}

//Menu Function//
void menu()
{
    struct location site[MAX];
    FILE*file;
      int i=0, stored;
    char choice;
    char q;

    file = fopen("locations.txt" ,"r");


    stored = fscanf(file,"%s %s %f %f",site[i].name,site[i].place,&site[i].east,&site[i].north);

    fclose(file);

    do
    { 

        printf("\nMenu\n\n");

        printf("[a]dd a record        [d]elete a record\n");
        printf("[e]dit a record       [s]earch for a record\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_record();
        //else if(choice == "s") search_for_record();
        else if(choice == 'q') 
        {
            printf("Would you like to save changes to the locations file?:\n"); 
            return;
        }
        else
        {
            printf("Please only select from the above menu");
            menu();
        }

    }
    while(choice!=q);

}

void view_sites()
{
    printf("\n You reached the view_site function\n");

    struct location site[MAX];
    FILE*file;
    int i=0, stored;
    file = fopen("locations.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++;
        }
    }
    fclose(file);
}

//Add Site Function//
void add_site(struct location site[MAX], int i)
{

    printf("\n You reached the add_site function\n");

    FILE*file;

    file = fopen("locations.txt" ,"r");
    fclose(file);

    file = fopen("locations.txt" ,"r+w");

    if(strlen(site[i].name)== 0)
    {

        printf("Please enter the name");
        scanf("%s", site[0].name);

        fwrite(&site[i].name, sizeof(site), 1, file); 

    }

    fclose(file);      

}

I still don't know why the function add_site does not work...it does print 'you have reached the add_site function' but after that it returns to the menu.

Edited 3 Years Ago by mike_2000_17: Fixed formatting

Ok here is my code so far:

#include <stdio.h>
#include <string.h>
#define MAX 20

struct location
    {
		char name[20],place[20];
        float east,north;
      
    };struct location site[MAX];


    
//Functions//
void menu();
void view_sites();
void add_site(struct location site[MAX], int i);
//void delete_record();
//void search_for_record();

//Main Funtion//
int main(void) 
{

    menu();
    
return 0;
}

//Menu Function//
void menu()
{
	struct location site[MAX];
	FILE*file;
      int i=0, stored;
	char choice;
	char q;

    file = fopen("locations.txt" ,"r");

  
    stored = fscanf(file,"%s %s %f %f",site[i].name,site[i].place,&site[i].east,&site[i].north);
   
    fclose(file);

	do
	{ 

		printf("\nMenu\n\n");

		printf("[a]dd a record        [d]elete a record\n");
		printf("[e]dit a record       [s]earch for a record\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_record();
		//else if(choice == "s") search_for_record();
		else if(choice == 'q') 
		{
			printf("Would you like to save changes to the locations file?:\n");	
			return;
		}
		else
		{
			printf("Please only select from the above menu");
			menu();
		}
		
	}
	while(choice!=q);

}

void view_sites()
{
	printf("\n You reached the view_site function\n");
	
	struct location site[MAX];
	FILE*file;
    int i=0, stored;
	file = fopen("locations.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++;
        }
    }
    fclose(file);
}

//Add Site Function//
void add_site(struct location site[MAX], int i)
{

	printf("\n You reached the add_site function\n");
	
	FILE*file;

	file = fopen("locations.txt" ,"r");
	fclose(file);

	file = fopen("locations.txt" ,"r+w");

	if(strlen(site[i].name)== 0)
	{
		
		printf("Please enter the name");
		scanf("%s", site[0].name);

 		fwrite(&site[i].name, sizeof(site), 1, file); 

	}

	fclose(file);      
	                                         
}

I still don't know why the function add_site does not work...it does print 'you have reached the add_site function' but after that it returns to the menu.

<< ALWAYS post your code in between code tags! >>

Let's look at add_site():

/Add Site Function//
void add_site(struct location site[MAX], int i)
{

printf("\n You reached the add_site function\n");

FILE*file;

/*
You don't know if you need to open a file, at all yet. First,
see if you have an empty record in your array.
And you would never need to read in more data, from
the file, in this function. You may want to write out
data, after opening the data file using append mode.
*/

file = fopen("locations.txt" ,"r");
fclose(file);


/* not yet! */
file = fopen("locations.txt" ,"r+w");

if(strlen(site[i].name)== 0)  //should be == '\0' (zero is a number, not a char)
{

printf("Please enter the name");
scanf("%s", site[0].name);

fwrite(&site[i].name, sizeof(site), 1, file);

}

Files don't always open like we think they should. If you don't check, you
can crash your program, writing out data to a device that isn't ready to
receive anything.

if(file==NULL)
{ print a file opening error
  and any further directions
  and stop processing data (return with 1, 
  indicating an error, is normal).
}

You need a consistent plan for working with the file. I suggest opening it to read in the initial data, and then closing it, right afterward. Later on, you'll need to open it, perhaps, in append mode, to add some data to the end of the file.

Then, I suggest you close the file, immediately again. Data can be lost easily if you get sloppy or unlucky while the file is open.

Edited 5 Years Ago by Adak: n/a

Ok so finally I managed to be able to write something into the file. Using this code:

#include <stdio.h>
#include <string.h>
#define MAX 20

struct location
    {
		char name[20],place[20];
        float east,north;
      
    };struct location site[MAX];


    
//Functions//
void menu();
void view_sites();
void add_site(struct location site[MAX], int i);
//void delete_record();
//void search_for_record();

//Main Funtion//
int main(void) 
{

    menu();
    
return 0;
}

//Menu Function//
void menu()
{
	struct location site[MAX];
	FILE*file;
      int i=0, stored;
	char choice;
	char q;

    file = fopen("sites.txt" ,"r");

  
    stored = fscanf(file,"%s %s %f %f",site[i].name,site[i].place,&site[i].east,&site[i].north);
   
    fclose(file);

	do
	{ 

		printf("\nMenu\n\n");

		printf("[a]dd a record        [d]elete a record\n");
		printf("[e]dit a record       [s]earch for a record\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_record();
		//else if(choice == "s") search_for_record();
		else if(choice == 'q') 
		{
			printf("\nWould you like to save changes to the locations file?:\n\n");	
			return;
		}
		else
		{
			printf("Please only select from the above menu");
			menu();
		}
		
	}
	while(choice!=q);

}

void view_sites()
{
	printf("\n You reached the view_site function\n");
	
	struct location site[MAX];
	FILE*file;
    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++;
        }
    }
    fclose(file);
}

//Add Site Function//
void add_site(struct location site[MAX], int i)
{

	printf("\n You reached the add_site function\n");
	
	FILE*file;
	int stored;

	file = fopen("sites.txt" ,"r");
	
	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;
        }
    }
		
 
    fclose(file);

	file = fopen("sites.txt" ,"a");

	if (file==NULL) printf("FAILED TO OPEN FILE!!\n\n");

	if(sizeof(site[i])== '0')
	{
		printf("\nPlease enter the name:\n\n");
		scanf("%s", site[0].name);

		printf("\nPlease enter the place:\n\n");
		scanf(" %s", site[0].place);
	}
	
	fwrite(&site[0].name, sizeof(site), 1, file); 
	fwrite(&site[0].place, sizeof(site), 1, file); 

	
fclose(file);      
	                                         
}

My orginal .txt file is:

Ikea Nottingham 0.1 0.2
Tesco Leicester 0.3 0.4

and then after calling add_site() I entered: 'Asda' for name and 'Lincoln' for place

The result produces this:

Ikea Nottingham 0.1 0.2
Tesco Leicester 0.3 0.4
AsdaLinc

and when I try and add another name and place again it sometimes adds it to the same line as the previous one or works as I would like and adds it on a new line. Also after I have inputed a new record when I call the view_sites() function it only displays how the .txt originally looked.

//Add Site Function//
void add_site(struct location site[MAX], int i)
{

	printf("\n You reached the add_site function\n");
	
	FILE*file;
	int stored;

/* The file should be opened and read in, at the top of the menu() function, not down here. Otherwise you'll have to read the file in, in every function (almost).

	file = fopen("sites.txt" ,"r");
	
	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;
        }
    }
		
 
    fclose(file);

All the above file code should be moved to the top of menu(), outside the big loop
*/


/* You're not ready to write out data yet. Move to the bottom of this function */
	file = fopen("sites.txt" ,"a");

	if (file==NULL) { 
           printf("FAILED TO OPEN FILE!!\n\n"); 
           return 1;
        }
	
     for(i=0;i<MAX;i++) {
       if(sizeof(site[i])== '0') //nope, should be '\0' (char end of string marker)
       {
	  printf("\nPlease enter the name:\n\n");
	  scanf("%s", site[0].name);  //you want site[i], not site[0]!

	  printf("\nPlease enter the place:\n\n");
	  scanf(" %s", site[0].place);  //same, use site[1], not site[0]

/* What about East and North? They should get some value? */

         print the name and place, to ensure you've got them OK, here.
         a little check saves a lot of time, later on.
	}
	
/* You should use printf(), and save the binary writing of the records, until after 
the program is de-bugged. */
	fwrite(&site[0].name, sizeof(site), 1, file); 

/* fwrite usually writes out an entire record, all at once, not a single record field */  

// unnecessary in any case==>fwrite(&site[0].place, sizeof(site), 1, file); 

	
fclose(file);      
	                                         
}

Ok finally I have managed to add to the .txt file. Now my problem is deleting. I have tried getting user input of the 'name' that wants to be deleted in order to find the record. This has not worked. Also I remember you saying once the record has been found that the first character needs to be zeroed out ('\0'). Would you use strcpy..or something along those lines? the delete function is at the bottom.

Sorry about this being long winded, I really appreciate your help.

#include <stdio.h>
#include <string.h>
#define MAX 20

struct location
    {
		char name[20],place[20];
        float east,north;
      
    };struct location site[MAX];

//Functions//
void menu(void);
void view_sites(void);
void add_site(struct location site[MAX], int i);
void delete_site(struct location site[MAX], int i);
//void search_for_record();

//Main Funtion//
int main(void) 
{
    menu();
	return 0;
}

//Menu Function//
void menu()
{
	struct location site[MAX];
	
    int i=0, stored;
	char choice;
	char q;
	
	FILE*file;
   	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++;  
		}
    }

	fclose(file);

	do
	{ 

		printf("\nMenu\n");
		printf("\nPlease press the key in [] to choose the appropriate option\n\n");		
		
		printf("[a]dd a record        [d]elete a record\n");
		printf("[e]dit a record       [s]earch for a record\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 == 's') search_for_record();
		else if(choice == 'q') 
		{
			printf("\nWould you like to save changes to the locations file?:\n\n");	
			return;
		}
		else
		{
			printf("Please only select from the above menu");
			menu();
		}
		
	}
	while(choice!='q');

}

void view_sites()
{
	printf("\n You reached the view_site function\n\n");
	struct location site[MAX];
    FILE*file;
    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++;
        }
    }
     
}

//Add Site Function//
void add_site(struct location site[MAX], int i)
{

	printf("\nYou reached the add_site function\n\n");
	
	int j;      
 
    FILE*file;
 
	//Search for next empty record    
	for (j=0;j<MAX;j++)
    
		if(site[j].name[0] == 0)   break; //j = next empty record
               
        //HERE also ERROR Check if j >= MAX !!!!!   
                 
        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);
                                              
        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);
                                                          
}

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

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

	int j;

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

	file = fopen ("sites.txt", "r");

	for (j=0;j<MAX;j++)
		if(site[j].name == "%c")
		{
			printf("This site exists");
		}
		else
		{
			printf("This site does not exist");
		}

	fclose(file);

}

You can use any character you want to flag the record as being deleted -- just use a character that is not likely to be valid in the record. Using '\0' may not be your best choice because that will make the file binary. I'd use something like tilda, or '~'. To do that all you have to do is fseek() to be beginning of the file and fwrite() a single charcter. Note that this will not prevent your program from reading the entire record. Your program has to learn that the '~' character means the record is deleted and should therefore just ignore it.

Edited 5 Years Ago by Ancient Dragon: n/a

I have used the end of string marker char: '\0' in the past, but AD is quite right - any char that couldn't be used in a name field, would be fine.

Once you decide what char you want to use, it's just a matter of assignment:

site[i].name[0]= '\0'; //or whatever char you want to use.

Then you have to let the program know what you're looking for, in your other functions. You don't want to be handling a "name", that has been marked with a tilde, as if it was still a valid entry.

Looking at the delete function:

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

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

	int j;

	FILE*file;
 
	printf("Please enter the name of the record you would like to delete:\n");

/* 
you need to enter a full name, not a single char, here. You're not looking for an empty record slot, you're looking for a record that is already entered into the database.
*/
	scanf(" %c", site[j].name);  //%s and this should be inside a for loop
/* how do you know before you look, what index (j) will have your record? */

/* you're opening files when you don't need to. 
First, work in the array, in any function -
THEN do the file work, if needed, LAST
THING.
*/



	file = fopen ("sites.txt", "r");

	for (j=0;j<MAX;j++)
		if(site[j].name == "%c")//if((strcmp(site.[j].name, target_name)==0)
		{
			printf("This site exists");
		}

/* it's a good idea to print the record on screen, 
and let the user confirm all deletions, before your
program makes them.


For future info:
Since the deleting technique is to overwrite
one char in the name field, there's an easy way to 
"recover" any record that was deleted accidentally,
with all data, except the first char, of the name.

*/	
	}
        if(j>=MAX)
		{
			printf("This site does not exist");
		}

/* 
do your file work down here, if needed. If the site to be 
deleted isn't found, you have nothing in the file, to do.
*/

	fclose(file);

}

Ok so now I end up deleting the whole text file....it is now the second to last function as I have added a find function.

#include <stdio.h>
#include <string.h>
#define MAX 20

struct location
    {
		char name[20],place[20];
        float east,north;
      
    };struct location site[MAX];

//Functions//
void menu(void);
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);

//Main Funtion//
int main(void) 
{
    menu();
	return 0;
}

//Menu Function//
void menu()
{
	struct location site[MAX];
	
    int i=0, stored;
	char choice;
	char q;
	
	FILE*file;
   	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++;  
		}
    }

	fclose(file);

	do
	{ 

		printf("\nMenu\n");
		printf("\nPlease press the key in [] to choose the appropriate option\n\n");		
		
		printf("[a]dd a site        [d]elete a record\n");
		printf("[f]ind a site       [s]earch for a record\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 == 'q') 
		{
			printf("\nWould you like to save changes to the locations file?:\n\n");	
			return;
		}
		else
		{
			printf("Please only select from the above menu");
			menu();
		}
		
	}
	while(choice!='q');

}

/////iew Sites///
void view_sites()
{
	printf("\n You reached the view_site function\n\n");
	struct location site[MAX];
    FILE*file;
    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++;
        }
    }
     
}

///////////////Add Site Function///////////////
void add_site(struct location site[MAX], int i)
{

	printf("\nYou reached the add_site function\n\n");
	
	int j;      
 
    FILE*file;
 
	//Search for next empty record    
	for (j=0;j<MAX;j++)
    
		if(site[j].name[0] == 0)   break; //j = next empty record
               
        //HERE also ERROR Check if j >= MAX !!!!!   
                 
        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);
                                              
        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\n",site[j].name);                                    
                                              
        fclose(file);

}

///////////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");


}

I did not understand your last post. Please tell me what function you are referring to, and what the problem is.

I don't want to spend time looking through the whole program or running it, so help me to zero in on the issue here.

This article has been dead for over six months. Start a new discussion instead.