Hi there, i have an assignment, and i need to create a monthly expenditure. I have managed to get alot done, a fully functioning menu and all the functions. Im stuck when it comes to deleting an entry

I have been using structured arrays to store data, ive posted all my code, i thought it be easier for help, sorry for the massive post.

#include "stdafx.h"
#include <iostream>
#include <string>
#include <stdlib.h>
#include <fstream>
using namespace std;

int i;
int count;
int userChoice;
string temp;

int newExpenses();
int newIncome();
void menuExpenses();
void menuIncome();
void mainMenu();
void monthlyExpenses();
void monthlyIncome();
void deleteEntry();


int main()
{

	string line;
	ifstream myfile ("counter.txt");
	if(myfile.is_open())
	{
		while(!myfile.eof())
		{
			getline(myfile,line);
			temp=line;
		}
		myfile.close();
	}


	count=atoi(temp.c_str());
	
	do{
	mainMenu();
	}while(userChoice != 1 || userChoice != 2);

	return 0;
}

struct entry{
	int ID;
	string date;
	string item;
	string price;
	string category;
}entries[100];

void mainMenu()
{
	cout<<"Monthly Expenditure"<<endl<<endl<<endl;
	cout<<"Main Menu"<<endl<<endl;
	cout<<"Income [1]"<<endl<<"Expenses [2]"<<endl<<"View Monthly Income [3]"<<endl<<"View Monthly Expenses [4]"<<endl<<"Delete Entry [5]"<<endl;
	cin>>userChoice;

	if(userChoice == 1)
	{	
		system("cls");
		menuIncome();
	}	
	
	else if(userChoice == 2)
	{
		system("cls");
		menuExpenses();
	}	

	else if(userChoice == 3)
	{
		system("cls");
		monthlyIncome();
	}

	else if(userChoice == 4)
	{
		system("cls");
		monthlyExpenses();
	}

	else if(userChoice == 5)
	{
		system("cls");
		deleteEntry();
	}

	else
	{
		system("cls");
		cout<<"Invalid input, please select again [1] [2] [3] [4]";
	}
}

void monthlyIncome()
{
	string line;
	ifstream myfile ("Income.txt");
	if(myfile.is_open())
	{
		while(!myfile.eof())
		{
			getline(myfile,line);
			cout<<line<<endl;
		}
		myfile.close();
	}

}


void monthlyExpenses()
{
	string line;
	ifstream myfile ("Expenses.txt");
	if(myfile.is_open())
	{
		while(!myfile.eof())
		{
			getline(myfile,line);
			cout<<line<<endl;
		}
		myfile.close();
	}

}

void menuExpenses()
{
int userChoice2=0;

do{
	cout<<"Expenses"<<endl<<endl;
	cout<<"Add Entry (1)"<<endl;
	cout<<"Sort Ascending (2)"<<endl;
	cout<<"Sort Descending (3)"<<endl;
	cin>>userChoice2;

	if(userChoice2 == 1)
	{
		system("cls");
		newExpenses();
	}
	else if(userChoice2 == 2)
	{	
		system("cls");
		//Sort code
	}
	else if(userChoice2 == 3)
	{	
		system("cls");
		//Sort code
	}
	else
	{
		system("cls");
		cout<<"Invalid input, please select again [1] [2] [3]"<<endl<<endl;
		userChoice2=0;

	}
}while(userChoice2==0);

}		

void menuIncome()
{
int userChoice3=0;

do{

	cout<<"Income"<<endl<<endl;
	cout<<"Add Entry (1)"<<endl;
	cout<<"Sort Ascending (2)"<<endl;
	cout<<"Sort Descending (3)"<<endl;
	cin>>userChoice3;

	if(userChoice3 == 1)
	{
		system("cls");
		newIncome();
	}
	else if(userChoice3 == 2)
	{
		system("cls");
		//Sort code
	}
	else if(userChoice3 == 3)
	{
		system("cls");
		//Sort code
	}
	else
	{
		system("cls");
		cout<<"Invalid input, please select again (1) (2) (3)"<<endl<<endl;
		userChoice3=0;
	}
}while(userChoice3==0);

}

int newIncome()
{
		cout<<"Income"<<endl<<endl;
		cout<<"New Entry"<<endl;

		entries[count].ID=count;
		cout<<"Date: ";
		cin>>entries[count].date;
		cout<<"Item: ";
		cin>>entries[count].item;
		cout<<"Price: ";
		cin>>entries[count].price;
		cout<<"Category: ";
		cin>>entries[count].category;
		cout<<endl;

		ofstream fout;
		
		fout.open("Income.txt", ios::app);

		fout<<entries[count].ID<<"     "<<entries[count].date<<"     "<<entries[count].item<<"     "<<entries[count].category<<"     "<<entries[count].price<<endl;
		fout<<flush;
		fout.close();


		
count++;


ofstream fout1;

fout1.open ("counter.txt");

fout1<<count;
fout1<<flush;
fout1.close();
return 0;
}		

