【问题标题】:validate input cmdline input argv[] contains all integers验证输入 cmdline 输入 argv[] 包含所有整数
【发布时间】:2011-06-26 15:16:32
【问题描述】:

所以我有一个处理数字操作的作业,其中还包括错误检查。我在错误检查方面遇到问题。用户通过命令行使用应用程序并给出 8 个空格分隔的数字。我在验证所提供的数据实际上是整数时遇到问题。

有人建议我使用 strtol() 方法,但是我知道如果整数无效,它会返回 0,但我需要返回错误消息而不是 0,因为 0 是有效的。我可以使用其他方法来验证输入吗?

【问题讨论】:

  • strtol 如果整数无效,则返回 0;仔细阅读功能说明。然而,它确实返回一个long。您需要确保该值符合int 范围。提示:使用<limits.h>

标签: c validation integer char


【解决方案1】:

strtol 不仅有它的返回值来表示转换中的错误,它还有它的第二个参数(我的手册页中的endptr);如果您将指向char * 的指针传递给它,它将在那里存储它无法转换的第一个字符的位置,或者如果没有任何东西可以转换,它将不理会它。因此,您有以下情况:

char * endptr=NULL;
int out=strtol(yourstring, &endptr, 10);
if(endptr==NULL)
{
    /* the whole string is garbage - no numbers extracted */
}
else if(*endptr==0)
{
    /* the whole string was a number - yay! */
}
else
{
    /* strtol extracted a number from the string, but stopped at some invalid character
       that you can check by looking at the value of endptr */
}

此外,您还可以检查strtol设置errno的值以防出现问题; EINVAL 用于如果无法提取任何内容,其他值可以在 strtol 的联机帮助页中查看。

您还可以使用sscanf 并检查其返回值,以快速查看字符串是否可以转换为int(或您在格式字符串中设置的任何内容)。

【讨论】:

    【解决方案2】:

    如果strtol() 遇到错误,它会将errno 设置为EINVAL。来自man page

    返回值

    strtol() 函数返回转换结果,除非值会下溢或溢出。 ...在这两种情况下,errno 都设置为 ERANGE。 ...

    错误

    EINVAL...给定的基数包含不受支持的值。 ...

    实现也可以将 errno 设置为 EINVAL,以防没有执行转换(没有看到数字,返回 0)。

    【讨论】:

      【解决方案3】:

      命令行参数是字符串,为什么不用isdigit(3)

      【讨论】:

      • 也许是因为这不会检查越界数字。而且您必须单独检查领先的-
      • 什么是“越界”整数?
      • 对于 32 位整数类型,10000000000000000000000000 越界。
      • 谁说过任何位宽?
      • 原帖者建议使用strtol查看。 ;)
      【解决方案4】:

      要正确使用strtol,您必须在调用它之前重置errno。而且,如果您编写的代码希望在其他项目中重用,那么该代码应该没有意外的副作用。因此有两种变体:一种可能对您的情况足够好的简单变体,另一种在可重用代码库中可接受的复杂变体。

      #include <errno.h>
      #include <stdbool.h>
      #include <stdlib.h>
      
      /* the simple variant, with the side-effect of changing errno */
      static bool is_long_1(const char *s)
      {
        char *end;
      
        errno = 0;
        strtol(s, &end, 10);
        return errno == 0 && *end == '\0';
      }
      
      /* the complex variant, without side-effects */
      static bool is_long_2(const char *s)
      {
        char *end;
        int saved_errno = errno;
        errno = 0;
      
        strtol(s, &end, 10);
        bool succeeded = errno == 0 && *end == '\0';
        errno = saved_errno;
        return succeeded;
      }
      

      使用这些函数之一来检查你的论点应该很容易,所以我把这部分留给你去发现。

      【讨论】:

        猜你喜欢
        • 2023-03-08
        • 2012-11-02
        • 2013-05-31
        • 1970-01-01
        • 2011-10-04
        • 2013-02-20
        • 1970-01-01
        • 1970-01-01
        • 2022-09-28
        相关资源
        最近更新 更多