故意返回无效值或类型

时间:2017-12-17 13:32:41

标签: c function return return-value return-type

作为Stephen Kochan的“Programming in C”(第3版)的建议练习,我想在strToInt函数中添加一些功能,将字符串转换为整数。该函数有一个返回类型int,如果传递的字符串文字有效(如“123”或“13”),这是好的。但是如果字符串包含任何非数字值(例如“12x3”,“foo”),则应打印错误消息并退出该函数。由于返回类型为int,因此需要返回一个整数,但在这种情况下,这可能会产生误导。所以我的问题是,在这种情况下应该返回什么,以便返回的值/类型明确地说明了一个无效的字符串文字已被传递并且不能与有效的返回值混淆?

int strToInt(const char string[])
{
    int i = 0, intValue, result = 0;

    // check whether string passed is a valid literal
    while (string[i] != '\0')
    {
        if (string[i] < '0' || string[i] > '9')
        {
            printf("ValueError: Invalid literal\n");
            return;                            // what should be returned here?
        }
        ++i;
    }

    for (i = 0; string[i] >= '0' && string[i] <= '9'; ++i)
    {
        intValue = string[i] - '0';
        result = result * 10 + intValue;
    }

    return result;
}

3 个答案:

答案 0 :(得分:3)

  

//应该在这里归还什么?

通常解决此问题的方法是将结果移动到输出参数。从而释放指示操作成功的状态的返回值。例如:

#include <stdbool.h>

bool strToInt(const char string[], int* outInt) {

    // check whether string passed is a valid literal
    while (string[i] != '\0')
    {
        if (string[i] < '0' || string[i] > '9')
        {
            printf("ValueError: Invalid literal\n");
            return false;
        }
    }

    int result = 0;
    for (int i = 0; string[i] >= '0' && string[i] <= '9'; ++i)
    {
        intValue = string[i] - '0';
        result = result * 10 + intValue;
    }

    if (outInt) // Or you may move the check earlier and return false too
      *outInt = result;

    return true;
}

你当然可以退回任何类型,而不仅仅是一个布尔。许多软件系统返回几个整数值中的一个,这些值可以指示操作可能失败的几种方式中的任何一种因此,错误处理可以更加精确和复杂。

答案 1 :(得分:2)

这是软件工程中一个有趣的问题,并没有“最佳答案”。

在某些情况下,指定范围的特定值可能有效。例如,在标准C库中,某些字符操作函数(如getc)的返回类型设置为int而不是char。这是为了能够返回-1作为错误代码。

如果没有可能从字符串转换为double的话,其他函数(例如strtod)只返回0(可以说这是否是好的方法)。如果发生错误,它们会返回一个特殊值(仍然是有效的双精度值)并设置errno

Errno似乎是unix世界中错误报告的标准方法。在核心,它基本上是一个全局变量,存储最后一个错误的错误代码。当发生某些事情时,大多数系统调用都返回一个特定的值,然后你应该检查errno中的错误代码,看看发生了什么。

答案 2 :(得分:0)

strto*函数的作用是什么 - 它们返回转换后的数字(如果有的话),然后将指针重置为它无法辨认的部分的开头。使用相同的音调可以做很多事情 - 如果你通过standard,你可以清楚地了解它。

因此,在给定12x3的示例的情况下,您的函数可能返回12,然后使指针指向字符串中的适当位置。这是通过传递的指针提供错误信息,然后返回尽可能多的从输入解析。

如果来自strtol页面的[long int strtol(const char *nptr, char **endptr, int base);]man),我们可以看到当endptr设置为字符串的结尾时,那意味着整个字符串我被解析成功。在部分转换的情况下,endptr不会指向字符串的中间。 同样地模仿strto*函数,我们可以看到它将errno设置为适当的数字来表示不同的问题(ERANGE等) - 所以你可以设置它以给用户一个准确的错误报告。