int newExpenses()
{
	
		cout<<"Expenses"<<endl<<endl;
		cout<<"New Entry"<<endl;

		entries[count].ID=count;
		cout<<"Date: ";
		cin>>entries[count].date;
		cout<<"Item: ";
		cin>>entries[count].item;
		cout<<"Price: ";
		cin>>entries[count].price;
		cout<<"Category: ";
		cin>>entries[count].category;
		cout<<endl;

		ofstream fout;
		
		fout.open("Expenses.txt", ios::app);
		
		fout<<entries[count].ID<<"     "<<entries[count].date<<"     "<<entries[count].item<<"     "<<entries[count].category<<"     "<<entries[count].price<<endl;
		fout<<flush;
		fout.close();
	

	
count++;

ofstream fout1;

fout1.open ("counter.txt");

fout1<<count;
fout1<<flush;
fout1.close();
return 0;
}	

void deleteEntry()
{
	int choice;
	int i;

	cout<<"What entry do you wish to delete?: "<<endl;
	cin>>choice;
	
	if(choice >= 0 && choice <= 100)
	{
		for(i=choice;i<100;i++)
		{
		entries[i] = entries[i + 1];
		}
	}
	else
	{
		cout<<"Invalid Entry";
	}
}

What my tutor suggested was to use a counter, and then save the counter also in a text file, so when i reopen the console, the counter doesnt reset to 0

Is there a simpler way to be able to delete one of these entries? each entry has an ID

(new to programming, still learning at uni)

1) Move the structure definition in lines 49-55 up above any functions, about line 13 because it makes better overall program organization. Most programs are organized to have all includes at the top followed by structures, classes, enumerations (in any order or in header files), globals and function prototypes. You have most of that already, just need to move the structure declaration to the top of the program.

line 34: why??

lines 64-88: It might be better to use a switch statement instead of all those if statements.

line 294: The array only has 100 elements, numbered 0 to and including 99. So the statement should be < 100, not <= 100.

The only other comment about that function is you need to clear the last structure by setting all strings to empty strings.

Thank you for your reply Ancient Dragon, i really appreciate the help, i have moved the structure declaration to line 13 now, and i have changed line 294 also to <100

Line 34: To be honest mate, im not sure either, my tutor helped me on this one, its something to do with changing the integer into a string, so i can save the counter in a text file. But the whole reason for that in the first place was to be able to delete an entry by its 'ID'

So when i re opened the console, and added another entry, the 'ID' didnt reset back to 0

I was aiming to be able to delete an entry by its 'ID', but now thinking about it, i dont think that would work.

0 20/09/2009 Watch Clothing £29.99
1 21/02/2009 Watch Clothes £13.99
2 11/11/2009 Bangle Jewellery £674.99

This is what the data in the text file looks like, can i not delete the data from the text file directly? Overwrite it maybe?

My heads spinning lol, im new to all this :)

>>can i not delete the data from the text file directly? Overwrite it maybe?

The only way to delete a line in a text file is to rewrite the entire file, leaving out the line to be deleted.

Also, don't put the £ symbol in the file because it just makes reading the file a little more difficult.

line 34 doesn't really do anything because temp is overwritten on every loop iteration. You need to add more code inside that loop to populate that array of structures as the rows are read. You can't wait until after reading is done. For example. At the end of the loop below the variable counter will contain the number of rows read from the file. You will want to use that variable throughout the rest of the program to determine how many valid entries there are in the array. When deleting a row make sure the row number to be deleted does not exceed the value of counter, which will probably be less than 100. When adding a new row you have to add it to the first unused entry (counter+1) and increment counter variable.

#include <sstream> // required for stringstream class

if(myfile.is_open())
{
    int counter = 0;
    while(getline(myfile,line))
    {
          stringstream str(line);
    // now split the line into its individual parts
    // These are listed in the same order as they appear
    // in the structure.
          str >> entries[counter].ID
               >> entries[counter].date
               >> entries[counter].item
               >> entries[counter].category
               >> entries[counter].price;
    }
    myfile.close();
}

Thanks again Dragon for the reply, ive sat and read through it a few times to get my head around it a bit more, it seems to be sinking in a little bit haha :D

Ive got rid of line 34 now and added the stringsteam header file

int main()
{

if(myfile.is_open())
{
    int counter = 0;
    while(getline(myfile,line))
    {
          stringstream str(line);

          str >> entries[counter].ID
               >> entries[counter].date
               >> entries[counter].item
               >> entries[counter].category
               >> entries[counter].price;
    }
    myfile.close();
}

        count=atoi(temp.c_str());
	return 0;
}

Is that where i am supposed to put it?

Dragon, ive decided that alot of my code was unnecessary, so i got rid of some functions, and made it alot simpler, and i also added the code that you suggested, although im not sure what it does lol

#include "stdafx.h"
#include <iostream>
#include <string>
#include <stdlib.h>
#include <fstream>
#include <sstream>
using namespace std;

int count;
int userChoice;

struct entry{
	int ID;
	string type;
	string date;
	string item;
	string price;
	string category;
}entries[100];

