【问题标题】:Check For Possible Int Overflow From an Input从输入检查可能的 Int 溢出
【发布时间】:2019-02-19 16:40:53
【问题描述】:

我已经阅读了一段时间的源代码,但是他们在执行操作时总是在谈论溢出,但是在用户输入它之前,我如何真正检查潜在的 int 溢出,然后才能将其分配给 int 标识符?

我想在输入的那一刻检查输入,所以当发现这样的值已经超出了 int 类型数据的值范围时,我可以在它进入下一部分代码之前停止它。

【问题讨论】:

  • 对结果进行边界检查。如果不能接受,就报错。
  • @tadman 说起来容易做起来难。
  • 当您未能测试结果并且只是假设没问题时会出现溢出错误。如果需要,请将结果限制在可接受的范围内。

标签: c


【解决方案1】:

你可以读取一个字符串然后使用 strtol 然后检查 endptrerrno,当一切正常时你可以分配你的 int 变量

strtol

的详细用法
#include <stdlib.h>
#include <ctype.h>
#include <errno.h>

int main()
{
  char s[32]; /* 31 characters is surely large enough for an int */

  if (scanf("%31s", s) != 1)
    puts("nok");
  else {
    errno = 0;

    char * endptr;
    long int l = strtol(s, &endptr, 10);

    if (endptr == s)
      puts("no digit");
    else if ((*endptr != 0) && !isspace(*endptr))
      puts("invalid number");
    else if (errno != 0)
      puts("overflow on long");
    else if (((int) l) != l) /* in case long and int do not have the same size */
      puts("overflow on int");
    else
      puts("you enter a valid int");
  }

  return 0;
}

编译和执行:

pi@raspberrypi:/tmp $ gcc -pedantic -Wextra s.c
pi@raspberrypi:/tmp $ ./a.out
a 
no digit
pi@raspberrypi:/tmp $ ./a.out
12z
invalid number
pi@raspberrypi:/tmp $ ./a.out
123
you enter a valid int
pi@raspberrypi:/tmp $ ./a.out
12345678901
overflow on long

所以要准确回答这个问题:

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <errno.h>

int readInt(int * v)
{
  char s[32]; /* 31 characters is surely large enough for an int */

  if (scanf("%31s", s) != 1)
    return 0;
  else {
    errno = 0;

    char * endptr;
    long int l = strtol(s, &endptr, 10);

    if ((endptr == s) ||       /* no digit */
        ((*endptr != 0) && !isspace(*endptr)) || /* e.g. 12a */
        (errno != 0) ||        /* overflow on long */
        (((int) l) != l))      /* overflow on int */
      return 0;

    *v = (int) l;
    return 1;
  }
}


int main()
{
  int v = 123;

  if (readInt(&v))
    printf("new valid in value : %d\n", v);
  else
    printf("unvalid input, still %d\n", v);

  return 0;
}

编译和执行:

pi@raspberrypi:/tmp $ gcc -pedantic -Wextra s.c
pi@raspberrypi:/tmp $ ./a.out
12
new valid in value : 12
pi@raspberrypi:/tmp $ ./a.out
9878787878787878
unvalid input, still 123
pi@raspberrypi:/tmp $ 

【讨论】:

  • 一个价值一千字的评论样本:)
  • @SergeyA 你是什么意思?缺少代码示例?
  • 是的,这正是我的意思
  • @SergeyA 所以我们同意,我会 ^^
  • 您需要在调用strtol() 之前将errno 设置为零,否则如果strtol() 成功,则无法保证为零。
【解决方案2】:

如果你必须直接读入一个 int,你不能在赋值之前真正检查溢出。

如果不需要直接读入 int 的话,有一些方法可以解决这个问题。例如,您可以读入字符缓冲区/字符串,然后检查输入是否为数字以及它是否适合 int。如果是这样,然后使用标准库函数将字符缓冲区转换为整数并分配给您的 int。

【讨论】:

  • 一个价值一千字的评论样本:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-08-24
  • 1970-01-01
  • 2023-03-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多