开发者

C++: Seg Fault on exit of IF statement

开发者 https://www.devze.com 2023-04-12 13:38 出处:网络
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 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.

0

精彩评论

暂无评论...
验证码 换一张
取 消