Hello,
Finally I am down to the last issue with my program: text file writing and reading.
My file has a function whose ofstream object does work and produces a text file for printing called "print".
This function is the printTextFile(fstream &readFromFile ) function.
But initially it is supposed to be creating a file called "hardware"where I store the records, update the records, add a new record, or delete. Well it seems that the fstream objects here are not working because when I search my file for hardware I cannot find it. I am trying to summarize my functions below with their objects and then including my main() and as well the functions and the function definitions.
createAndInitializeTextFile() - ofstream object that writes
enterRecords() - fstream object that I use to seek records with seekp and then also use to write
processChoice() has the fstream object with hardware.dat that is passed the following functions:
void printTextFile(fstream&);
void updateRecord(fstream&);
void newRecord( fstream& );
void deleteRecord( fstream& );
void outputLine( ostream&, const Tools & );
My code in main() :
int main()
{
Tools tool;
tool.createAndInitializeTextFile();
tool.enterRecords();
if(tool.test())
{
cout << "\nHardware program successful.\n";
tool.processChoice();
}
else
{
cout <<"\nHardware program failed.\n";
}
cout << endl;
return 0;
}
My member function definitions:
void Tools::createAndInitializeTextFile()
{
ofstream outTools( "hardware.dat", ios::out | ios::binary );
// exit program if ofstream could not open file
if ( !outTools )
{
cerr << "File could not be opened." << endl;
exit( 1 );
}
Tools blankTool(0); // constructor zeros out each data member
// output 100 blank records to file
for ( int i = 0; i < 100; i++ )
outTools.write( reinterpret_cast < const char * >( &blankTool ), sizeof ( Tools ) );
}
void Tools::enterRecords()
{
fstream outTools( "hardware.dat", ios::in | ios::out | ios::binary );
// exit program if fstream cannot open file
if ( !outTools )
{
cerr << "File could not be opened." << endl;
exit( 1 );
} // end if
// require user to specify a tool identification number
cout << "Enter tool identification number (1 to 100, 0 to end input): ";
cin >> partNumber;
Tools tool; // create the object
// user enters information, which is copied into file
while (partNumber != 0)
{
validatePartNumber(partNumber);
// user enters tool name, quantity and unit price
cout << "Enter the tool name: ";
cin.ignore();
cin.getline(toolName, sizeof(toolName));
cout << "Enter the quantity in stock: ";
cin >> inStock;
cout << "Enter the unit price: ";
cin >> unitPrice;
// set the record for the part number, tool name, quantity in stock, and unit price
tool.setPartNumber( partNumber );
tool.setToolName( toolName );
tool.setInStock( inStock );
tool.setUnitPrice( unitPrice );
// seek position in file of user-specified record
outTools.seekp( ( tool.getPartNumber() - 1 ) * sizeof ( Tools ) );
// write user-specified information in file
outTools.write( reinterpret_cast < const char * >( &tool ), sizeof ( Tools) );
//enable user to enter another account
cout << "\nEnter tool identification number (1 to 100, 0 to end input): ";
cin >> partNumber;
} // end while loop
} // end enterRecords function
bool Tools::test()
{
Tools tool;
bool answer = false;
ifstream inTools( "hardware.dat", ios::in | ios::binary );
// exit program if ifstream cannot open file
if ( !inTools )
{
answer = false;
cerr << "File could not be opened." << endl;
exit( 1 );
} // end if
else
{
answer = true;
}
return answer;
}
void Tools::processChoice()
{
// open file for reading and writing
fstream inOutTools( "hardware.dat", ios::in | ios::out | ios::binary );
// exit program if fstream cannot open file
if ( !inOutTools )
{
cerr << "File could not be opened." << endl;
exit ( 1 );
} // end if
int choice; // store user choice
// enable user to specify action
while ( ( choice = enterChoice() ) != END )
{
switch ( choice )
{
case PRINT: // create text file from record file
printTextFile( inOutTools );
break;
case UPDATE: // update record
updateRecord( inOutTools );
break;
case NEW: // create record
newRecord( inOutTools );
break;
case DELETE: // delete existing record
deleteRecord( inOutTools );
break;
default: // display error if user does not select valid choice
cerr << "Incorrect choice" << endl;
break;
} // end switch
inOutTools.clear(); // reset end-of-file indicator
} // end while
} // end function
// enable user to input menu choice
int Tools::enterChoice()
{
// display available options
cout << "\nEnter your choice:" << endl
<< "1 - store a formatted text file of accounts - called \"print.txt\" for printing." << endl
<< "2 - update an account" << endl
<< "3 - add a new account" << endl
<< "4 - delete an account" << endl
<< "5 - end program\n? ";
int menuChoice;
cin >> menuChoice; // input menu selection from user
return menuChoice;
}
// create formatted text file for printing
void Tools::printTextFile(fstream &readFromFile )
{
// create text file
ofstream outPrintFile( "print.txt", ios::out );
// exit program if ofstream cannot create file
if ( !outPrintFile )
{
cerr << "File could not be created." << endl;
exit( 1 );
} // end if
// print header in the test file (formatted this way to easily view)
outPrintFile << left << setw(9) << "Tool Id"
<< right << setw(11)<< " Tool Name"
<< right << setw(20) << "Quantity"
<< right << setw(15) << " Unit Price" << endl;
// print header in the output prompt screen
printHeader();
// set file-position pointer to beginning of readFromFile
readFromFile.seekg( 0 );
// read first record from record file
Tools tool;
readFromFile.read( reinterpret_cast < char * >( &tool ),
sizeof ( Tools ) );
// copy all records from record file into text file
while ( !readFromFile.eof() )
{
// write single record to text file
if ( tool.getPartNumber() != 0 ) // skip empty records
outputLine( outPrintFile, tool );
// read next record from record file
readFromFile.read( reinterpret_cast < char * >( &tool),
sizeof ( Tools ) );
} // end while
}
// update the new quantity and unit price in the record
void Tools::updateRecord( fstream &updateFile )
{
Tools tool;
// obtain number of account to update
partNumber = getPart( "\nEnter tool part identification number to update: " );
tool.setPartNumber( partNumber );
// move file-position pointer to correct record in file
updateFile.seekg( ( partNumber - 1 ) * sizeof ( Tools ) );
// read first record from file
updateFile.read( reinterpret_cast < char * >( &tool ),
sizeof( Tools ) );
// update record
if ( tool.getPartNumber() != 0 )
{
printHeader();
outputLine( updateFile, tool ); // display the record
cout << "\nEnter new current quantity: ";
int currentQuantity;
cin >> currentQuantity;
tool.setInStock( currentQuantity );
// request user enter a new unit price
cout << "Enter new unit price for the tool: ";
double currentPrice; // change the unit price
cin >> currentPrice;
tool.setUnitPrice( currentPrice );
cout << "\nPart # " << partNumber << " has been updated.\n";
printHeader();
outputLine( updateFile, tool ); // display the record
tool.setPartNumber( partNumber );
tool.setToolName( toolName );
tool.setInStock( inStock );
tool.setUnitPrice( unitPrice );
// move file-position pointer to correct record in file
updateFile.seekp( ( partNumber - 1 ) * sizeof( Tools ) );
// insert record in file
updateFile.write( reinterpret_cast < const char * >( &tool ),
sizeof( Tools ) );
} // end if
else // display error if account does not exist
cerr << "\nPart identification # " << partNumber << " has no information." << endl;
} // end function updateRecord
// create and insert record
void Tools::newRecord( fstream &insertInFile )
{
// obtain number of account to create
int partNumber = getPart( "\nEnter new part number: " );
validatePartNumber(partNumber);
// move file-position pointer to correct record in file
insertInFile.seekg( ( partNumber - 1 ) * sizeof( Tools ) );
// read record from file
Tools tool;
insertInFile.read( reinterpret_cast < char * >( &tool ),
sizeof( Tools ) );
// create record, if record does not previously exist
if ( tool.getPartNumber() == 0 )
{
// user enters tool name, quantity and unit price
cout << "Enter the tool name: ";
fflush(stdin);
cin.getline( toolName, size, '\n' );
cout << "Enter the quantity in stock: ";
cin >> inStock;
cout << "Enter the unit price: ";
cin >> unitPrice;
// set the record for the part number, tool name, quantity in stock, and unit price
tool.setPartNumber( partNumber );
tool.setToolName( toolName );
tool.setInStock( inStock );
tool.setUnitPrice( unitPrice );
// move file-position pointer to correct record in file
insertInFile.seekp( ( partNumber - 1 ) * sizeof( Tools ) );
// insert record in file
insertInFile.write( reinterpret_cast < const char * >( &tool ),
sizeof( Tools ) );
} // end if
else // display error if account already exists
cerr << "\n\nPart # " << partNumber << " already contains information." << endl;
} // end function newRecord
// delete an existing record
void Tools::deleteRecord( fstream &deleteFromFile )
{
// obtain number of account to delete
int partNumber = getPart( "Enter the tool to delete: " );
// move file-position pointer to correct record in file
deleteFromFile.seekg( ( partNumber - 1 ) * sizeof( Tools ) );
// read record from file
Tools tool;
deleteFromFile.read( reinterpret_cast < char * >( &tool ),
sizeof( Tools ) );
// delete record, if record exists in file
if ( tool.getPartNumber() != 0 )
{
Tools blankTool(0); // create blank record
// move file-position pointer to correct record in file
deleteFromFile.seekp( ( partNumber - 1 ) *
sizeof( Tools ) );
// replace existing record with blank record
deleteFromFile.write(
reinterpret_cast < const char * >( &blankTool ),
sizeof( Tools ) );
cout << "\nPart # " << partNumber << " deleted.\n";
} // end if
else // display error if record does not exist
cerr << "\nPart # " << partNumber << " is empty.\n";
} // end deleteRecord
// display single record
void Tools::outputLine(ostream &output, const Tools &record )
{
output << left << setw(11 ) << record.getPartNumber()
<< setw(16) << record.getToolName()
<< right << setw(9) << record.getInStock()
<< right << setw(15) << setprecision(2) << fixed << showpoint << record.getUnitPrice() << endl;
cout << left << setw(10) << record.getPartNumber()
<< setw(18) << record.getToolName()
<< right << setw(5) << record.getInStock()
<< right << setw(15) << setprecision(2) << fixed << showpoint << record.getUnitPrice() << endl;
}Well, it seems you have a problem. This is not enough: what and where is a problem?..
I can't find my hardware.dat file on the computer and also the write in the updateRecord() function does not work.
>>I can't find my hardware.dat file on the compute
It will be in the same directory that contains the program *.exe file.
>>the write in the updateRecord() function does not work.
what makes you think it doesn't work? What does it do that it's not supposed to do, or what doesn't it do that its supposed to do ? Just by looking at the function it appears to be working right, but since we don't have all the code for the entire program its not possible for us to test it.
>>I can't find my hardware.dat file on the compute It will be in the same directory that contains the program *.exe file.
>>the write in the updateRecord() function does not work. what makes you think it doesn't work? What does it do that it's not supposed to do, or what doesn't it do that its supposed to do ? Just by looking at the function it appears to be working right, but since we don't have all the code for the entire program its not possible for us to test it.
Basically I typed in the input and then hit 1 to print the file. I can find the print.dat file but I cannot find the hardware.dat.
Basically I try to make a change and then hit 1 again and when I go back to check the print.dat it shows it in the output screen but then hit 1 again and there is no change, the change also does NOT occur in the print.dat. So when I could not find the hardware.dat this makes me think that I am not recording there to begin with.
All of my code is below:
header:
class Tools
{
public:
Tools(int = -1, string = "", int = 0, double = 0.0); // default tools constructor
// accessor functions for partNumber, toolName, inStock, unitPrice
void setPartNumber(int);
int getPartNumber() const;
void validatePartNumber(int);
void setToolName(string);
string getToolName() const;
void setInStock(int);
int getInStock() const;
void setUnitPrice(double);
double getUnitPrice() const;
void createAndInitializeTextFile();
void enterRecords();
bool test();
void printHeader();
void processChoice();
int enterChoice();
void printTextFile(fstream&);
void updateRecord(fstream&);
void newRecord( fstream& );
void deleteRecord( fstream& );
void outputLine( ostream&, const Tools & );
int getPart( const char * const );
private:
static const int size = 20;
enum Choices { PRINT = 1, UPDATE, NEW, DELETE, END };
int partNumber; // part id number (tool identifitcation number) is the record number (record key)
char toolName[20]; // tool name
int inStock; // in stock
double unitPrice; // price per unit
}; // end class Tools
member functions:
// default Tools constructor
Tools::Tools( int partNumberValue,string toolNameValue, int inStockValue, double unitPriceValue)
{
setPartNumber( partNumberValue);
setToolName( toolNameValue );
setInStock( inStockValue);
setUnitPrice( unitPriceValue );
} // end Tools constructor
// get tool identification number
int Tools::getPartNumber() const
{
return partNumber;
}
// set tool identification numbers
void Tools::setPartNumber( int partNumberValue)
{
partNumber = partNumberValue;
}
void Tools::validatePartNumber(int checkPart)
{
if(checkPart > 0 && checkPart <= 100)
partNumber = checkPart;
else
{
bool flag = false;
while(flag == false)
{
cout << "Part number is a record, an integer within range 1 to 100.";
cout << "\nRe-enter tool identification number (1 to 100, 0 to end input)\n? ";
cin >> checkPart;
if(checkPart > 0 && checkPart <= 100)
{
partNumber = checkPart;
flag = true;
}
} // end while loop
} // end if
} // end function
// get tool name
string Tools::getToolName() const
{
return toolName;
}
// set the tool name
void Tools::setToolName(string toolNameString)
{
// copy at most 20 characters for the tool name
const char *toolNameValue = toolNameString.data();
int length = int(toolNameString.size());
length = (length < size ? length : 19);
strncpy(toolName, toolNameValue, length);
toolName[ length ] = '\0'; // append null character to lastName
}
// get in-stock quantity for the tool
int Tools::getInStock() const
{
return inStock;
}
// set in-stock quantity for the tool
void Tools::setInStock( int inStockValue)
{
inStock= inStockValue;
}
// get unit price for each tool
double Tools::getUnitPrice() const
{
return unitPrice;
}
// set unit price for each tool
void Tools::setUnitPrice( double unitPriceValue )
{
unitPrice = unitPriceValue;
}
void Tools::printHeader()
{
cout << left << setw(10) << "\nTool Id"
<< left << setw(17)<< " Tool Name"
<< right << setw(12) << "Quantity"
<< right << setw(15) << "Unit Price" << endl;
cout << "------- ----------- -------- ----------" << endl;
}
void Tools::createAndInitializeTextFile()
{
ofstream outTools( "hardware.dat", ios::out | ios::binary );
// exit program if ofstream could not open file
if ( !outTools )
{
cerr << "File could not be opened." << endl;
exit( 1 );
}
Tools blankTool(0); // constructor zeros out each data member
// output 100 blank records to file
for ( int i = 0; i < 100; i++ )
outTools.write( reinterpret_cast < const char * >( &blankTool ), sizeof ( Tools ) );
}
void Tools::enterRecords()
{
fstream outTools( "hardware.dat", ios::in | ios::out | ios::binary );
// exit program if fstream cannot open file
if ( !outTools )
{
cerr << "File could not be opened." << endl;
exit( 1 );
} // end if
// require user to specify a tool identification number
cout << "Enter tool identification number (1 to 100, 0 to end input): ";
cin >> partNumber;
Tools tool; // create the object
// user enters information, which is copied into file
while (partNumber != 0)
{
validatePartNumber(partNumber);
// user enters tool name, quantity and unit price
cout << "Enter the tool name: ";
cin.ignore();
cin.getline(toolName, sizeof(toolName));
cout << "Enter the quantity in stock: ";
cin >> inStock;
cout << "Enter the unit price: ";
cin >> unitPrice;
// set the record for the part number, tool name, quantity in stock, and unit price
tool.setPartNumber( partNumber );
tool.setToolName( toolName );
tool.setInStock( inStock );
tool.setUnitPrice( unitPrice );
// seek position in file of user-specified record
outTools.seekp( ( tool.getPartNumber() - 1 ) * sizeof ( Tools ) );
// write user-specified information in file
outTools.write( reinterpret_cast < const char * >( &tool ), sizeof ( Tools) );
//enable user to enter another account
cout << "\nEnter tool identification number (1 to 100, 0 to end input): ";
cin >> partNumber;
} // end while loop
} // end enterRecords function
bool Tools::test()
{
Tools tool;
bool answer = false;
ifstream inTools( "hardware.dat", ios::in | ios::binary );
// exit program if ifstream cannot open file
if ( !inTools )
{
answer = false;
cerr << "File could not be opened." << endl;
exit( 1 );
} // end if
else
{
answer = true;
}
return answer;
}
void Tools::processChoice()
{
// open file for reading and writing
fstream inOutTools( "hardware.dat", ios::in | ios::out | ios::binary );
// exit program if fstream cannot open file
if ( !inOutTools )
{
cerr << "File could not be opened." << endl;
exit ( 1 );
} // end if
int choice; // store user choice
// enable user to specify action
while ( ( choice = enterChoice() ) != END )
{
switch ( choice )
{
case PRINT: // create text file from record file
printTextFile( inOutTools );
break;
case UPDATE: // update record
updateRecord( inOutTools );
break;
case NEW: // create record
newRecord( inOutTools );
break;
case DELETE: // delete existing record
deleteRecord( inOutTools );
break;
default: // display error if user does not select valid choice
cerr << "Incorrect choice" << endl;
break;
} // end switch
inOutTools.clear(); // reset end-of-file indicator
} // end while
}
// enable user to input menu choice
int Tools::enterChoice()
{
// display available options
cout << "\nEnter your choice:" << endl
<< "1 - store a formatted text file of accounts - called \"print.txt\" for printing." << endl
<< "2 - update an account" << endl
<< "3 - add a new account" << endl
<< "4 - delete an account" << endl
<< "5 - end program\n? ";
int menuChoice;
cin >> menuChoice; // input menu selection from user
return menuChoice;
}
// create formatted text file for printing
void Tools::printTextFile(fstream &readFromFile )
{
// create text file
ofstream outPrintFile( "print.txt", ios::out );
// exit program if ofstream cannot create file
if ( !outPrintFile )
{
cerr << "File could not be created." << endl;
exit( 1 );
} // end if
// print header in the test file (formatted this way to easily view)
outPrintFile << left << setw(9) << "Tool Id"
<< right << setw(11)<< " Tool Name"
<< right << setw(20) << "Quantity"
<< right << setw(15) << " Unit Price" << endl;
// print header in the output prompt screen
printHeader();
// set file-position pointer to beginning of readFromFile
readFromFile.seekg( 0 );
// read first record from record file
Tools tool;
readFromFile.read( reinterpret_cast < char * >( &tool ),
sizeof ( Tools ) );
// copy all records from record file into text file
while ( !readFromFile.eof() )
{
// write single record to text file
if ( tool.getPartNumber() != 0 ) // skip empty records
outputLine( outPrintFile, tool );
// read next record from record file
readFromFile.read( reinterpret_cast < char * >( &tool),
sizeof ( Tools ) );
} // end while
}
// update the new quantity and unit price in the record
void Tools::updateRecord( fstream &updateFile )
{
Tools tool;
// obtain number of account to update
partNumber = getPart( "\nEnter tool part identification number to update: " );
tool.setPartNumber( partNumber );
// move file-position pointer to correct record in file
updateFile.seekg( ( partNumber - 1 ) * sizeof ( Tools ) );
// read first record from file
updateFile.read( reinterpret_cast < char * >( &tool ),
sizeof( Tools ) );
// update record
if ( tool.getPartNumber() != 0 )
{
printHeader();
outputLine( updateFile, tool ); // display the record
// request user to specify new quantity
cout << "\nEnter new current quantity: ";
int currentQuantity; // change the quantity
cin >> currentQuantity;
tool.setInStock( currentQuantity ); // update record
// request user enter a new unit price
cout << "Enter new unit price for the tool: ";
double currentPrice; // change the unit price
cin >> currentPrice;
tool.setUnitPrice( currentPrice ); // update record
cout << "\nPart # " << partNumber << " has been updated.\n";
// print header in the output prompt screen
printHeader();
outputLine( updateFile, tool ); // display the record
// set the record for the part number, tool name, quantity in stock, and unit price
tool.setPartNumber( partNumber );
tool.setToolName( toolName );
tool.setInStock( inStock );
tool.setUnitPrice( unitPrice );
// move file-position pointer to correct record in file
updateFile.seekp( ( partNumber - 1 ) * sizeof( Tools ) );
// insert record in file
updateFile.write( reinterpret_cast < const char * >( &tool ),
sizeof( Tools ) );
//// move file-position pointer to correct record in file
//updateFile.seekp( ( tool.getPartNumber() - 1 ) * sizeof ( Tools ) );
//// write updated record over old record in file
//updateFile.write( reinterpret_cast < const char * >( &tool ),sizeof ( Tools) );
} // end if
else // display error if account does not exist
cerr << "\nPart identification # " << partNumber << " has no information." << endl;
} // end function updateRecord
// create and insert record
void Tools::newRecord( fstream &insertInFile )
{
// obtain number of account to create
int partNumber = getPart( "\nEnter new part number: " );
validatePartNumber(partNumber);
// move file-position pointer to correct record in file
insertInFile.seekg( ( partNumber - 1 ) * sizeof( Tools ) );
// read record from file
Tools tool;
insertInFile.read( reinterpret_cast < char * >( &tool ),
sizeof( Tools ) );
// create record, if record does not previously exist
if ( tool.getPartNumber() == 0 )
{
// user enters tool name, quantity and unit price
cout << "Enter the tool name: ";
fflush(stdin);
cin.getline( toolName, size, '\n' );
cout << "Enter the quantity in stock: ";
cin >> inStock;
cout << "Enter the unit price: ";
cin >> unitPrice;
// set the record for the part number, tool name, quantity in stock, and unit price
tool.setPartNumber( partNumber );
tool.setToolName( toolName );
tool.setInStock( inStock );
tool.setUnitPrice( unitPrice );
// move file-position pointer to correct record in file
insertInFile.seekp( ( partNumber - 1 ) * sizeof( Tools ) );
// insert record in file
insertInFile.write( reinterpret_cast < const char * >( &tool ),
sizeof( Tools ) );
} // end if
else // display error if account already exists
cerr << "\n\nPart # " << partNumber << " already contains information." << endl;
} // end function newRecord
// delete an existing record
void Tools::deleteRecord( fstream &deleteFromFile )
{
// obtain number of account to delete
int partNumber = getPart( "Enter the tool to delete: " );
// move file-position pointer to correct record in file
deleteFromFile.seekg( ( partNumber - 1 ) * sizeof( Tools ) );
// read record from file
Tools tool;
deleteFromFile.read( reinterpret_cast < char * >( &tool ),
sizeof( Tools ) );
// delete record, if record exists in file
if ( tool.getPartNumber() != 0 )
{
Tools blankTool(0); // create blank record
// move file-position pointer to correct record in file
deleteFromFile.seekp( ( partNumber - 1 ) *
sizeof( Tools ) );
// replace existing record with blank record
deleteFromFile.write(
reinterpret_cast < const char * >( &blankTool ),
sizeof( Tools ) );
cout << "\nPart # " << partNumber << " deleted.\n";
} // end if
else // display error if record does not exist
cerr << "\nPart # " << partNumber << " is empty.\n";
} // end deleteRecord
// display single record
void Tools::outputLine(ostream &output, const Tools &record )
{
output << left << setw(11 ) << record.getPartNumber()
<< setw(16) << record.getToolName()
<< right << setw(9) << record.getInStock()
<< right << setw(15) << setprecision(2) << fixed << showpoint << record.getUnitPrice() << endl;
cout << left << setw(10) << record.getPartNumber()
<< setw(18) << record.getToolName()
<< right << setw(5) << record.getInStock()
<< right << setw(15) << setprecision(2) << fixed << showpoint << record.getUnitPrice() << endl;
}
// obtain account-number value from user
int Tools::getPart( const char * const prompt )
{
int partNumber;
// obtain part identification number value
do
{
cout << prompt << " (1 - 100): ";
cin >> partNumber;
} while ( partNumber < 1 || partNumber > 100 );
return partNumber;
}
main() :
int main()
{
Tools tool;
tool.createAndInitializeTextFile();
tool.enterRecords();
if(tool.test())
{
cout << "\nHardware program successful.\n";
tool.processChoice();
}
else
{
cout <<"\nHardware program failed.\n";
}
cout << endl;
return 0;
}You apparently didn't get a clean compile with the code you posed because it contains several errors. One error is function outputLine() -- One place passes fstream object as the first parameter while another passes ofstream. If I leave it as ostream like you have it then the function has millions of errors. My suggestion is to NOT use ofstream, but use fstream everywhere so that your program is consistent.