| | |
printing text file string contents (array) - padded characters
Please support our C++ advertiser: Programming Forums - DaniWeb Sister Site
![]() |
•
•
Join Date: May 2008
Posts: 96
Reputation:
Solved Threads: 0
I am not sure how to prevent the padded characters within a string array from printing. The user inputs the information in function enterRecords() and then prints in outputLine(ostream &output, const Tools &record ) function.
I am having issues with outputline when I try to print to screen and then use it to print to the text file.
My code is the following:
I am having issues with outputline when I try to print to screen and then use it to print to the text file.
My code is the following:
C++ Syntax (Toggle Plain Text)
// 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 < 20 ? 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::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; // 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: "; fflush(stdin); cin.getline( toolName, 20, '\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 ); // 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() { ifstream inTools( "hardware.dat", ios::in | ios::binary ); // exit program if ifstream cannot open file if ( !inTools ) { cerr << "File could not be opened." << endl; exit( 1 ); } // end if Tools tool; bool answer = false; if ( tool.getPartNumber() != 0 ) answer = true; else answer = false; 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 //menuChoice = 1; 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 outPrintFile << left << setw( 10 ) << "Tool Identification" << right << setw( 20 )<< "Tool Name" << setw( 11 ) << "Quantity" << right << setw( 10 ) << "Unit Price" << endl; // 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 ) { // obtain number of account to update int partNumber = getPart( "\nEnter tool part identification number to update: " ); // move file-position pointer to correct record in file updateFile.seekg( ( partNumber - 1 ) * sizeof ( Tools ) ); // read first record from file Tools tool; updateFile.read( reinterpret_cast < char * >( &tool ), sizeof( Tools ) ); // update record if ( tool.getPartNumber() != 0 ) { outputLine( cout, 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 << "\nEnter new unit price for the tool: "; double currentPrice; // change the unit price cin >> currentPrice; tool.setUnitPrice( currentPrice ); // update record outputLine( cout, tool ); // display the record // move file-position pointer to correct record in file updateFile.seekp( ( partNumber - 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( "Enter 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 << "\nEnter the tool name: "; fflush(stdin); cin.getline( toolName, 20, '\n' ); cout << "\nEnter 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; // 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 ) { cout << left << setw( 10 ) << record.getPartNumber() << setw( 16 ) << record.getToolName() << right << setw(9) << record.getInStock() << setw( 10 ) << setprecision(2) << right << fixed << showpoint << record.getUnitPrice() << endl; }
>>I am not sure how to prevent the padded characters within a string array from printing.
Post an example of such a string -- something like this perhaps:
Post an example of such a string -- something like this perhaps:
C++ Syntax (Toggle Plain Text)
" Hello World "
Don't PM me with questions -- you might get a nasty PM in response. If you have a question then post it in one of the forums.
•
•
Join Date: May 2008
Posts: 96
Reputation:
Solved Threads: 0
•
•
•
•
>>I am not sure how to prevent the padded characters within a string array from printing.
Post an example of such a string -- something like this perhaps:C++ Syntax (Toggle Plain Text)
" Hello World "
Not sure what you mean by this but below are the 2 functions and the screen print out for an example on how it is printing my array with the tool names.
Basically the characters ( ? padded characters) are coming out when the record prints.
Also for my first line / record, it is not aligning it like the rest of the records.
C++ Syntax (Toggle Plain Text)
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(10) << "Tool Id" << right << setw(10)<< " Tool Name" << right << setw(20) << "Quantity" << right << setw(20) << " Unit Price" << endl; // print header in the output prompt screen cout << left << setw(10) << "\nTool Id" << left << setw(15)<< " Tool Name" << right << setw(20) << "Quantity" << right << setw(16) << "Unit Price" << endl; // 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 }
C++ Syntax (Toggle Plain Text)
// display single record void Tools::outputLine(ostream &output, const Tools &record ) { output << left << setw(10 ) << 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( 16 ) << record.getToolName() << right << setw(12) << record.getInStock() << right<< setw(15) << setprecision(2) << fixed << showpoint << record.getUnitPrice() << endl; }
And this is what happens:
http://i24.photobucket.com/albums/c2...176/screen.jpg
Last edited by QuantNeeds; Jul 28th, 2008 at 9:52 pm.
•
•
Join Date: May 2008
Posts: 96
Reputation:
Solved Threads: 0
Ok - yep I have been working on it and I still have the same problems:
1) the way its reading in the strings and not clearing the past entries for the new inputs (just tags remaining at the end
2) prints the padded characters
3) for some reason my first record is not aligned
Attached is the screen shot and below is the code
1) the way its reading in the strings and not clearing the past entries for the new inputs (just tags remaining at the end
2) prints the padded characters
3) for some reason my first record is not aligned
Attached is the screen shot and below is the code
C++ Syntax (Toggle Plain Text)
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: "; fflush(stdin); cin.getline( toolName, 20, '\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 ); // 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 // display single record void Tools::outputLine(ostream &output, const Tools &record ) { output << left << setw(10 ) << 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( 16 ) << record.getToolName() << right << setw(12) << record.getInStock() << right<< setw(15) << setprecision(2) << fixed << showpoint << record.getUnitPrice() << endl; }
Last edited by QuantNeeds; Jul 28th, 2008 at 11:43 pm.
try clearing the string yourself before calling getline() and see if you still get the same results. I suspect it won't make any difference. That means the problem is something else in your program, such as something writing beyond the bounds of an array. If your program is still using that setToolName() function you posted earlier then that's the problem -- its not null-terminating the string. strncpy() doesn't null-terminate the string if the source string is longer than the destination buffer.
Don't PM me with questions -- you might get a nasty PM in response. If you have a question then post it in one of the forums.
![]() |
Other Threads in the C++ Forum
- Previous Thread: Reversing the words alone in a program
- Next Thread: GUI: 3 C:\Dev-Cpp\lolLOLlol.cpp expected `,' or `;' before numeric constant
Views: 2181 | Replies: 5
| Thread Tools | Search this Thread |
Tag cloud for C++
6 add api array arrays beginner binary bitmap c++ c/c++ calculator char class classes code compile compiler console conversion convert count data delete desktop directshow dll encryption error file forms fstream function functions game getline givemetehcodez google graph homeworkhelper iamthwee ifstream input int integer java lazy lib linkedlist linux loop looping loops map math matrix memory microsoft newbie news node number output parameter pointer problem program programming project proxy python random read recursion recursive reference return sort string strings struct studio system template templates test text tree unix url variable vector video visual visualstudio win32 windows winsock word wordfrequency wxwidgets






