I am reposting this with all of the code this time. I would appreciate not closing the post for at least a little while. I am obviously no expert and I have never run into anything like this before but I do think it can be useful to other members. I tried the comments and agree the error is with destruction but can't find where. I have included the location of the seg fault in comment towards the bottom. I don't have an IDE and don't know how to use the debugger surely built into xterm so I am at a loss!!
#include <iostream>
#include <fstream>
#include <string>
#include "File.h"
using namespace std;
string promptQuit()
{
string userMode;
cout
<<
"Would you like to [q]uit? Enter any other key to continue."
<<
endl;
cin >> userMode;
cin.clear();
cin.ignore( 1000,'\n' );
return userMode;
}
int main()
{
/**************************************************************************/
/* Variable Declarations and Initializations */
/**************************************************************************/
char fileName[256];
char destinationFile[256];
string userMode;
/**************************************************************************/
/* Begin prompting user for what they want to do, starting with */
/* the filename, then what they want to do with the file. Once the user */
/* finishes with a particular file, they may continue with another file. */
/* Therefore, this loop terminates only when the user asks to quit */
/**************************************************************************/
while( userMode != "q" )
{
cout
<<
"Welcome to the file handling system. Please type the name of the "
"file that you wish to read from, write to, or modify followed by "
"the <return> key:"
<<
endl;
cin.getline( fileName, 256 );
File thisFile( fileName );
cout
<<
"Current File: " << thisFile.getFileName() << "\nWhat would you "
"like to do?\n[r]ead, [w]rite, [m]odify, or [q]uit"
<<
endl;
cin >> userMode;
// Invalid entry handling: Reset the failure bit and skip past the
// invalid input in the stream, then notify and re-prompt the user for
// valid input
while( !( (userMode == "w") | (userMode == "r") | (userMode == "q") |
(userMode == "m" ) ) )
{
cout
<<
"Invalid entry, please try again\nWhat would you like to do?\n"
"[r]ead, [w]rite, [m]odify, or [q]uit"
<<
endl;
cin >> userMode;
cin.clear();
cin.ignore( 1000, '\n' );
}
/*********************************************************************/
/* Write Mode: The user is prompted to enter one number at a time */
/* and this number is written to the chosen file. If the user enters*/
/* an invalid number, such as a letter, the user is notified and */
/* prompted to enter a valid real number */
开发者_运维技巧 /*********************************************************************/
if( userMode == "w" )
thisFile.writeTo();
/*********************************************************************/
/* Read Mode: The user reads in the entire contents from the file */
/* they have chosen */
/*********************************************************************/
if( userMode == "r" )
thisFile.readFrom();
/*********************************************************************/
/* Modify Mode: The user may either leave the old file unmodified and*/
/* place the modified contents into a new file or actually modify the*/
/* original file. */
/* The user reads in one line from the file at a time and can either */
/* choose to accept this number, replace it, delete it, or accept it */
/* and insert one or more numbers after it. At any time the user may*/
/* also choose to accept the remainder of the numbers in the file */
/*********************************************************************/
if( userMode == "m" )
{
cout
<<
"Do you want to modify the original file?\n[y]es/[n]o?"
<<
endl;
string modify;
cin >> modify;
while( !( ( modify == "y" ) | ( modify == "n" ) ) )
{
cout
<<
"Invalid entry, please try again\nDo you want to modify "
"the original file?\n[y]es/[n]o?"
<<
endl;
cin >> userMode;
cin.clear();
cin.ignore( 1000, '\n' );
}
if( modify == "y" )
{
File tempFile;
thisFile.modify( &tempFile );
}
if( modify == "n" )
{
cout
<<
"Please type the name of the destination file followed by "
"the <return> key:"
<<
endl;
cin.getline( destinationFile, 256 );
File newFile( destinationFile );
thisFile.modify( &newFile );
/****************************************************************/
/****Seg fault occurs here. Never exits this IF but above*******/
/*function does return.Doesn't get past close curly brace********/
/****************************************************************/
}
}
userMode = promptQuit();
}
return 0;
}
Here is the .cpp file
#include <fstream>
#include <iostream>
#include <sstream>
#include <stdlib.h>
#include <string>
#include <math.h>
#include <iomanip>
#include "File.h"
using namespace std;
// Returns ordinal number from input integer num, e.g., 1st for 1
string ordinalString( const int num )
{
stringstream numeric;
numeric << num;
string ordinalUnit;
string ordinal = numeric.str();
switch( num%10 )
{
case 1: ordinalUnit = "st"; break;
case 2: ordinalUnit = "nd"; break;
case 3: ordinalUnit = "rd"; break;
default: ordinalUnit = "th"; break;
}
switch( num )
{
case 11: ordinalUnit = "th"; break;
case 12: ordinalUnit = "th"; break;
case 13: ordinalUnit = "th"; break;
}
ordinal += ordinalUnit;
return ordinal;
}
float promptRealNumber()
{
float validEntry;
// Invalid entry handling: Reset the failure bit and skip past the
// invalid input in the stream, then notify and re-prompt the user for
// valid input
while ( !(cin >> validEntry) )
{
cout << "Invalid Input: Entry must be a real number. Please try again:";
cin.clear();
cin.ignore( 1000, '\n' );
}
return validEntry;
}
File::File()
{
fileName = "temp.txt";
entries = 0;
}
File::File( const char * file_name )
{
entries = 0;
string currentLine;
fileName = file_name;
ifstream thisFile( file_name );
if ( thisFile.is_open() )
{
while ( !thisFile.eof() )
{
getline ( thisFile, currentLine );
entries++;
}
thisFile.close();
}
else
cout << "Error opening file. File may not exist." << endl;
entries--;
}
File::File( const File * copyFile )
{
fileName = copyFile->fileName;
entries = copyFile->entries;
}
void File::promptNumEntries()
{
cout
<<
"Please enter the number of entries you wish to input into "
<< fileName << " followed by the '<return>' key"
<<
endl;
// Invalid entry handling: Reset the failure bit and skip past the invalid
// input in the stream, then notify and re-prompt the user for valid input
while ( !(cin >> entries) || ( floor( entries ) != entries ) )
{
cout << "Invalid Input: Entry must be an integer. Please try again: ";
cin.clear();
cin.ignore ( 1000, '\n' );
}
}
void File::readFrom()
{
string currentLine;
ifstream inFile( fileName.c_str() );
if ( inFile.is_open() )
{
while ( inFile.good() )
{
getline ( inFile, currentLine );
cout << currentLine << endl;
}
inFile.close();
}
else
cout << "Error opening file. File may not exist." << endl;
}
void File::writeTo()
{
ofstream outFile( fileName.c_str() );
string ending;
promptNumEntries();
for( int entry = 1; entry <= entries; entry++ )
{
// Notify the user which entry they are currently entering so if they lose
// their place, they can easily find which number they should be entering.
cout
<<
"Please enter the " << ordinalString( entry ) << " number followed "
"by the <return> key"
<<
endl;
float entryNum = promptRealNumber();
outFile << fixed << setprecision(1) << entryNum << endl;
}
outFile.close();
}
void File::modify( const File * destination_file )
{
ifstream sourceFile( fileName.c_str() );
ofstream destinationFile( destination_file->fileName.c_str() );
string currentLine;
string entryAction;
string insertMore = "y";
float replacementEntry;
float insertEntry;
int entry = 0;
if ( sourceFile.is_open() )
{
while ( !sourceFile.eof() )
{
getline( sourceFile, currentLine );
cout
<<
currentLine << endl << "Do you want to [k]eep this entry, "
"[r]eplace it, [d]elete it, [i]nsert after it, or accept this "
"and [a]ll remaining entries?"
<<
endl;
cin >> entryAction;
// Keep current entry. Also called when inserting an entry since
// this also requires keeping the current entry
if( ( entryAction == "k" ) | ( entryAction == "i" ) )
destinationFile << currentLine << endl;
// Replace current entry
if( entryAction == "r" )
{
cout
<<
"Please type the new entry followed by the <return> key:"
<<
endl;
replacementEntry = promptRealNumber();
destinationFile
<<
fixed << setprecision(1) << replacementEntry
<<
endl;
}
// Deleting the current entry amounts to simply ignoring it and
// continuing to the next entry, if it exists
if( entryAction == "d" );
// Insert one or more entries after current entry
if( entryAction == "i" )
{
while( insertMore == "y" )
{
cout
<<
"Please type the entry to be inserted followed by the "
"<return> key:"
<<
endl;
insertEntry = promptRealNumber();
destinationFile
<<
fixed << setprecision(1) << insertEntry
<<
endl;
cout << "Insert another number?\n[y]es/[n]o?" << endl;
cin >> insertMore;
while( !( (insertMore == "y") | (insertMore == "n" ) ) )
{
cout
<<
"Invalid entry, please try again\nInsert another "
"number?\n[y]es/[n]o?"
<<
endl;
cin >> insertMore;
cin.clear();
cin.ignore( 1000, '\n' );
}
}
}
// Accept all remaining entries
if( entryAction == "a" )
{
destinationFile << currentLine << endl;
while ( entry < entries )
{
getline ( sourceFile, currentLine );
destinationFile << currentLine << endl;
entry++;
}
}
destinationFile.close();
sourceFile.close();
}
}
else
cout << "Error opening file. File may not exist." << endl;
}
void File::copyFileContents( const File * to, const File * from )
{
ifstream fromFile( to->fileName.c_str() );
ofstream toFile( from->fileName.c_str() );
string currentLine;
while( !fromFile.fail() && !toFile.fail() )
{
for( int line = 0; line < from->entries; line++ )
{
getline( fromFile, currentLine );
toFile << currentLine;
}
}
}
Here is the .h file
#include <string>
using namespace std;
class File
{
public:
File();
File( const char * );
File( const File * copyFile );
~File() { delete this; }
string getFileName() { return fileName; }
float numEntries() { return entries; }
void setNumEntries( const float numEntries ) { entries = numEntries; }
void promptNumEntries();
void readFrom();
void writeTo();
void modify( const File * );
void copyFileContents( const File * , const File * );
private:
string fileName;
float entries;
};
I tried commenting out the sourceFile.close() statement and still nothing. I know its a lot of code but whoever can help would be my hero of the century!!
Remove delete(this)
from the destructor!
You aren't constructing a File
with new
(since you're using a static instance on the stack), but the destructor is called anyway. So the delete
statement is invalid and probably causes the segfault.
I've once seen a SEG fault on an if statement and the cause of it (after many hours of misery) turned out to be because I was accessing a private data member of the object, but that I had already started to destroy the object.
My guess is that it might be this line as that looks to me that you are destroying a resource that you are still using.:
sourceFile.close();
Try commenting that out and see how it goes.
精彩评论