【问题标题】:Hexadecimal number comparison?十六进制数比较?
【发布时间】:2015-02-22 17:35:18
【问题描述】:

我是 C 语言的新手,对十六进制、十进制数字的工作原理有点困惑。我正在尝试使用最多 4 个字节,所以 0xFFFFFFFF。我基本上希望程序在输入任何 9 位或更高位的数字时发出警报。我编写了如下代码,但它仍然允许我输入大于 0xFFFFFFFF 的数字。我究竟做错了什么?提前致谢!

int main()
{
uint32_t rgba;
printf("Enter rgba value: ");
scanf("%x", &rgba);
if (rgba > 0xFFFFFFFF){
    printf("Maximum number of 8 digits!\n");
}
else{
    rgba_values(rgba);
}
return 0;
}

【问题讨论】:

  • 您无法检查大于存储可能的数字。 “太大的值”永远不会存储在目标变量中。如果您想允许输入此接下来阻止它,请使用更大的类型或字符串进行输入。
  • 我明白你的意思,但我将变量定义为 32 位,如果我输入更大的值,那么不会出现自动错误吗?
  • The man page 指出,如果出现错误,errno 应设置为 ERANGEscanf 应返回 EOF。但是你不检查它的返回值...

标签: c hex


【解决方案1】:

正如@Jongware 评论的那样,“您无法检查大于可以存储的数字。”

要检测用户输入是否超出uint32_t rgba 的范围,代码需要了解用户输入已经或将超出该范围。

方法一:使用较大的整数类型:此方法将“100000000”检测为输入过大,但对于大于“FFFFFFFFFFFFFFFF”的数字会出现问题。

unsigned long long UserInput;
uint32_t rgba;
printf("Enter rgba value: ");
if (scanf("%llx", &UserInput) != 1) {
  puts("EOF or Scan Failure");
  return 1;
}
if (UserInput > 0xFFFFFFFFu) {
  puts("Range error");
  return 1;
}
rgba = UserInput;
rgba_values(rgba);

方法二:使用fgets()/strtoul()。以下内容适用于长达 99 个char 的输入(包括'\n')。

uint32_t rgba;
char *buf[100];
printf("Enter rgba value: ");
if(fgets(buf, sizeof buf, stdin) == NULL)  {
  puts("EOF");
  return 1;
}
char *endptr = 0;
errno = 0;
unsigned long ul = strtoul(buf, &endptr, 16);
if (buf == endptr) {
  puts("No conversion");
  return 1;
}
if (errno || ul > 0xFFFFFFFFu) {
  puts("value out of range");
  return 1;
}
rgba = (uint32_t) ul;
rgba_values(rgba);

其他方法包括计算十六进制字符数或一次转换用户输入 1 char

【讨论】:

    【解决方案2】:
    if (rgba > 0xFFFFFFFF)
    

    rgba 是一个 32 位无符号整数值,上述条件始终为假。 32 位无符号整数值始终为

    【讨论】:

    • 对不起,当我说 scanf("%x", &rgba);它让我输入一个十六进制的值。假设我输入了 9 位数字的 123456789,我希望它在这种情况下给出消息。但它没有给出“最大 8 位数”消息,而是跳转到 rgba_values 函数。
    【解决方案3】:

    检查scanf 的返回值:当且仅当输入是没有溢出的有效十六进制数时,它才返回1。请注意,只有当int 在您的平台上正好是 32 位时,这才符合您的目的。

    【讨论】:

    • 不幸的是,这不是真的——读取无符号数(如%x)将读取任意大的数并将它们减少 mod 2n。有符号数字 (%d) 在溢出时会导致未定义的行为。在这两种情况下, scanf 都不会(必然)返回有用的错误代码。不过,您应该始终检查 scanf 的返回值以捕获完全无效的输入。
    • 我的错! scanf 几乎完全没用! strtoul 会检查溢出,但 long 不一定是 32 位。读取字符串,检查最多 8 个十六进制数字,忽略初始 '0's 并将其传递给 strtoul 似乎是首选解决方案。
    【解决方案4】:

    您可以做的是先将用户输入存储到 char* 中:

    char rgba_str[20]; // 20 is an arbitrary larger buffer size
    printf("Enter rgba value: ");
    scanf("%s", &rgba_str);
    

    然后查看字符串的长度是否大于9位:

    if ( strlen( rgba_str ) > 8 )
      // Error
    

    如果不是,将rgba_str转为十六进制整数:

    else
      rgba = strtoul(rgba_str, NULL, 16);
    

    【讨论】:

      猜你喜欢
      • 2010-12-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-31
      • 2012-08-16
      • 2014-08-12
      • 2019-07-24
      • 1970-01-01
      相关资源
      最近更新 更多