Getting specific inputs from a file

I have a listing of a file

Page 1 of 1

11 Replies - 541 Views - Last Post: 25 March 2010 - 04:30 PM Rate Topic: -----

#1 IngeniousHax  Icon User is offline

  • |>|20-514<|{3|2

Reputation: 78
  • View blog
  • Posts: 1,358
  • Joined: 28-March 09

Getting specific inputs from a file

Posted 25 March 2010 - 01:39 PM

So I have an assignment where I had to build a program to write inventory information to a file, and than it had to allow the user to search for certain items and also overwrite certain items... That works fine.

But not I have to take the file that was made from that assignment and read in the numerical values to get a final number...
such as:
total quantity on hand :15000
total whole cost: $250000
total retail value: $500000

The only problem is, I can't read in just the values I need...
Or I can't figure it out rather, I thought changing the way I wrote to the file, so it was more of a listing than a binary mode file would help, but than my listing portion of the program doesn't work.

Any ideas on how to access specific elements of a file?

If you need th previous assignment code, I can provide that, but I just deleted all my current assignment code out of frustration...

Is This A Good Question/Topic? 0
  • +

Replies To: Getting specific inputs from a file

#2 jjl  Icon User is offline

  • Engineer
  • member icon

Reputation: 1046
  • View blog
  • Posts: 4,449
  • Joined: 09-June 09

Re: Getting specific inputs from a file

Posted 25 March 2010 - 01:43 PM

What does the file actually look like. Im thinking you can just use a stringstream with getline to tokenize each line into separate parts.
Was This Post Helpful? 0
  • +
  • -

#3 IngeniousHax  Icon User is offline

  • |>|20-514<|{3|2

Reputation: 78
  • View blog
  • Posts: 1,358
  • Joined: 28-March 09

Re: Getting specific inputs from a file

Posted 25 March 2010 - 01:57 PM

the file currently looks like this:
candy ÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌô         @      @0716198 


But, I could have it output like this:
candy // item description
500 // amount on hand
560 // whole sale price
570 // retail price
07161987 // date added



the latter of the two though, doesn't read correctly when searching for an inventory item and crashes

This post has been edited by IngeniousHax: 25 March 2010 - 01:58 PM

Was This Post Helpful? 0
  • +
  • -

#4 jjl  Icon User is offline

  • Engineer
  • member icon

Reputation: 1046
  • View blog
  • Posts: 4,449
  • Joined: 09-June 09

Re: Getting specific inputs from a file

Posted 25 March 2010 - 02:17 PM

post your code
Was This Post Helpful? 0
  • +
  • -

#5 IngeniousHax  Icon User is offline

  • |>|20-514<|{3|2

Reputation: 78
  • View blog
  • Posts: 1,358
  • Joined: 28-March 09

Re: Getting specific inputs from a file

Posted 25 March 2010 - 02:19 PM

This is the code that : Writes to file, reads certain entries from file, edits entries in file
#include <iostream>
#include <iomanip>
#include <string>
#include <fstream>
using namespace std;

const int maxDesc = 100, maxDate = 8;		// Constants
struct inventoryInfo
{
	char itemDescription[maxDesc];
	int quantityOH;		// quantity on hand
	double wholeSale;		// the wholesale cost
	double retailCost;		// The retail cost of the item
	char dateAdded[maxDate];	// the date the item was added
};

/****************************\
|		Function Prototypes			  |
\****************************/
char menu();
void writeToFile(inventoryInfo &);
long recordNum(int);
void displayRecordFromFile(inventoryInfo &, char *);
void modifyRecordFromFile(inventoryInfo &, char *);
void fatal(char *);
void invalidEntry(char *);

/**********************\
|			Begin Main			|
\**********************/
int main() 
{
	inventoryInfo inv;
	char menuChoice;
	char inventorySearch[maxDesc];

	do
	{
		cout << "\t\t-=[ Inventory Menu ]=- \n" << endl;
		menuChoice = menu();		// call menu function to get user choice, than use switch() statement to use choice accordingly
			switch(menuChoice)
			{
				case 'A' :
					cin.clear();
					cin.ignore();
					writeToFile(inv);
					cin.clear();
					cout << "\n\nPress any key to return to menu." << endl;
					cin.sync();
					cin.get();
					system("cls");
					break;
				case 'B':
					cin.clear();
					cin.ignore();
					cout << "Enter the item name to display it's listing: " ;
					cin.getline(inventorySearch, maxDesc);
					cin.clear();
					displayRecordFromFile(inv, inventorySearch);
					cout << "\n\nPress any key to return to menu." << endl;
					cin.sync();
					cin.get();
					system("cls");
					break;
				case 'C':
					cin.clear();
					cin.ignore();
					cout << "Enter item's name to modify: ";
					cin.getline(inventorySearch, maxDesc);
					cin.clear();
					modifyRecordFromFile(inv, inventorySearch);
					cout << "\n\nPress any key to return to menu" << endl;
					cin.sync();
					cin.get();
					system("cls");
			}
	}while(menuChoice != 'D');		// Loop until exit button is entered, which is D
	return 0;
}

/**************************\
|	Begin Function Definitions		   |
\**************************/
	

void fatal(char *msg)
{
	cout << msg << endl;
	exit(1);
}

void invalidEntry(char *msg)
{
	cout << msg << endl;
	cout << "Please re-enter: ";
}


/**********************\
|		Print Menu				|
\**********************/
char menu()
{
	char userMenu;
	char options[4][50] = {
		"A) Add new records to file\n",
		"B)/> Display any record in file\n", 
		"C) Change a record in the file\n",
		"D) Exit\n"	};

		for(int x = 0; x < 4; x++)
			printf("%s", options[x]);
		cin >> userMenu;
		return toupper(userMenu);
}
/*******************\
|		End Menu			|
\*******************/

void writeToFile(inventoryInfo &inv)		// Writing to file portion
{
	char response;		// For looping until user decides they dont want to enter anymore

	ofstream outFile("inventory.dat", ios::out  | ios::app);		// open a file for writing in binary mode
	if(!outFile)		// If unable to open file for some reason, call fatal()
		fatal("[!!] Fatal error opening inventory.dat");


	system("cls");		// clear screen for aesthetics and cleanliness
	cout << "\t\t -=[ Inventory Entry Screen ]=-" << endl;
	do
	{		// Begin receiving the information from the user for the corresponding information
		cout << "Item Description: ";
		cin.getline(inv.itemDescription, maxDesc); 
		
		cout << "Quantity On Hand: ";
		cin >> inv.quantityOH;
		cin.ignore();
		if(inv.quantityOH < 0)		// If the onhand quantity is negative, spit out an error and ask for a re-enter
		{
			invalidEntry("[!!] Quantity on hand entered less than 0");		// invalidEntry() prints the corresponding message aswell as a re-enter, defined in function
			cin >> inv.quantityOH;
			cin.ignore();
		}
		
		cout << "Wholesale Cost: $";
		cin >> inv.wholeSale;
		cin.ignore();
		if(inv.wholeSale < 0)		// same as inv.quanityOH above
		{
			invalidEntry("[!!] Wholesale cost less than 0");
			cin >> inv.wholeSale;
			cin.ignore();
		}
		
		cout << "Retail Cost: $";
		cin >> inv.retailCost;
		cin.ignore();
		if(inv.retailCost < 0)		// Sam as above information and error checking
		{
			invalidEntry("[!!] Retail cost less than 0");
			cin >> inv.retailCost;
			cin.ignore();
		}
		
		cout << "Date Added (mmddyyyy): ";		// Enter the date
		cin.getline(inv.dateAdded, maxDate);
		if(sizeof(inv.dateAdded) > 8)// || sizeof(inv.dateAdded) < 7)	// If its 7, good, if it's 8, spit an error, less than 7, error
		{
			invalidEntry("[!!] Date entered incorrectly");
			cin.clear();
			cin >> inv.dateAdded;
		}
		
		outFile.write(reinterpret_cast<char*>(&inv), sizeof(inv));	// Write the information to the file
		cin.clear();
		cin.ignore();		// ignore the \n, otherwise the program falls through "item description"
		cout << "Additional inventory to add to file (y/n): ";		// if the user wants to write more
		cin >> response;
		response = toupper(response);	// set response toupper(), saves on typing
		cin.ignore();
		cout << "\n\n";
	}while(response == 'Y');

	outFile.close();		// Close the file
}

/*********************\
|	END WRITE TO FILE  |
\*********************/





/*************************\
| This function is to read the user  |
| defined inventory item to find	|
| and print it out as requested by	|
| option B in the switch()			|
| statement.							|
\************************/

void displayRecordFromFile(inventoryInfo &inv, char *inventorySearch)		// look at a specific entry in the file
{
	int i = 0;		// For the count of records passed until found
	ifstream inFile("inventory.dat", ios::in  | ios::beg);	// open the file for reading from the beginning in binary mode
	
	if(!inFile)		// if unable to open file for reading
		fatal("[!!] Fatal error opening inventory.dat");	// call to fatal() function

	inFile.read(reinterpret_cast<char *>(&inv), sizeof(inv));		// Get the full first entry from inventoryInfo
	
	while(strcmp(inventorySearch, inv.itemDescription) != 0 && !inFile.eof())	// while the search string isn't found, continue to loop
	{
		i ++;		// increase each time it isn't found
		inFile.read(reinterpret_cast<char *>(&inv), sizeof(inv));		// Read the entire struct information for next comparison
	}

	if(strcmp(inventorySearch, inv.itemDescription) == 0)	// If it is found go through and do this
	{
		inFile.seekg(recordNum(i), ios::beg);	// go to found item, seeking from beginning of file and using recordNum to start reading from

		system("cls");	// clear the screen (aesthetics)
		cout << "\t\t-=[ Inventory Listing ]=-\n\n" << endl;		// Print heading of choice and all the information until next comment
			cout << "Item description: " << inv.itemDescription << endl;
			cout << "Quantity on hand: " << inv.quantityOH << endl;
			cout << "Wholesale cost: $" << fixed << showpoint << setprecision(2) << inv.wholeSale << endl;
			cout << "Retail cost: $" << fixed << showpoint << setprecision(2) << inv.retailCost << endl;
			cout << "Date added: " << inv.dateAdded << endl;
			cout << endl;	// End printing information of user defined inventory string
	}
	else
		fatal("[!!] Listing not found. May not exist.");		// If entry is not found, print fatal() function

}

/************************\
|	END READ ENTRY			|
\************************/



/**********************************\
| This function is going to allow a user to		|
| select an entry to modify. It will scan the file	|
| and grab the entry, than ask the user for the	|
| new information for the entry					|
\**********************************/

void modifyRecordFromFile(inventoryInfo &inv, char *inventorySearch)
{
	int i = 0;		// For the count of records passed until found
	fstream File("inventory.dat", ios::in | ios::out  | ios::beg);	// open the file for reading from the beginning in binary mode
	
	if(!File)		// if unable to open file for reading
		fatal("[!!] Fatal error opening inventory.dat");	// call to fatal() function

	File.read(reinterpret_cast<char *>(&inv), sizeof(inv));		// Get the full first entry from inventoryInfo
	
	while(strcmp(inventorySearch, inv.itemDescription) != 0 && !File.eof())	// while the search string isn't found, continue to loop
	{
		i ++;		// increase each time it isn't found
		File.read(reinterpret_cast<char *>(&inv), sizeof(inv));		// Read the entire struct information for next comparison
	}

	if(strcmp(inventorySearch, inv.itemDescription) == 0)	// If it is found go through and do this
	{
		File.seekg(recordNum(i), ios::beg);	// go to found item, seeking from beginning of function and using recordNum to stop reading at
		system("cls");
		cout << "\t\t-=[ Entry Found ]=-" << endl;
		cout << "\t\t-=[ Begin Modifications To The Entry ]=-" << endl;
		
		cout << "Item Description: ";
		cin.getline(inv.itemDescription, maxDesc); 
		
		cout << "Quantity On Hand: ";
		cin >> inv.quantityOH;
		cin.ignore();
		if(inv.quantityOH < 0)		// If the onhand quantity is negative, spit out an error and ask for a re-enter
		{
			invalidEntry("[!!] Quantity on hand entered less than 0");		// invalidEntry() prints the corresponding message aswell as a re-enter, defined in function
			cin >> inv.quantityOH;
			cin.ignore();
		}
		
		cout << "Wholesale Cost: $";
		cin >> inv.wholeSale;
		cin.ignore();
		if(inv.wholeSale < 0)		// same as inv.quanityOH above
		{
			invalidEntry("[!!] Wholesale cost less than 0");
			cin >> inv.wholeSale;
			cin.ignore();
		}
		
		cout << "Retail Cost: $";
		cin >> inv.retailCost;
		cin.ignore();
		if(inv.retailCost < 0)		// Sam as above information and error checking
		{
			invalidEntry("[!!] Retail cost less than 0");
			cin >> inv.retailCost;
			cin.ignore();
		}
		
		cout << "Date Added (mmddyyyy): ";		// Enter the date
		cin.getline(inv.dateAdded, maxDate);
		if(sizeof(inv.dateAdded) > 8)// || sizeof(inv.dateAdded) < 7)	// If its 7, good, if it's 8, spit an error, less than 7, error
		{
			invalidEntry("[!!] Date entered incorrectly");
			cin.clear();
			cin >> inv.dateAdded;
		}
	}
	else
		fatal("[!!] Entry not found.");
		
		File.write(reinterpret_cast<char*>(&inv), sizeof(inv));
		cout << "\t\t\t-=[ Modification Complete ]=-"  << endl;
		cin.ignore();
		cin.clear();
}






/**********************\
| To get the records position	|
| in the file for the user, so		|
| they can view any record		|
| they want, thats in the file		|
\**********************/
long recordNum(int i)
{
	return sizeof(inventoryInfo) * i;
}
/****************\
| End recordNum	   |
\****************/


Was This Post Helpful? 0
  • +
  • -

#6 n8wxs  Icon User is offline

  • --... ...-- -.. . -. ---.. .-- -..- ...
  • member icon

Reputation: 971
  • View blog
  • Posts: 3,878
  • Joined: 07-January 08

Re: Getting specific inputs from a file

Posted 25 March 2010 - 02:54 PM

Quote

But not I have to take the file that was made from that assignment and read in the numerical values to get a final number...
such as:
total quantity on hand :15000
total whole cost: $250000
total retail value: $500000

The only problem is, I can't read in just the values I need...
Or I can't figure it out rather, I thought changing the way I wrote to the file, so it was more of a listing than a binary mode file would help, but than my listing portion of the program doesn't work.

Any ideas on how to access specific elements of a file?


Are you trying to sum up each of the values for each file record?


I found a problem with the date added field in your inventoryInfo structure. The character array is sized as 8. It should be 9 because there needs to be space for a terminating null.

...
cout << "Date Added (mmddyyyy): ";              // Enter the date
cin.getline(inv.dateAdded, maxDate); // getline() will add a terminating null
...



See Get line from stream
Was This Post Helpful? 0
  • +
  • -

#7 IngeniousHax  Icon User is offline

  • |>|20-514<|{3|2

Reputation: 78
  • View blog
  • Posts: 1,358
  • Joined: 28-March 09

Re: Getting specific inputs from a file

Posted 25 March 2010 - 03:00 PM

Yeah thats what I am trying to do, and thanks for the bug find.
Was This Post Helpful? 0
  • +
  • -

#8 n8wxs  Icon User is offline

  • --... ...-- -.. . -. ---.. .-- -..- ...
  • member icon

Reputation: 971
  • View blog
  • Posts: 3,878
  • Joined: 07-January 08

Re: Getting specific inputs from a file

Posted 25 March 2010 - 03:28 PM

Well, this should get you started. :)

void sumRecords()
{
	int quantityOH = 0;         // quantity on hand
	double wholeSale = 0;       // the wholesale cost
	double retailCost = 0;      // The retail cost of the item

	inventoryInfo inv;

	// open the file for reading from the beginning in binary mode
	ifstream inFile("inventory.dat", ios::in  | ios::binary);

	if(!inFile)             // if unable to open file for reading
		fatal("[!!] Fatal error opening inventory.dat");        // call to fatal() function

	while (inFile.read((char *)&inv, sizeof(inv)))
	{
		quantityOH += inv.quantityOH;
		wholeSale += inv.wholeSale * inv.quantityOH;
		retailCost += inv.retailCost * inv.quantityOH;
	}

	inFile.close();

	cout << "total quantity on hand: " << quantityOH << endl;
	cout << "total whole cost: " << wholeSale << endl;
	cout << "total retail value: " << retailCost << endl;
}


Was This Post Helpful? 1
  • +
  • -

#9 IngeniousHax  Icon User is offline

  • |>|20-514<|{3|2

Reputation: 78
  • View blog
  • Posts: 1,358
  • Joined: 28-March 09

Re: Getting specific inputs from a file

Posted 25 March 2010 - 04:11 PM

Thanks, but I have the below question on how that works...

So the way that works is it just references the data types and ignores the ones not being accessed by the data types?
Was This Post Helpful? 0
  • +
  • -

#10 n8wxs  Icon User is offline

  • --... ...-- -.. . -. ---.. .-- -..- ...
  • member icon

Reputation: 971
  • View blog
  • Posts: 3,878
  • Joined: 07-January 08

Re: Getting specific inputs from a file

Posted 25 March 2010 - 04:25 PM

Yes. :)

The while() loop is reading one record from the file each pass. The record is read into the inventoryInfo inv; structure. The sums are computed by using the values stored in the record. The itemDescription and dateAdded fields are still part of the record but are being ignored since they are not useful in finding the totals.
Was This Post Helpful? 1
  • +
  • -

#11 IngeniousHax  Icon User is offline

  • |>|20-514<|{3|2

Reputation: 78
  • View blog
  • Posts: 1,358
  • Joined: 28-March 09

Re: Getting specific inputs from a file

Posted 25 March 2010 - 04:26 PM

Ohhhh.... That's a lot less complicated than I was making it in my head. LoL. I was trying all kinds of wicked things. Thanks a lot for your help n8wxs
Was This Post Helpful? 0
  • +
  • -

#12 n8wxs  Icon User is offline

  • --... ...-- -.. . -. ---.. .-- -..- ...
  • member icon

Reputation: 971
  • View blog
  • Posts: 3,878
  • Joined: 07-January 08

Re: Getting specific inputs from a file

Posted 25 March 2010 - 04:30 PM

You're welcome!
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1