int newEntry();
void mainMenu();
void monthlyExpenditure();
void deleteEntry();


int main()
{
	string line;
	ifstream myfile ("Expend.txt");
	if(myfile.is_open())
	{
    int count = 0;
    while(getline(myfile,line))
    {
          stringstream str(line);

          str  >> entries[count].ID
	        >> entries[count].type
               >> entries[count].date
               >> entries[count].item
               >> entries[count].category
               >> entries[count].price;
    }
    myfile.close();
}


	do{
	mainMenu();
	}while(userChoice != 1 || userChoice != 2);

	return 0;
}


void mainMenu()
{
	cout<<"Monthly Expenditure"<<endl<<endl<<endl;
	cout<<"Main Menu"<<endl<<endl;
	cout<<"Add Entry [1]"<<endl<<"Delete Entry [2]"<<endl<<"View Expenditure [3]"<<endl;
	cin>>userChoice;

	if(userChoice == 1)
	{	
		system("cls");
		newEntry();
	}	
	
	else if(userChoice == 2)
	{
		system("cls");
		deleteEntry();
	}	

	else if(userChoice == 3)
	{
		system("cls");
		monthlyExpenditure();
	}

	else
	{
		system("cls");
		cout<<"Invalid input, please select again [1] [2] [3]";
	}
}

void monthlyExpenditure()
{
	string line;
	ifstream myfile ("Expend.txt");
	if(myfile.is_open())
	{
		while(!myfile.eof())
		{
			getline(myfile,line);
			cout<<line<<endl;
		}
		myfile.close();
	}

}

int newEntry()
{
		cout<<"New Entry"<<endl<<endl;

		entries[count].ID=count;
		cout<<"Type: ";
		cin>>entries[count].type;
		cout<<"Date: ";
		cin>>entries[count].date;
		cout<<"Item: ";
		cin>>entries[count].item;
		cout<<"Price: ";
		cin>>entries[count].price;
		cout<<"Category: ";
		cin>>entries[count].category;
		cout<<endl;

		ofstream fout;
		
		fout.open("Expend.txt", ios::app);

		fout<<entries[count].ID<<"     "<<entries[count].type<<"     "<<entries[count].date<<"     "<<entries[count].item<<"     "<<entries[count].category<<"     "<<entries[count].price<<endl;
		fout<<flush;
		fout.close();
		
count++;

return 0;
}		


void deleteEntry()
{
//code here to enable to delete an entry
}

I have taken out the code for the counter, should i put it back in? all it did was save the count in a text file, so when i reopened the console, it didnt reset to 0

Heres what my new text file looks like now, just 1 text file now instead of 2 for both Income and Expenses

0 Income 02/02/2009 Salary Wage 1299.99
1 Expense 02/02/2009 Watch Jewellery 29.99
2 Expense 26/02/2009 Car Vehicle 3412.87
0 Income 29/02/2009 Salary Wage 1087.00
0 Expense 29/02/2009 Sunglasses Clothing 124.65

the new entries[count].type is for the user to enter whether its a income or expense, also can you see the 'ID' down the side, there are two entries with 0, the last two entries, this is where i closed the console and reopened it, and then added another entry, the count is back to 0

Does that code you gave me load the information from the text file back into the array?

and i also added the code that you suggested, although im not sure what it does lol

What it does is move the line read from the file into the structure. There is no point reading the file if you are not going to do anything with the data.

I have taken out the code for the counter, should i put it back in?

No -- variable count is ok too.

all it did was save the count in a text file, so when i reopened the console, it didnt reset to 0

Actually saving count to the text file. Just count the lines as they are read is all that you need to do.

And you need to increment the value of count on line 44, which I think I forgot to do in my post.

Does that code you gave me load the information from the text file back into the array?

Yes

Cheers again Dragon for the help, i tried using the string stream to load the data back into the array, but it didnt work, so instead i tried this

ifstream fin ("Expend.txt");
	if(fin.is_open())
	{
    
    while (!fin.eof())
		{
			for (j=1;j<250;j++)
			{
				fin >> entries[j].ID
					>> entries[j].type
					>> entries[j].date
					>> entries[j].item
					>> entries[j].price
					>> entries[j].category;
		
			}
		}
		fin.close();
	}

This seems to work too, i need to pick your brains about somethin else also. Is there such code that will close the console window, i want an option on the menu that when a user enters that option, it will exit the console

And another thing, am i able to save all the data in the structure array to a text file, in one go. Pls can you show me some example code of how i can achieve this. I have an idea, i think i need to put it in a loop

ofstream fout;
		
		fout.open("Expend.txt");

		for (j=1;j<250;j++)
		{
		
			fout
			<<entries[j].type<<"     "
			<<entries[j].date<<"     "
			<<entries[j].item<<"     "
			<<entries[j].price<<"     "
			<<entries[j].category<<endl;
		
	
		}
		fout<<flush;
		fout.close();

I tried this, but it saves all 250 array entries as 0, i dont know how to get it to just saved the entries with data in them

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