【问题标题】:Intentionally returning an invalid value or type故意返回无效的值或类型
【发布时间】:2018-05-31 00:56:17
【问题描述】:

作为 Stephen Kochan 的“Programming in C”(第 3 版)的建议练习,我想向 strToInt 函数添加一些功能,该函数将字符串转换为整数。如果传递的字符串文字有效(如“123”或“13”),该函数有一个返回类型int。但如果字符串包含任何非数值(例如“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;
}

【问题讨论】:

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


    【解决方案1】:

    做好strto* 函数所做的事情——它们返回转换后的数字(如果有的话),然后将指针重置到它无法识别的部分的开头。使用相同的语气,它可以做很多事情 - 如果您通过standard 可以清楚地了解它。

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

    如果是man 页面中的strtol ([long int strtol(const char *nptr, char **endptr, int base);]),我们可以看到当endptr 设置为字符串的末尾时,这意味着整个字符串已成功稀疏。在部分转换的情况下,endptr 不会指向字符串的中间。 以同样的方式模仿strto* 函数,我们可以看到它将errno 设置为适当的数字以表示不同的问题(ERANGE 等) - 因此您可以设置它以向用户提供精确的错误报告。

    【讨论】:

      【解决方案2】:

      //这里应该返回什么?

      可以在此处返回的所有内容都不会是有效的结果。通常解决这个问题的方法是将结果移动到一个输出参数。从而释放指示操作成功的状态的返回值。例如:

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

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

      【讨论】:

        【解决方案3】:

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

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

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

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

        【讨论】:

          猜你喜欢
          • 2012-02-07
          • 1970-01-01
          • 2012-11-25
          • 2019-05-07
          • 2022-12-06
          • 2022-11-02
          • 2019-05-04
          • 2014-08-08
          • 1970-01-01
          相关资源
          最近更新 更多