简体   繁体   English

使用try-catch块从文件读取行以获取异常C ++

[英]Reading lines from a file using a try-catch block for exceptions C++

I want to read lines in certain length and parse them. 我想读取一定长度的行并进行解析。 To parse them I use exceptions to take care of specific bad inputs, but whenver I catch an error my buffer is filled with bad input and the next getline command puts gibberish in it even though there is still valid input in the file. 为了解析它们,我使用异常来处理特定的错误输入,但是每当我遇到错误时,我的缓冲区就会被错误输入填充,即使文件中仍然有有效输入,下一个getline命令也会在其中输入乱码。

Here is my code: 这是我的代码:

( inStream is of type istream because if the file is invalid I read from cin ) 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();
    }
}

After the first time I catch exception from parse (already in the catch block) buffer is filled with junk and not the original contents, also the next iteration of the loop fills buffer with junk and not the input. 第一次后,我赶上从异常parse (已在catch块) buffer充满了垃圾,而不是原来的内容,也是循环的下一次迭代填充buffer带的垃圾,而不是输入。 I tried using clear() and ignore(MAX_LINE_LENGTH, '\\n') after the catch blocks but it didn't help. 我尝试在catch块之后使用clear()ignore(MAX_LINE_LENGTH, '\\n') ,但这没有帮助。 What can I do? 我能做什么? I want to read MAX_LINE_LENGTH chars at most so that if I get more than that in a single line I read it in the next iteration. 我最多要读取MAX_LINE_LENGTH个字符,这样,如果我在一行中得到的字符更多,则可以在下一次迭代中读取它。

I read from a file (not redirecting), here's how: 我从文件中读取(不重定向),方法如下:

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;

You'll have to supply more information. 您必须提供更多信息。 The following works just fine when compiled with g++ 5.1.1 on Fedora. 当在Fedora上使用g ++ 5.1.1进行编译时,以下代码可以正常工作。 Obviously, I had to create some of the missing infrastructure to get it to compile and run but I don't think I took too many liberties. 显然,我必须创建一些缺少的基础结构才能进行编译和运行,但是我认为我没有太多的自由。

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

Since you're not really explained what you're ultimately trying to do you will probably have to refactor this in terms of processing the pieces of the input. 由于您并没有真正解释您最终想要做什么,因此您可能必须在处理输入内容方面进行重构。 istream.getline() deals in raw characters and can be 'fiddly' istream.getline()处理原始字符,并且可以被“巧妙地”处理

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM