c - C中如何保证数据类型的一致性?

标签 c types

让我们假设以下代码:

#include <stdio.h>
int main()
{
   int n;
   scanf("%d",&n);
}

如何确保用户提供的数据是整数(而不是字符)?

是否有任何库可以从用户那里读取数据来确保这一点?

最佳答案

围绕 scanf 调用,您还需要做一些额外的工作。

首先,scanf 将返回成功转换和分配的次数 - 在本例中,您期望 1 表示成功。如果没有成功的转换和赋值,它将返回0。如果输入错误,将返回EOF

因此,作为第一步,您需要执行以下操作:

if ( scanf( "%d", &n ) != 1 )
  // input was not an integer or error on input
else
  // successful input, do something with n

这本身还不够。

%d 告诉 scanf 跳过前导空格,然后读取第一个非数字字符。如果输入“abc”,则没有有效的数字字符,scanf返回0,并且n为未修改。

但是,如果输入像"12c"这样的字符串,那么"12"将被读取并转换,n将被赋值值 12scanf 将返回 1'c' 将保留在输入中流使下一次读取变得困惑。理想情况下,您应该拒绝整个输入。

有几种方法可以解决这个问题。您可以查看紧随输入之后的字符 - 如果它是空格,则输入有效:

char dummy;
int items_read = scanf( "%d%c", &n, &dummy );

如果items_read为2,则意味着scanf读取至少一个十进制数字字符,后跟一个非十进制数字字符。如果dummy包含空格字符,则意味着输入是有效的整数。如果 dummy 包含非空白字符,则用户在输入时误入了非数字字符(意味着 n 中的值不应被信任)。无论哪种方式,我们都需要在继续之前将该虚拟字符推回输入流。

如果 items_read 为 1,这意味着我们至少读取一个十进制数字字符,然后点击 EOF,这意味着我们的输入也必须是有效的整数。

所以,测试看起来像这样:

if ( items_read == 2 && isspace( dummy ) || items_read == 1 )
{
  // do something with n
  if ( items_read == 2 )
    ungetc( dummy, stdin );
}
else
{
  // input was not an integer, or error on input
}

或者,您可以将输入读取为字符串,然后使用strtol 进行转换:

char input[MAX_INPUT_LENGTH+1];
if ( fgets( input, sizeof input, stdin ) ) // using fgets instead of scanf for this
{
  char *chk; // stores address of first character *not* converted
  long tmp = strtol( input, &chk, 0 ); // convert into a temporary
  if ( isspace( *chk ) || *chk == 0 )
  {
    // input is good, assign tmp to n
    if ( tmp <= INT_MAX && tmp >= INT_MIN )
      n = tmp;
    else
      // input was within range for long but not int
  }
  else
    // trailing non-digit character
}

关于c - C中如何保证数据类型的一致性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55872124/

相关文章:

代码未执行

c - 无限循环的原因

python - 如何记录字符串 kwargs 及其预期类型

c - PIC18F87f22(C 语言)上的冲突声明和类型重新声明问题

go - 使用来自其父级的方法更改嵌入式结构的属性

Haskell 无限类型和我的 FSM 函数

arrays - 无法插入 : ERROR: array value must start with "{" or dimension information

c - 为 C 中的结构分配内存

将二进制转换为十六进制的 C 程序

c - 在运行时为文件分配唯一编号