#include <iostream>
#include <fstream>
#include <iomanip>
using namespace std;
const int DESC_SIZE = 50;
const int DATE_SIZE = 10;
struct Inventory
{
char desc[DESC_SIZE],
date[DATE_SIZE];
int quantity;
double whlCost,
rtlCost;
};
int menu();
void addRecord(fstream &);
void displayRecord(fstream &);
void changeRecord(fstream &);
int main ()
{
Inventory rec = {"", 0, 0.0};
cout << fixed << showpoint << setprecision(2);
cout << "Auto Zone Inventory" << endl;
int selection;
fstream invtry("Inventory.dat", ios::out | ios::binary);
if (!invtry)
{
cout << "Error opening the file.";
return 0;
}
for (int count = 0; count < 10; count++)
{
invtry.write(reinterpret_cast<char*>(&rec),sizeof(rec));
}
invtry.close();
invtry.open("Inventory.dat", ios::out | ios::binary);
do
{
selection = menu();
switch(selection)
{
case 1:
addRecord(invtry);
break;
case 2:
displayRecord(invtry);
break;
case 3:
changeRecord(invtry);
break;
case 4:
cout << "Thank you for using this program. Take care now!" << endl;
}
} while(selection!= 4);
invtry.close();
system("pause");
return 0;
}
int menu ()
{
int choice;
//system("cls");
cout << "Auto Zone Inventory" << endl;
cout << "1. Add new records to the file" << endl;
cout << "2. Display any record in the file" << endl;
cout << "3. Change any record in the file" << endl;
cout << "4. Quit the program" << endl;
cout << endl;
cout << "Please enter your choice (1-4): ";
cin >> choice;
while (choice < 1 || choice > 4)
{
cout << "Invalid entry. Please enter a number (1-4)" << endl;
cin >> choice;
}
cout << endl;
return choice;
}
void addRecord(fstream &file)
{
cout << "Please enter new record data" << endl;
Inventory rec;
fstream invtry("Inventory.dat", ios::out | ios::binary);
if (!invtry)
{
cout << "Error in opening the file.";
exit(-1);
}
cout << "Item Description:" << endl;
cin.ignore();
cin.getline(rec.desc, DESC_SIZE);
cout << rec.desc << endl;
cout << "Quantity on hand:" << endl;
cin >> rec.quantity;
while (rec.quantity < 0)
{
cout << "Invalid entry. Please enter only positive values." << endl;
cin >> rec.quantity;
}
cout << "Wholesale Cost" << endl;
cin >> rec.whlCost;
while (rec.whlCost < 0)
{
cout << "Invalid entry. Please enter only positive values." << endl;
cin >> rec.whlCost;
}
cout << "Retail Cost" << endl;
cin >> rec.rtlCost;
while (rec.rtlCost < 0)
{
cout << "Invalid entry. Please enter only positive values." << endl;
cin >> rec.rtlCost;
}
cout << "Date added to inventory" << endl;
cin.ignore();
cin.getline(rec.date, DATE_SIZE);
invtry.write(reinterpret_cast<char *>(&rec),sizeof(rec));
cout << "Record added to inventory";
file.close();
}
void displayRecord(fstream &file)
{
Inventory rec;
fstream invtry("Inventory.dat", ios::in | ios::out | ios::binary);
if (!invtry)
{
cout << "Error in opening the file.";
exit(-1);
}
long num;
cout << "Please enter the record you would like to view (1-10)" << endl;
cin >> num;
invtry.seekg(num * sizeof(rec), ios::beg);
invtry.read(reinterpret_cast<char *>(&rec), sizeof(rec));
while (!invtry.eof())
{
cout << "Here is your current record:";
cout << "Item Description:";
cout << rec.desc << endl;
cout << "Quantity on hand:";
cout << rec.quantity << endl;
cout << "Wholesale cost";
cout << rec.whlCost << endl;
cout << "Retail cost:";
cout << rec.rtlCost << endl;
cout << "Date added to inventory:";
cout << rec.date << endl;
invtry.read(reinterpret_cast<char *>(&rec),sizeof(rec));
file.close();
}
}
void changeRecord(fstream &file)
{
Inventory rec;
long num;
fstream invtry("Inventory.dat", ios::in | ios::out | ios::binary);
if (!invtry)
{
cout << "Error opening the file.";
exit(-1);
}
cout << "Please enter the record you wish to edit (1-10)";
cin >> num;
invtry.seekg(num * sizeof(rec), ios::beg);
invtry.read(reinterpret_cast<char *>(&rec), sizeof(rec));
cout << "Here is your current record:";
cout << "Item description:";
cout << rec.desc << endl;
cout << "Quantity on hand:";
cout << rec.quantity << endl;
cout << "Wholesale cost:";
cout << rec.whlCost << endl;
cout << "Retail cost:";
cout << rec.rtlCost << endl;
cout << "Date added to inventory:";
cout << rec.date << endl;
cout << "Please enter your new data to the record";
cout << "Item description:";
cin.ignore();
cin.getline(rec.desc, DESC_SIZE);
cout << "Quantity on hand:";
cin >> rec.quantity;
while (rec.quantity < 0)
{
cout << "Invalid entry. Please enter only positive values." << endl;
cin >> rec.quantity;
}
cout << "Wholesale cost:";
cin >> rec.whlCost;
while (rec.whlCost < 0)
{
cout << "Invalid entry. Please enter only positive values." << endl;
cin >> rec.whlCost;
}
cout << "Retail cost:";
cin >> rec.rtlCost;
while (rec.rtlCost < 0)
{
cout << "Invalid entry. Please enter only positve values." << endl;
cin >> rec.rtlCost;
}
cout << "Date added to inventory:";
cin.ignore();
cin.getline(rec.date, DATE_SIZE);
invtry.seekp(num * sizeof(rec), ios::beg);
invtry.write(reinterpret_cast<char *>(&rec), sizeof(rec));
cout << "The Record has been edited." << endl;
invtry.close();
}
Infinite loops in a file program
Page 1 of 114 Replies - 575 Views - Last Post: 10 December 2012 - 07:18 PM
#1
Infinite loops in a file program
Posted 28 November 2012 - 05:59 PM
Replies To: Infinite loops in a file program
#2
Re: Infinite loops in a file program
Posted 28 November 2012 - 06:26 PM
Quote
Yes, one of the problems is that you seem to try to open files that are already open. For example look at the following snippet:
void addRecord(fstream &file)
{
...
fstream invtry("Inventory.dat", ios::out | ios::binary);
if (!invtry)
{
cout << "Error in opening the file.";
exit(-1);
}
...
invtry.write(reinterpret_cast<char *>(&rec),sizeof(rec));
cout << "Record added to inventory";
file.close();
}
In your calling function you have already opened Inventory.dat using the file instance. So why are you trying to reopen the same file in this function and naming the stream invtry? Next why are you closing file before you leave this function? You should really close the file in the same function that opened it in the first place, don't hide this closing of your stream. It will make finding problems harder.
In my opinion you should open you file once, and only once. You then pass this stream instance to your functions, as you are already doing. Then use this file stream in your functions. Make sure you check that the read/write operations succeed by testing the stream before and after the read/write operations.
Also unless the use of binary files is a requirement of your assignment I recommend you stick with text files until you are more familiar with file input and output. Is much more difficult to insure that you are properly writing your file when using binary files because you need specialty programs to view your file.
Jim
#3
Re: Infinite loops in a file program
Posted 29 November 2012 - 02:40 AM
I have to say that you explained everything very clearly here, and I never realized until you pointed this out. All I can say is that the only reason I kept closing the file, was because I thought that was what you were supposed to do, according to the book that I was reading. However; in their example, they were not using functions or menus, so I overlooked the real problem, which obviously is files opening and closing, and a looping mess!
I noticed that I did not make multiple checks for the files, only when I started the stream for each function, not afterward. So making another check during that could also help out in seeing if I have a problem, which I obviously do.
When you say that I should close the file in the same function that opened it,then wouldn't that then be the menu function? Is that where it should be closed and only closed? Makes sense if that is the case, since the menu will always be the function that opens up the option functions for the user.
I named the file stream "invrty" because I thought it was supposed to be a different name from the file name. Is that wrong? Please explain this, as that is how they showed me in the book.
"In your calling function you have already opened Inventory.dat using the file instance. So why are you trying to reopen the same file in this function and naming the stream invtry?"
I'm not sure I understand this, yes I created an instance with: Inventory rec = {"", 0, 0.0}; But I haven't even named the file yet until about 4 lines down. So can you explain to me how you say that I am opening the file up twice..
No, the assignment does not specifically require binary files, but when I when to practice one of the exercises in the book, I was able to use binary, and even though you can't read anything in the file, the display will still reveal the correct information that is stored there. But yeah you are right about reading it in the file, but is it really that much of a problem? As long as the screen is outputting the correct information, why would that matter?
This post has been edited by JackOfAllTrades: 02 December 2012 - 05:17 AM
Reason for edit:: Removed unecessary quote
#4
Re: Infinite loops in a file program
Posted 29 November 2012 - 07:16 AM
Quote
It looks like you are opening "Inventory.dat" in main(), so that is where I would close the file, but not until after I was totally finished processing that file. Also remember that C++ file streams will be automatically closed when they go out of scope. So in the following snippet:
void processFile();
int main()
{
processFile();
return 0;
}
void processFile()
{
ifstream fin("Inventory.dat");
// Do some reading...
}
The Inventory.dat file is opened in processFile() and it will automatically be closed when that function ends. This one of the nice things about using C++ streams the have destructors which will automatically clean up after themselves.
Quote
The name of the file stream can anything, as long as it is unique. It could be the same as the file name, but that is not necessary. Remember the name of the stream is a variable, and you must follow variable naming rules. I myself prefer to keep the name of file streams short, but at the same time descriptive. If I only have one file I usually use things like "fin" for input files and "fout" for output files. But there is nothing wrong with invrty, inventory, or any other name. However I would normally use something like inventory for the name of the class instance that is being used to handle the data from the file.
Quote
In the following snippet:
void addRecord(fstream &file)
{
...
fstream invtry("Inventory.dat", ios::out | ios::binary);
...
file.close();
}
You are passing in a reference to a file stream, this file stream was opened in the calling function. The name of the file used when opening this stream was "Inventory.dat". So after the call to fstream() you will have two file streams that are operating on the same actual file. One stream named file, the other named invtry. In this function since you have passed a properly opened fstream you should use that and not create a new fstream instance. At the end of this function you close the file that you passed in as an argument, why?
void readFile(std::fstream& fin);
void writeFile(std::fstream& fout);
int main()
{
fstream finout("Inventory.dat");
readFile(finout);
writeFile(finout);
}
void readFile(std::fstream& fin)
{
// Do some reading.
fin.close();
}
void writeFile(std::fstream& fout)
{
// Let's try to write to the file.
fout << "HELLO WORLD"<< std::endl;
fout.close();
}
When you try to run this program you may forget that the stream was closed in your functions. Remember in this simple program these functions are in the same file but in an actual program the functions may be in separate files, and possibly written by different people.
Quote
In my opinion the problem with binary files is that when you make a change to the format of the file, you must rewrite the entire file. With a text file you and use a text editor to view and alter the file to suit your new requirements. It is also much easier to see whem you are not properly reading and writing to the file when you can see the differences in a text editor.
Jim
This post has been edited by jimblumberg: 29 November 2012 - 07:18 AM
#5
Re: Infinite loops in a file program
Posted 01 December 2012 - 08:25 PM
Quote
void readFile(std::fstream& fin);
void writeFile(std::fstream& fout);
int main()
{
fstream finout("Inventory.dat");
readFile(finout);
writeFile(finout);
}
void readFile(std::fstream& fin)
{
// Do some reading.
fin.close();
}
void writeFile(std::fstream& fout)
{
// Let's try to write to the file.
fout << "HELLO WORLD"<< std::endl;
fout.close();
}
In your example you have the streams named in the prototypes, but there is no in:: or out:: inside the function. My question is this; how is the compiler going to what to do with the file. If it needs to read it, wouldn't you need a in::, or to write an out::? I understand when you say that I shouldn't open the files up in the functions because they were already opened back in main, but how are you going to let the compiler know what to do with it? Here is an updated code, it will look funny to you, because I was trying to use the in:: and the out:: in the functions, because that is where I am stuck.
Also, I have another function called "changeRecord" and that is going to need two arguments; one to read what is currently in the file, and the other to write or change the file from what it was previously. How would I go about in passing two arguments for that function? Here is the updated code....
#include <iostream>
#include <fstream>
#include <iomanip>
using namespace std;
const int DESC_SIZE = 50;
const int DATE_SIZE = 10;
struct Inventory
{
char desc[DESC_SIZE],
date[DATE_SIZE];
int quantity;
double whlCost,
rtlCost;
};
int menu();
void addRecord(std::fstream& fout);
void displayRecord(std::fstream& fin);
void changeRecord(std::fstream&);
int main ()
{
Inventory rec = {"", 0, 0.0};
cout << fixed << showpoint << setprecision(2);
//cout << "Auto Zone Inventory" << endl;
int selection;
fstream finout("Inventory.dat", ios::out | ios::binary);
if (!finout)
{
cout << "Error opening the file.";
return 0;
}
for (int count = 0; count < 10; count++)
{
finout.write(reinterpret_cast<char*>(&rec),sizeof(rec));
}
//finout.close();
//finout.open("Inventory.dat", ios::out | ios::binary);
do
{
selection = menu();
switch(selection)
{
case 1:
addRecord(finout);
break;
case 2:
displayRecord(finout);
break;
case 3:
changeRecord(finout);
break;
case 4:
cout << "Thank you for using this program. Take care now!" << endl;
}
} while(selection!= 4);
//invtry.close();
system("pause");
return 0;
}
int menu ()
{
int choice;
//system("cls");
cout << "Auto Zone Inventory" << endl;
cout << "1. Add new records to the file" << endl;
cout << "2. Display any record in the file" << endl;
cout << "3. Change any record in the file" << endl;
cout << "4. Quit the program" << endl;
cout << endl;
cout << "Please enter your choice (1-4): ";
cin >> choice;
while (choice < 1 || choice > 4)
{
cout << "Invalid entry. Please enter a number (1-4)" << endl;
cin >> choice;
}
cout << endl;
return choice;
}
void addRecord(std::fstream& fout)
{
cout << "Please enter new record data" << endl;
Inventory rec;
//fstream fout("Inventory.dat", ios::out | ios::binary);
if (!fout)
{
cout << "Error in opening the file.";
exit(-1);
}
cout << "Item Description:" << endl;
cin.ignore();
cin.getline(rec.desc, DESC_SIZE);
cout << rec.desc << endl;
cout << "Quantity on hand:" << endl;
cin >> rec.quantity;
while (rec.quantity < 0)
{
cout << "Invalid entry. Please enter only positive values." << endl;
cin >> rec.quantity;
}
cout << "Wholesale Cost" << endl;
cin >> rec.whlCost;
while (rec.whlCost < 0)
{
cout << "Invalid entry. Please enter only positive values." << endl;
cin >> rec.whlCost;
}
cout << "Retail Cost" << endl;
cin >> rec.rtlCost;
while (rec.rtlCost < 0)
{
cout << "Invalid entry. Please enter only positive values." << endl;
cin >> rec.rtlCost;
}
cout << "Date added to inventory" << endl;
cin.ignore();
cin.getline(rec.date, DATE_SIZE);
fout.write(reinterpret_cast<char *>(&rec),sizeof(rec));
cout << "Record added to inventory";
fout.close();
}
void displayRecord(std::fstream& fin)
{
Inventory rec;
// fstream fin("Inventory.dat", ios::in | ios::binary);
if (!fin)
{
cout << "Error in opening the file.";
exit(-1);
}
long num;
cout << "Please enter the record you would like to view (1-10)" << endl;
cin >> num;
fin.seekg(num * sizeof(rec), ios::beg);
fin.read(reinterpret_cast<char *>(&rec), sizeof(rec));
while (!fin.eof())
{
cout << "Here is your current record:";
cout << "Item Description:";
cout << rec.desc << endl;
cout << "Quantity on hand:";
cout << rec.quantity << endl;
cout << "Wholesale cost";
cout << rec.whlCost << endl;
cout << "Retail cost:";
cout << rec.rtlCost << endl;
cout << "Date added to inventory:";
cout << rec.date << endl;
fin.read(reinterpret_cast<char *>(&rec),sizeof(rec));
fin.close();
}
}
void changeRecord(std::fstream& fin, std::fstream& fout)
{
Inventory rec;
long num;
fstream invtry("Inventory.dat", ios::in | ios::out | ios::binary);
if (!invtry)
{
cout << "Error opening the file.";
exit(-1);
}
cout << "Please enter the record you wish to edit (1-10)";
cin >> num;
invtry.seekg(num * sizeof(rec), ios::beg);
invtry.read(reinterpret_cast<char *>(&rec), sizeof(rec));
cout << "Here is your current record:";
cout << "Item description:";
cout << rec.desc << endl;
cout << "Quantity on hand:";
cout << rec.quantity << endl;
cout << "Wholesale cost:";
cout << rec.whlCost << endl;
cout << "Retail cost:";
cout << rec.rtlCost << endl;
cout << "Date added to inventory:";
cout << rec.date << endl;
cout << "Please enter your new data to the record";
cout << "Item description:";
cin.ignore();
cin.getline(rec.desc, DESC_SIZE);
cout << "Quantity on hand:";
cin >> rec.quantity;
while (rec.quantity < 0)
{
cout << "Invalid entry. Please enter only positive values." << endl;
cin >> rec.quantity;
}
cout << "Wholesale cost:";
cin >> rec.whlCost;
while (rec.whlCost < 0)
{
cout << "Invalid entry. Please enter only positive values." << endl;
cin >> rec.whlCost;
}
cout << "Retail cost:";
cin >> rec.rtlCost;
while (rec.rtlCost < 0)
{
cout << "Invalid entry. Please enter only positve values." << endl;
cin >> rec.rtlCost;
}
cout << "Date added to inventory:";
cin.ignore();
cin.getline(rec.date, DATE_SIZE);
invtry.seekp(num * sizeof(rec), ios::beg);
invtry.write(reinterpret_cast<char *>(&rec), sizeof(rec));
cout << "The Record has been edited." << endl;
invtry.close();
}
This post has been edited by jimblumberg: 01 December 2012 - 09:43 PM
Reason for edit:: Removed unecessary quote.
#6
Re: Infinite loops in a file program
Posted 01 December 2012 - 09:42 PM
int someFunction(int); int someFunction(int name);
The function implementation requires a name as well as the type. This name will be used inside the function to refer to the that variable. This name does not need to match either the function prototype variable name or the function call variable name.
But remember that the function prototype, function implementation, and the function call must all agree as to the number and the type of parameters. Don't confuse the name of the variables with the variable type. Types are things like int, double, float, fstream, etc.
Quote
Since you are using fstream you don't need to pass two different stream instances into your function. An fstream can read and write to the stream at the same time. This is the purpose of this class. This class has different stream pointers for input and output. You can be receiving input from one point in a file without affecting the position of the output pointer. But in order to read and write from the stream you first need to open the stream for both input and output.
fstream finout("yourFileName", std::ios::binary | std::ios::in | std::ios::out);
If you only want input or output, but not both then you should be using the ifstream and ofstream classes. These classes are designed to only read or write to the stream.
In your changeRecord() function you are still trying to re-open your already open stream. You don't want to do this, use the parameter you are passing into this function. And remember your function implementation doesn't agree with your function prototype, you will need to fix this issue. Also when you want to change the position of the get pointer you need to use the seekg() member function and when you want to change the position of the put pointer you need to use the seekp() member function.
Jim
#7
Re: Infinite loops in a file program
Posted 09 December 2012 - 08:15 PM
jimblumberg, on 01 December 2012 - 09:42 PM, said:
int someFunction(int); int someFunction(int name);
The function implementation requires a name as well as the type. This name will be used inside the function to refer to the that variable. This name does not need to match either the function prototype variable name or the function call variable name.
But remember that the function prototype, function implementation, and the function call must all agree as to the number and the type of parameters. Don't confuse the name of the variables with the variable type. Types are things like int, double, float, fstream, etc.
Quote
Since you are using fstream you don't need to pass two different stream instances into your function. An fstream can read and write to the stream at the same time. This is the purpose of this class. This class has different stream pointers for input and output. You can be receiving input from one point in a file without affecting the position of the output pointer. But in order to read and write from the stream you first need to open the stream for both input and output.
fstream finout("yourFileName", std::ios::binary | std::ios::in | std::ios::out);
If you only want input or output, but not both then you should be using the ifstream and ofstream classes. These classes are designed to only read or write to the stream.
In your changeRecord() function you are still trying to re-open your already open stream. You don't want to do this, use the parameter you are passing into this function. And remember your function implementation doesn't agree with your function prototype, you will need to fix this issue. Also when you want to change the position of the get pointer you need to use the seekg() member function and when you want to change the position of the put pointer you need to use the seekp() member function.
Jim
Ok so I have been working on this program all week, and I have everything good except the date validation. I need to include in my regular expression algorithm leap year and dates that can be passed as valid. I was able to find the one I have online, but I am having trouble adding to it for the leap year and valid dates. The only thing this validation will check is for dashes, integers between 0-9, and not allow strings and that is it. Is there a way I can add to this expression that I have currently for leap year and valid dates? Here is my updated code:
// inventory.cpp : Defines the entry point for the console application.
//
#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>
#include <regex>
using namespace std;
const int DESC_SIZE = 50;
struct Date{
int Month;
int Day;
int Year;
};
struct Inventory
{
char desc[DESC_SIZE];
int quantity;
double whlCost,
rtlCost;
Date date;
};
void menu(std::fstream&);
bool addRecord(std::fstream&);
bool displayRecord(std::fstream&);
bool changeRecord(std::fstream&);
Date dateValidation(string);
int main()
{
cout << fixed << showpoint << setprecision(2);
fstream file;
ifstream ifile("Inventory.dat");
if (!ifile)
{
Date date;
date.Day = 1;
date.Month = 1;
date.Year = 1970;
Inventory rec = {"Default", 0, 0.0, 0.0, date};
file.open ("Inventory.dat", fstream::out | fstream::binary);
for (int count = 0; count < 10; count++)
{
file.write((char*)&rec,sizeof(rec));
}
cout << endl << "Warning, did not find file, so we created one.";
cout << endl;
file.close();
}
// Create Menu and run program
menu(file);
system("pause");
return 0;
}
Date dateValidation(string data){
Date date;
match_results<string::const_iterator> m;
regex re("([0-9]+)-([0-9]+)-([0-9]*)?");
if (regex_match(data, m, re)) {
date.Day = stoi(m[1].str()),
date.Month = stoi(m[2].str()),
date.Year = stoi(m[3].str());
}
else date.Year = 0000;
return date;
}
void menu(std::fstream& file)
{
int choice = 0;
bool success;
while(choice!= 4) {
cout << "Auto Zone Inventory" << endl;
cout << endl << "1. Add new records to the file" << endl;
cout << "2. Display any record in the file" << endl;
cout << "3. Change any record in the file" << endl;
cout << "4. Quit the program" << endl;
cout << endl;
cout << "Please enter your choice (1-4): ";
cin >> choice;
while (choice < 1 || choice > 4)
{
cout << endl << "Invalid entry. Please enter a number (1-4)" << endl;
cin >> choice;
}
cout << endl;
switch(choice){
case 1:
success = addRecord(file);
break;
case 2:
success = displayRecord(file);
break;
case 3:
success = changeRecord(file);
break;
case 4:
success = true;
cout << "Thank you for using this program. Auto Zone cares!" << endl;
break;
default :
cout << "Error " << choice << " is not a valid number";
break;
}
if (!success) cout << "File IO Error reading file!";
else {
system("Pause");
system("cls");
}
}
}
bool addRecord(std::fstream& file)
{
cout << "Please enter new record data" << endl;
Inventory rec;
string dateStr;
file.open ("Inventory.dat", fstream::out | fstream::app | fstream::binary);
cout << endl << "Item Description:" << endl;
cin.ignore();
cin.getline(rec.desc, DESC_SIZE);
cout << rec.desc << endl;
cout << endl << "Quantity on hand:" << endl;
cin >> rec.quantity;
while (rec.quantity < 0)
{
cout << endl << "Invalid entry. Please enter only positive values." << endl;
cin >> rec.quantity;
}
cout << endl << "Wholesale Cost" << endl;
cin >> rec.whlCost;
while (rec.whlCost < 0)
{
cout << endl << "Invalid entry. Please enter only positive values." << endl;
cin >> rec.whlCost;
}
cout << endl << "Retail Cost" << endl;
cin >> rec.rtlCost;
while (rec.rtlCost < 0)
{
cout << endl << "Invalid entry. Please enter only positive values." << endl;
cin >> rec.rtlCost;
}
bool loop = true;
while (loop){
cout << endl << "Date added to inventory (MM-DD-YYYY)" << endl;
cin.ignore();
cin >> dateStr;
rec.date = dateValidation(dateStr);
if (rec.date.Year != 0000) {
loop = false;
}
else
cout << endl << "Error Date Format is (MM-DD-YYYY)" <<endl;
}
file.write(reinterpret_cast<char *>(&rec),sizeof(rec));
cout << endl << "Record added to inventory" << endl;
file.close();
return true;
}
bool displayRecord(std::fstream& file)
{
Inventory rec;
file.open ("Inventory.dat", fstream::in | fstream::binary);
long num;
//Figure out How many records exist
long a = file.tellg();
file.seekg(0, fstream::end);
long b = file.tellg();
long sizeFile = b - a;
int c = sizeof(rec);
int numRecords = (sizeFile / c);
if (numRecords > 0){
cout << "Please enter the record you would like to view (1-"<< (numRecords) <<")" << endl;
cin >> num;
if ((num >= 0) && (num <= (numRecords))){
num = num -1;
file.seekg(num * sizeof(rec), fstream::beg);
file.read(reinterpret_cast<char *>(&rec), sizeof(rec));
if (!file.eof())
{
cout << endl << "Here is your current record:" << endl;
cout << endl << "Item Description: ";
cout << rec.desc << endl;
cout << "Quantity on hand: ";
cout << rec.quantity << endl;
cout << "Wholesale cost: ";
cout << rec.whlCost << endl;
cout << "Retail cost: ";
cout << rec.rtlCost << endl;
cout << "Date added to inventory: ";
cout << rec.date.Day << "-" << rec.date.Month << "-" << rec.date.Year << endl;
}
file.close();
}
else {
cout << "Record Outside of Database Range" << endl;
}
}
else {
cout << "No Records Found !" << endl;
return false;
}
return true;
}
bool changeRecord(std::fstream& file)
{
Inventory rec;
Inventory* recs;
string dateStr;
string yn;
char* buffer;
long num;
file.open ("Inventory.dat", fstream::in | fstream::out | fstream::binary);
//Figure out How many records exist
long a = file.tellg();
file.seekg(0, fstream::end);
long b = file.tellg();
long sizeFile = b - a;
int numRecords = 0;
if (sizeFile > 4){
int c = sizeof(rec);
numRecords = (sizeFile / c);
}
if (numRecords > 0){
cout << "Please enter the record you would like to view (1-"<< (numRecords) <<")" << endl;
cin >> num;
if (!file.eof()){
num = num -1;
file.seekg(num * sizeof(rec), fstream::beg);
file.read(reinterpret_cast<char *>(&rec), sizeof(rec));
cout << endl << "Here is your current record" << endl;
cout << endl << "Item description: ";
cout << rec.desc << endl;
cout << "Quantity on hand: ";
cout << rec.quantity << endl;
cout << "Wholesale cost: ";
cout << rec.whlCost << endl;
cout << "Retail cost: ";
cout << rec.rtlCost << endl;
cout << "Date added to inventory: ";
cout << rec.date.Day << "-" << rec.date.Month << "-" << rec.date.Year << endl;
}
cout << endl << "Do you want to proceed ? (Y/N)" << endl;
cin >> yn;
if ((yn == "Y")||(yn == "y")){
cout << endl << "Please enter your new data to the record"<< endl;
cout << endl << "Item description:" << endl;
cin.ignore();
cin.getline(rec.desc, DESC_SIZE);
cout << endl << "Quantity on hand:" << endl;
cin >> rec.quantity;
while (rec.quantity < 0)
{
cout << endl << "Invalid entry. Please enter only positive values." << endl;
cin >> rec.quantity;
}
cout << endl << "Wholesale cost:" << endl;
cin >> rec.whlCost;
while (rec.whlCost < 0)
{
cout << endl << "Invalid entry. Please enter only positive values." << endl;
cin >> rec.whlCost;
}
cout << endl << "Retail cost:" << endl;
cin >> rec.rtlCost;
while (rec.rtlCost < 0)
{
cout << endl << "Invalid entry. Please enter only positve values." << endl;
cin >> rec.rtlCost;
}
bool loop = true;
while (loop){
cout << endl << "Date added to inventory (MM-DD-YYYY)" << endl;
cin.ignore();
cin >> dateStr;
rec.date = dateValidation(dateStr);
if (rec.date.Year != 0000) {
loop = false;
}
else
cout << endl << "Error Date Format is (MM-DD-YYYY)" <<endl;
}
file.seekp(num * sizeof(rec), fstream::beg);
file.write(reinterpret_cast<char *>(&rec), sizeof(rec));
cout << endl << "The Record has been edited." << endl;
}
}
else cout << endl << "File contains no records!" << endl;
file.close();
return true;
}
#8
Re: Infinite loops in a file program
Posted 10 December 2012 - 05:13 AM
Example:
// validate the time while setting it
void Time::setTime(int h, int m, int s)
{
setHour(h);
setMinute(m);
setSecond(s);
}
void Time::setHour(int h)
{ hour = (h >= 0 && h < 24) ? h : 0; }
void Time::setMinute(int m)
{ minute = (m >= 0 && m < 60) ? m : 0; }
void Time::setSecond(int s)
{ second = (s >= 0 && s < 60) ? s : 0; }
Hope this Helps!
#9
Re: Infinite loops in a file program
Posted 10 December 2012 - 01:38 PM
// inventory.cpp : Defines the entry point for the console application.
//
#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>
#include <regex>
using namespace std;
const int DESC_SIZE = 50;
struct Date{
int Month;
int Day;
int Year;
};
struct Inventory
{
char desc[DESC_SIZE];
int quantity;
double whlCost,
rtlCost;
Date date;
};
void menu(std::fstream&);
bool addRecord(std::fstream&);
bool displayRecord(std::fstream&);
bool changeRecord(std::fstream&);
Date dateValidation(string);
int main()
{
cout << fixed << showpoint << setprecision(2);
fstream file;
ifstream ifile("Inventory.dat");
if (!ifile)
{
Date date;
date.Day = 1;
date.Month = 1;
date.Year = 1970;
Inventory rec = {"Default", 0, 0.0, 0.0, date};
file.open ("Inventory.dat", fstream::out | fstream::binary);
for (int count = 0; count < 10; count++)
{
file.write((char*)&rec,sizeof(rec));
}
cout << endl << "Warning, did not find file, so we created one.";
cout << endl;
file.close();
}
// Create Menu and run program
menu(file);
system("pause");
return 0;
}
Date dateValidation(string data){
Date date;
match_results<string::const_iterator> m;
regex re("([0-9]+)-([0-9]+)-([0-9]*)?");
if (regex_match(data, m, re)) {
date.Day = stoi(m[1].str()),
date.Month = stoi(m[2].str()),
date.Year = stoi(m[3].str());
}
else date.Year = 0000;
return date;
}
void menu(std::fstream& file)
{
int choice = 0;
bool success;
while(choice!= 4) {
cout << "Auto Zone Inventory" << endl;
cout << endl << "1. Add new records to the file" << endl;
cout << "2. Display any record in the file" << endl;
cout << "3. Change any record in the file" << endl;
cout << "4. Quit the program" << endl;
cout << endl;
cout << "Please enter your choice (1-4): ";
cin >> choice;
while (choice < 1 || choice > 4)
{
cout << endl << "Invalid entry. Please enter a number (1-4)" << endl;
cin >> choice;
}
cout << endl;
switch(choice){
case 1:
success = addRecord(file);
break;
case 2:
success = displayRecord(file);
break;
case 3:
success = changeRecord(file);
break;
case 4:
success = true;
cout << "Thank you for using this program. Auto Zone cares!" << endl;
break;
default :
cout << "Error " << choice << " is not a valid number";
break;
}
if (!success) cout << "File IO Error reading file!";
else {
system("Pause");
system("cls");
}
}
}
bool addRecord(std::fstream& file)
{
cout << "Please enter new record data" << endl;
Inventory rec;
string dateStr;
file.open ("Inventory.dat", fstream::out | fstream::app | fstream::binary);
cout << endl << "Item Description:" << endl;
cin.ignore();
cin.getline(rec.desc, DESC_SIZE);
cout << rec.desc << endl;
cout << endl << "Quantity on hand:" << endl;
cin >> rec.quantity;
while (rec.quantity < 0)
{
cout << endl << "Invalid entry. Please enter only positive values." << endl;
cin >> rec.quantity;
}
cout << endl << "Wholesale Cost" << endl;
cin >> rec.whlCost;
while (rec.whlCost < 0)
{
cout << endl << "Invalid entry. Please enter only positive values." << endl;
cin >> rec.whlCost;
}
cout << endl << "Retail Cost" << endl;
cin >> rec.rtlCost;
while (rec.rtlCost < 0)
{
cout << endl << "Invalid entry. Please enter only positive values." << endl;
cin >> rec.rtlCost;
}
bool loop = true;
while (loop){
cout << endl << "Date added to inventory (MM-DD-YYYY)" << endl;
cin.ignore();
cin >> dateStr;
rec.date = dateValidation(dateStr);
if (rec.date.Year != 0000) {
loop = false;
}
else
cout << endl << "Error Date Format is (MM-DD-YYYY)" <<endl;
}
file.write(reinterpret_cast<char *>(&rec),sizeof(rec));
cout << endl << "Record added to inventory" << endl;
file.close();
return true;
}
bool displayRecord(std::fstream& file)
{
Inventory rec;
file.open ("Inventory.dat", fstream::in | fstream::binary);
long num;
//Figure out How many records exist
long a = file.tellg();
file.seekg(0, fstream::end);
long b = file.tellg();
long sizeFile = b - a;
int c = sizeof(rec);
int numRecords = (sizeFile / c);
if (numRecords > 0){
cout << "Please enter the record you would like to view (1-"<< (numRecords) <<")" << endl;
cin >> num;
if ((num >= 0) && (num <= (numRecords))){
num = num -1;
file.seekg(num * sizeof(rec), fstream::beg);
file.read(reinterpret_cast<char *>(&rec), sizeof(rec));
if (!file.eof())
{
cout << endl << "Here is your current record:" << endl;
cout << endl << "Item Description: ";
cout << rec.desc << endl;
cout << "Quantity on hand: ";
cout << rec.quantity << endl;
cout << "Wholesale cost: ";
cout << rec.whlCost << endl;
cout << "Retail cost: ";
cout << rec.rtlCost << endl;
cout << "Date added to inventory: ";
cout << rec.date.Day << "-" << rec.date.Month << "-" << rec.date.Year << endl;
}
file.close();
}
else {
cout << "Record Outside of Database Range" << endl;
}
}
else {
cout << "No Records Found !" << endl;
return false;
}
return true;
}
bool changeRecord(std::fstream& file)
{
Inventory rec;
Inventory* recs;
string dateStr;
string yn;
char* buffer;
long num;
file.open ("Inventory.dat", fstream::in | fstream::out | fstream::binary);
//Figure out How many records exist
long a = file.tellg();
file.seekg(0, fstream::end);
long b = file.tellg();
long sizeFile = b - a;
int numRecords = 0;
if (sizeFile > 4){
int c = sizeof(rec);
numRecords = (sizeFile / c);
}
if (numRecords > 0){
cout << "Please enter the record you would like to view (1-"<< (numRecords) <<")" << endl;
cin >> num;
if (!file.eof()){
num = num -1;
file.seekg(num * sizeof(rec), fstream::beg);
file.read(reinterpret_cast<char *>(&rec), sizeof(rec));
cout << endl << "Here is your current record" << endl;
cout << endl << "Item description: ";
cout << rec.desc << endl;
cout << "Quantity on hand: ";
cout << rec.quantity << endl;
cout << "Wholesale cost: ";
cout << rec.whlCost << endl;
cout << "Retail cost: ";
cout << rec.rtlCost << endl;
cout << "Date added to inventory: ";
cout << rec.date.Day << "-" << rec.date.Month << "-" << rec.date.Year << endl;
}
cout << endl << "Do you want to proceed ? (Y/N)" << endl;
cin >> yn;
if ((yn == "Y")||(yn == "y")){
cout << endl << "Please enter your new data to the record"<< endl;
cout << endl << "Item description:" << endl;
cin.ignore();
cin.getline(rec.desc, DESC_SIZE);
cout << endl << "Quantity on hand:" << endl;
cin >> rec.quantity;
while (rec.quantity < 0)
{
cout << endl << "Invalid entry. Please enter only positive values." << endl;
cin >> rec.quantity;
}
cout << endl << "Wholesale cost:" << endl;
cin >> rec.whlCost;
while (rec.whlCost < 0)
{
cout << endl << "Invalid entry. Please enter only positive values." << endl;
cin >> rec.whlCost;
}
cout << endl << "Retail cost:" << endl;
cin >> rec.rtlCost;
while (rec.rtlCost < 0)
{
cout << endl << "Invalid entry. Please enter only positve values." << endl;
cin >> rec.rtlCost;
}
bool loop = true;
while (loop){
cout << endl << "Date added to inventory (MM-DD-YYYY)" << endl;
cin.ignore();
cin >> dateStr;
rec.date = dateValidation(dateStr);
if (rec.date.Year != 0000) {
loop = false;
}
else
cout << endl << "Error Date Format is (MM-DD-YYYY)" <<endl;
}
file.seekp(num * sizeof(rec), fstream::beg);
file.write(reinterpret_cast<char *>(&rec), sizeof(rec));
cout << endl << "The Record has been edited." << endl;
}
}
else cout << endl << "File contains no records!" << endl;
file.close();
return true;
}
#10
Re: Infinite loops in a file program
Posted 10 December 2012 - 01:50 PM
Remember, regex is for pattern matching, not for logic to tell if something is logically valid or not. That is 88/59/0987 is matched, but not logically valid. Probably why you are having a bit of trouble here.
#11
Re: Infinite loops in a file program
Posted 10 December 2012 - 01:52 PM
Well! A simple solution is, when setting your date you can check it, if it is valid assign it, if not, then reset it.
Example:
// where 1 denotes the default value to reset the date to // nDay is the input day date.day = (nDay >= 1 && nDay <= 31)? nDay : 1;
Hope this Helps!
#12
Re: Infinite loops in a file program
Posted 10 December 2012 - 02:03 PM
AKMafia001, on 10 December 2012 - 01:52 PM, said:
Well! A simple solution is, when setting your date you can check it, if it is valid assign it, if not, then reset it.
Example:
// where 1 denotes the default value to reset the date to // nDay is the input day date.day = (nDay >= 1 && nDay <= 31)? nDay : 1;
Hope this Helps!
Thanks for replying. This looks good, but where should I place it? Should it go in the dateValidation function? Or inside the while (loop) where the user can input its choice? Also, will I need to have an array for the months? Something like: {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} Or could I just create if / else statements for each of the months. I think I really did create a mess with the regular expression approach, but I want to keep going with it since the program works, and the fact that the assignment is due today.....
#13
Re: Infinite loops in a file program
Posted 10 December 2012 - 02:09 PM
Martyr2, on 10 December 2012 - 01:50 PM, said:
Remember, regex is for pattern matching, not for logic to tell if something is logically valid or not. That is 88/59/0987 is matched, but not logically valid. Probably why you are having a bit of trouble here.
Thanks for replying. No there really is no other reason other than the fact that the program works with it. I searched a long time online to find something that worked and that is all I could come up with. But I get what you are saying about pattern matching. I guess then is there a way I could then create the isLeapYear() function you suggested, and test each condition separately? If possible then, how can I get this function to work with the loop since I only have one argument for the user to send to the function?
#14
Re: Infinite loops in a file program
Posted 10 December 2012 - 03:02 PM
Jim
#15
Re: Infinite loops in a file program
Posted 10 December 2012 - 07:18 PM
|
|

New Topic/Question
Reply



MultiQuote




|