处理此错误检查的正确方法是什么?

时间:2011-07-11 03:05:36

标签: c error-handling validation

我有一个函数,应该传递一个带有两个数字的字符串(作为正则表达式:/-?[0-9]+ -?[0-9]+/)并返回第二个。

我已经决定该程序应该进行错误检查。首先,它应该测试字符串是否实际上是所需的形式;第二,它应该确保第一个数字(返回的数字)是连续的。

现在我已经编程了很长时间,这不是一项艰巨的任务。 (由于这些数字不一定适合机器词,所以稍微有些困难。)但我的问题是我应该如何这样做而不是我可以 。我提出的所有解决方案都有些难看。

  • 我可以使用全局变量来保存值并比较它们(或者只是将值保留在那里NULL);这似乎是错误的事。
  • 我可以通过引用传递一个或两个返回值和最后一个/当前行的第一个数字并修改它们
  • 我可以使用返回值给出一个bool,因为有/没有错误

因此,欢迎任何有关正确的方式处理C中此类错误检查的方法的想法。


这与更理论化的question I asked on cstheory有关。作为参考,这是函数:

char*
scanInput(char* line)
{
    int start = 0;
    while (line[start] == ' ' || line[start] == '\t')
        start++;
    if (line[start] == '#')
        return NULL;    // Comment
    if (line[start] == '-')
        start++;
    while (line[start] >= '0' && line[start] <= '9')
        start++;
    while (line[start] == ' ' || line[start] == '\t')
        start++;
    int end = start;
    if (line[end] == '-')
        end++;
    while (line[end] >= '0' && line[end] <= '9')
        end++;
    if (start == end)
        return NULL;    // Blank line, or no numbers found
    line[end] = '\0';

    return line + start;
}

并且它被称为:

while(fgets(line, MAX_LINELEN, f) != NULL) {
    if (strlen(line) > MAX_LINELEN - 5)
        throw_error(talker, "Maximum line length exceeded; file probably not valid");
    char* kept = scanInput(line);
    if (kept == NULL)
        continue;
    BIGNUM value = strtobignum(kept);
    if (++i > MAX_VECLEN) {
        warning("only %d terms used; file has unread terms", MAX_VECLEN);
        break;
    }
    // values are used here
}

2 个答案:

答案 0 :(得分:2)

C中的传统解决方案是使用传递引用(指针)来返回函数计算的值,并使用返回值进行错误处理,就像scanf执行此操作一样。

int scanInput(char **line_p int *number){
    char * line = *line_p;
    ...
    if(something bad happens){
        return 1;
    }
    ...
    *linep = line + start;
    *number = ...;
    return 0; //success
}

int main(){
    char word[100]; strcpy(word, "10 17");
    char *line = word;
    int number;
    switch(scanInput(&line, &number)){
        case 1:
        default:
    }
}

额外点:

  • 使用一些枚举来为错误代码赋予意义可能是个好主意。
  • 如果您可以使用C ++(或类似的)异常通常是错误处理的最佳解决方案,因为您不必再​​用ifs填充代码
  • 全球变量通常都是邪恶的。如果您想要使用它们,请考虑在结构中封装所需的状态,并将指针传递给它。在OO意义上将其视为“this”指针。

答案 1 :(得分:1)

最终,您需要隔离并转换每行中的两个大数字。要检查该行上的第一个数字是否是前一个数字,您必须保留最后找到的数字的记录。因此,您可能需要一个结构,例如:

BIGNUM old_value = 0;  // See notes below

while (fgets(line, sizeof(line), f) != 0)
{
    BIGNUM value1;
    BIGNUM value2;
    if (ScanDoubleBigNum(line, &value1, &value2) != 0)
        ...handle line format error...
    if (old_value == 0 || are_consecutive(old_value, value1))
    {
        // OK - valid information found
        // Release old_value
        old_value = value1;
        process(value2);
        // Release value2
    }
    else
        ...handle non-consecutive error...
}

are_consecutive()函数确定其第二个参数是否大于第一个参数。 process()函数执行第二个值所需的任何操作。 ScanDoubleBigNum()函数与您的ScanInput()相关,但它会读取两个值。实际代码将调用包含大约一半ScanBigNum()的另一个函数(称为ScanInput())(因为它包含两次基本相同的代码),以及当前在循环中发生的转换。 ScanDoubleBigNum()中的代码会两次调用ScanBigNum()。请注意,ScanBigNum()需要确定扫描完成的位置,以便第二次调用可以在第一次停止的地方继续。

我冒昧地假设BIGNUM是由指针标识的已分配结构,因此初始化BIGNUM old_value = 0;是一种表示尚无值的方式。可能有一个释放BIGNUM的功能。如果这不正确,那么您需要调整建议的代码以适应BIGNUM类型的实际行为。 (这是基于OpenSSL还是SSLeay代码?)