C:如何防止使用scanf溢出输入?

时间:2014-02-09 21:43:38

标签: c integer overflow scanf

我对C比较陌生,想知道如何防止输入溢出......

例如,我有:

scanf("%d", &a);

其中a是整数。

那么我能做些什么来阻止某人输入一个大于最大整数的数字呢?由于我正在处理的问题的限制,你必须使用scanf。我该如何限制输入?

提前致谢。

1 个答案:

答案 0 :(得分:1)

'阻止用户输入非常具有挑战性 没有任何魔术手可以触及并阻止用户敲击键盘。

但是代码可以限制它的内容。

1)scanf()很难限制。它可能不会在溢出时设置errno。代码可以将char的数量限制为9.这是第一步,但不能输入“1000000000”或“00000000000000001”等值。

// Assume INT_MAX = 2,147,483,647.
scanf("%9d", &a);

2)一种迂腐的方法会使用fgetc()。接下来是unsigned方法。 int需要更多。

unsigned a = 0;
int ch = fgetc(stdin);
while (isspace(ch)) {
  ch = fgetc(stdin);
}
while (isdigit(ch)) {
  unsigned newa = a*10 + ch - '0';
  if (newa < a) {
    break;  // overflow detected.
  }
  a = newa;
  ch = fgetc(stdin);
}
ungetc(ch, stdin);  // Put back `ch` as it was not used.       

3)但我更喜欢改变目标,只是再次告诉用户,即使它意味着阅读更多的字符。

// 0:success or EOF
int Read_int(const char *prompt, int *dest, int min, int max) {
  for (;;) {
    char buf[sizeof(int)*3 + 3];
    fputs(prompt, stdout);
    if (fgets(buf, sizeof buf, stdin) == NULL) {
      return EOF;
    }
    char *endptr;
    errno = 0;
    long l = strtol(buf, &endptr, 10);
    if (buf == endptr || *endptr != '\n') {
      continue; // only \n entered or invalid `chars` entered
    }
    if (!errno && l >= min && l <= max) {
     *dest = (int) l;
     return 0; // success
    }
  }
}  

int a;
Read_int("Enter an `int`\n", &a, INT_MIN, INT_MAX);