建议处理while循环错误

时间:2014-08-13 07:37:30

标签: c++ memory while-loop

在通过while循环逐行读取文本文件的情况下,建议的处理错误的方法是什么?

(注意:here使用了fggets

bool SomeClass::ReadFile(int ignorelines) {
    FILE *file = fopen(m_filepath.c_str(), "r");
    if (file!=NULL) {
        char *buffer;                           //line reading buffer
        while (fggets(&buffer,file)==0) {       //read line (fggets returns non-zero at provided terminator or \eof)
            if (ignorelines>0) {
                ignorelines--;                  //count the lines ignored
                free(buffer);
                continue;
            }
            line.assign(buffer);
            if (!PerformLineCheck1(buffer)) {   
                m_error+="The line is not allowed.\n";
                free(buffer);
                fclose(file);
                return false;
            }
            if (!PerformLineModification1(buffer)) {
                m_error+="The line could not be modified properly.\n";
                free(buffer);
                fclose(file);
                return false;
            }
            if (!PerformLineExtraction(buffer)) {   
                m_error+="The variables could not be extracted.\n";
                free(buffer);
                fclose(file);
                return false;
            }
            //extracted all, now continue with next line
            free(buffer);                       //clear up the line
        }
        fclose(file);
        return true;
    }
    m_error+="There was an error opening the data file.\n";
    return false;
}

我可以想到一些选择:

  • 使用break;退出while循环:但是我需要 添加free(buffer);,这可能会导致freeing memory twice
  • 使用trycatch,但这也处理了这些函数中的所有其他异常,并建议使用assert(as 建议here)。但是,断言将承担代码错误并中断操作 对于这种情况,程序执行可以继续,函数只需要返回false。

对于类似上面的循环的建议有什么建议?

3 个答案:

答案 0 :(得分:0)

首先,trycatch不是一个完全糟糕的主意。您可以测试特定错误并重新抛出其余错误,或者在一个dragnet中捕获每个可能的错误,打印错误消息并关闭。这完全取决于您正在阅读的数据类型,您将合理期望看到的错误,以及您需要执行的优质错误恢复级别。

至于使用break,有一种方法可以在不进行双重免费的情况下执行此操作,但是,某些人可能不受欢迎。

基本上,它看起来像这样:

while (someCondition) {
   // Do things
   error = 1; // Error encountered
   if (error)
       goto cleanUp;
   // Do some more things
}
// Do some other things that you need to do outside the loop here
:cleanUp
free(buffer);
return error;

它的操作类似于在某些语言中使用自定义onError事件处理程序。

答案 1 :(得分:0)

第一步:尽早处理错误,移动"如果我们无法打开文件"一点点。

bool SomeClass::ReadFile(int ignorelines) {
    FILE *file = fopen(m_filepath.c_str(), "r");
    if (file==NULL) {
      m_error+="There was an error opening the data file.\n";
      return false;
    }

然后其余的代码使用res变量来跟踪整个操作是否成功,以及序列末尾的单个if来确定我们是否继续循环(或者,如果您愿意,可以while (res && fggets( ... )))。

    char *buffer;                           //line reading buffer
    bool result = true;
    while (fggets(&buffer,file)==0) {       //read line (fggets returns non-zero at provided terminator or \eof)
        if (ignorelines>0) {
            ignorelines--;                  //count the lines ignored
        }
        else
        {
            line.assign(buffer);
            if (!PerformLineCheck1(buffer)) {   
                m_error+="The line is not allowed.\n";
               res = false;
            }
            else if (!PerformLineModification1(buffer)) {
                m_error+="The line could not be modified properly.\n";
                res = false;
            } 
            else if (!PerformLineExtraction(buffer)) {   
                m_error+="The variables could not be extracted.\n";
                res = false;
            }
        }
        //extracted all, now continue with next line
        free(buffer);                       //clear up the line
        if (!res) break; 
    }
    fclose(file);
    return res;
}

这减少了代码中的重复以释放和关闭。

(编辑:不是continue的粉丝,我在第一个if之后将其更改为else,并删除了free(buffer)来电

答案 2 :(得分:0)

  1. 您可以只使用一行try块,因此其他功能不会导致任何问题, 示例如下所示。
  2. 如果您不确定某个缓冲区是否已清除,请使用xxx == nullptr进行检查 不会被删除两次。
  3. 对于点号。 1,如果要在使用fgets()时捕获异常,请执行以下操作:

    int result = 0;
    while (true) {
        char* buffer = new char[100]; //YOU MUST allocate space for the buffer, 
                                      //cannot use it directly
        try {
            result = fggets(&buffer,file);
        }
        catch () {
            //do whatever you need to catch, break if necessary
            //handling of memory is shown below
        }
        if (0 == result) {
            if (nullptr != buffer) { // make sure when you execute delete[] or free, the pointer is valid
                delete[] buffer;//or free
            }
            break;
        }
        //do your other things here
    }