使用异常 C++ 的 try-catch 块从文件中读取行
Reading lines from a file using a try-catch block for exceptions C++
我想读取一定长度的行并解析它们。为了解析它们,我使用异常来处理特定的错误输入,但是每当我发现错误时,我的缓冲区就会充满错误的输入,下一个 getline 命令会在其中放入乱码,即使文件中仍然存在有效输入。
这是我的代码:
(inStream
是 istream
类型因为如果文件无效我从 cin
读取)
char buffer[MAX_LINE_LENGTH];
string line;
while (inStream.getline(buffer,MAX_LINE_LENGTH)) {
line=string(buffer);
try {
parse(line, inStream, outStream);
}
catch(const DoneError& e){
outStream<<e.what();
return 0;
}
catch(const MyException& e) {
outStream<<e.what();
}
//invalid_argument or out_of_range at stod & stoi
catch (const logic_error& e) {
outStream<<BadParameterExeption().what();
}
catch(const exception& e){
outStream<<e.what();
}
}
在我第一次从 parse
捕获异常后(已经在 catch 块中)buffer
充满了垃圾而不是原始内容,循环的下一次迭代也填充了 buffer
有垃圾而不是输入。
我尝试在 catch 块之后使用 clear()
和 ignore(MAX_LINE_LENGTH, '\n')
但它没有帮助。
我能做什么?
我想最多阅读 MAX_LINE_LENGTH 个字符,这样如果我在一行中得到的字符数超过这个数目,我会在下一次迭代中阅读它。
我从文件中读取(不是重定向),方法如下:
ifstream inpFile;
ofstream outFile;
/* I receive the files' names via argv, some are input some are output
* (order is fixed but not the number)
* /.prog outpu1 input1 output2 input2 (and so on)
* degenerated example on how It works:
* for(int i=argc-1; i>0; i-=2){
* inpFile.open(argv[i]);
* if(inpFile.is_open()) return true;
* }
*/
if (!initFiles (argc, argv, inpFile, outFile))
return 1;
istream &inStream = (inpFile.is_open()) ? inpFile : cin;
ostream &outStream = (outFile.is_open()) ? outFile : cout;
您必须提供更多信息。当在 Fedora 上用 g++ 5.1.1 编译时,下面的代码工作得很好。显然,我必须创建一些缺少的基础结构才能编译它 运行 但我认为我没有采取太多的自由。
#include <iostream>
#include <fstream>
#include <exception>
#include <stdexcept>
#include <string>
using namespace std;
#define min(x, y) (x < y) ? x : y
const int MAX_LINE_LENGTH = 80;
struct DoneError : public exception
{
const char *what() const throw()
{
return "Done Exception";
}
};
struct MyException : public exception
{
const char *what() const throw()
{
return "MyException";
}
};
struct BadParameterExeption : public exception
{
const char *what() const throw()
{
return "Bad Parameter";
}
};
void parse(string l, istream &is, ostream &os)
{
if (l.find("MyException") != string::npos)
throw MyException();
if (l.find("Done") != string::npos)
throw DoneError();
if (l.find("logic") != string::npos)
throw logic_error("You made a logic error");
if (l.find("BadParameter") != string::npos)
throw BadParameterExeption();
}
int main(int argc, char **argv)
{
ifstream inpFile(argv[1]);
ofstream outFile(argv[2]);
istream &inStream = (inpFile.is_open()) ? inpFile : cin;
ostream &outStream = (outFile.is_open()) ? outFile : cout;
char buffer[MAX_LINE_LENGTH];
string line;
try {
while (getline(inStream, line, '\n'))
{
while (line.length() > 0)
{
string smaller = line.substr(0, min(MAX_LINE_LENGTH, line.length()));
line = line.substr(min(MAX_LINE_LENGTH, line.length()));
try {
parse(smaller, inStream, outStream);
}
catch(const DoneError& e){
outStream<<e.what()<<endl;;
return 0;
}
catch(const MyException& e) {
outStream<<e.what()<<endl;;
}
//invalid_argument or out_of_range at stod & stoi
catch (const logic_error& e)
{
outStream<<BadParameterExeption().what()<<endl;;
}
catch(const exception& e){
outStream<<e.what()<<endl;;
}
}
}
}
return 0;
}
由于您没有真正解释您最终要尝试做什么,因此您可能必须在处理输入片段方面重构它。 istream.getline() 处理原始字符,可以是 'fiddly'
我想读取一定长度的行并解析它们。为了解析它们,我使用异常来处理特定的错误输入,但是每当我发现错误时,我的缓冲区就会充满错误的输入,下一个 getline 命令会在其中放入乱码,即使文件中仍然存在有效输入。
这是我的代码:
(inStream
是 istream
类型因为如果文件无效我从 cin
读取)
char buffer[MAX_LINE_LENGTH];
string line;
while (inStream.getline(buffer,MAX_LINE_LENGTH)) {
line=string(buffer);
try {
parse(line, inStream, outStream);
}
catch(const DoneError& e){
outStream<<e.what();
return 0;
}
catch(const MyException& e) {
outStream<<e.what();
}
//invalid_argument or out_of_range at stod & stoi
catch (const logic_error& e) {
outStream<<BadParameterExeption().what();
}
catch(const exception& e){
outStream<<e.what();
}
}
在我第一次从 parse
捕获异常后(已经在 catch 块中)buffer
充满了垃圾而不是原始内容,循环的下一次迭代也填充了 buffer
有垃圾而不是输入。
我尝试在 catch 块之后使用 clear()
和 ignore(MAX_LINE_LENGTH, '\n')
但它没有帮助。
我能做什么?
我想最多阅读 MAX_LINE_LENGTH 个字符,这样如果我在一行中得到的字符数超过这个数目,我会在下一次迭代中阅读它。
我从文件中读取(不是重定向),方法如下:
ifstream inpFile;
ofstream outFile;
/* I receive the files' names via argv, some are input some are output
* (order is fixed but not the number)
* /.prog outpu1 input1 output2 input2 (and so on)
* degenerated example on how It works:
* for(int i=argc-1; i>0; i-=2){
* inpFile.open(argv[i]);
* if(inpFile.is_open()) return true;
* }
*/
if (!initFiles (argc, argv, inpFile, outFile))
return 1;
istream &inStream = (inpFile.is_open()) ? inpFile : cin;
ostream &outStream = (outFile.is_open()) ? outFile : cout;
您必须提供更多信息。当在 Fedora 上用 g++ 5.1.1 编译时,下面的代码工作得很好。显然,我必须创建一些缺少的基础结构才能编译它 运行 但我认为我没有采取太多的自由。
#include <iostream>
#include <fstream>
#include <exception>
#include <stdexcept>
#include <string>
using namespace std;
#define min(x, y) (x < y) ? x : y
const int MAX_LINE_LENGTH = 80;
struct DoneError : public exception
{
const char *what() const throw()
{
return "Done Exception";
}
};
struct MyException : public exception
{
const char *what() const throw()
{
return "MyException";
}
};
struct BadParameterExeption : public exception
{
const char *what() const throw()
{
return "Bad Parameter";
}
};
void parse(string l, istream &is, ostream &os)
{
if (l.find("MyException") != string::npos)
throw MyException();
if (l.find("Done") != string::npos)
throw DoneError();
if (l.find("logic") != string::npos)
throw logic_error("You made a logic error");
if (l.find("BadParameter") != string::npos)
throw BadParameterExeption();
}
int main(int argc, char **argv)
{
ifstream inpFile(argv[1]);
ofstream outFile(argv[2]);
istream &inStream = (inpFile.is_open()) ? inpFile : cin;
ostream &outStream = (outFile.is_open()) ? outFile : cout;
char buffer[MAX_LINE_LENGTH];
string line;
try {
while (getline(inStream, line, '\n'))
{
while (line.length() > 0)
{
string smaller = line.substr(0, min(MAX_LINE_LENGTH, line.length()));
line = line.substr(min(MAX_LINE_LENGTH, line.length()));
try {
parse(smaller, inStream, outStream);
}
catch(const DoneError& e){
outStream<<e.what()<<endl;;
return 0;
}
catch(const MyException& e) {
outStream<<e.what()<<endl;;
}
//invalid_argument or out_of_range at stod & stoi
catch (const logic_error& e)
{
outStream<<BadParameterExeption().what()<<endl;;
}
catch(const exception& e){
outStream<<e.what()<<endl;;
}
}
}
}
return 0;
}
由于您没有真正解释您最终要尝试做什么,因此您可能必须在处理输入片段方面重构它。 istream.getline() 处理原始字符,可以是 'fiddly'