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:

// 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:

"        Hello    World   "

>>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:

"        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.

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
}
// 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:
[IMG]http://i24.photobucket.com/albums/c27/moons176/screen.jpg[/IMG]

IMG tags don't work here. Hit the Advanced button, scroll down, then select the Manage Attachments. That will let you load an image file to your post.

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

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;
}

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.

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