C++:IF 语句退出时出现段错误
这次我将连同所有代码一起重新发布。我希望至少在一段时间内不关闭该帖子。我显然不是专家,以前从未遇到过类似的事情,但我确实认为这对其他成员很有用。我尝试了评论并同意错误与破坏有关,但找不到位置。我已在底部的评论中包含了段错误的位置。我没有 IDE,也不知道如何使用 xterm 内置的调试器,所以我不知所措!
#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;
}
这是 .cpp 文件
#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;
}
}
}
这是 .h 文件
#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;
};
我尝试注释掉 sourceFile.close() 语句,但仍然没有任何结果。我知道它有很多代码,但任何能提供帮助的人都将成为我的世纪英雄!
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!!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
从析构函数中删除
delete(this)
!您没有使用
new
构造一个File
(因为您在堆栈上使用静态实例),但无论如何都会调用析构函数。因此delete
语句无效,可能会导致段错误。Remove
delete(this)
from the destructor!You aren't constructing a
File
withnew
(since you're using a static instance on the stack), but the destructor is called anyway. So thedelete
statement is invalid and probably causes the segfault.我曾经在 if 语句上看到过 SEG 错误,其原因(经过几个小时的痛苦)原来是因为我正在访问对象的私有数据成员,但我已经开始销毁该对象。
我的猜测是,这可能是这一行,因为在我看来,您正在破坏您仍在使用的资源。:
尝试将其注释掉,看看它是如何进行的。
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.:
Try commenting that out and see how it goes.