【问题标题】:C: Comparing two bytes to see if one is within a certain range of the otherC:比较两个字节,看一个是否在另一个的一定范围内
【发布时间】:2009-12-16 21:11:31
【问题描述】:

我正在编写比较代表整数的 2 个字节的代码。我想看看字节 R 是否与 G 的 +-10 相匹配。我遇到的代码问题是在接近结尾的 if 语句中进行比较。即使它们应该超出范围,字节也永远不会超出范围。我确信问题出在我如何添加/减去error_range,但我不知道有任何其他方法可以做到这一点。

我首先考虑将字节转换为整数,但我在网上找不到任何帮助。如果这比我在这里做的更好,请告诉我该怎么做。

感谢任何帮助!

const char ERROR_RANGE = 0x1010; //warning: overflow in implicit constant conversion
char R, G; /2 separate bytes
char buffer; //enough space for 1 byte

image = fopen(fileName,"r"); //open file

fread(&buffer, 1, 1, image); //read 1 byte  
memcpy (&R,&buffer,1); //store it as R

fread(&buffer, 1, 1, image); //read 1 byte   
memcpy (&G,&buffer,1); //store it as G

fclose(image);

if((R >= (G + ERROR_RANGE)) && (R <= (G - ERROR_RANGE)))
{
    printf("Outside of range!\n");
}

谢谢。

【问题讨论】:

  • 您有没有想过打印出 ERROR_RANGE 以查看初始化的内容?如果从文件中读取的值为 126,您还期望会发生什么?

标签: c byte


【解决方案1】:

你的问题是因为你的测试说:

if (R 大于等于 G + ERROR) AND (R 小于等于 G - ERROR)

不可能两者兼有。

首先将&amp;&amp; 替换为||

更好的测试是:

如果(R和G的差大于ERROR)

翻译为:

if (abs(R - G) > ERROR_RANGE)
{
    printf("Error");
}

【讨论】:

  • 哇,感谢您了解这一点。我绝对的意思是或!并感谢有关减去它们的建议!
  • @KMM - 如果我在使用复合 if 语句时遇到问题,我经常用英语或伪代码将它们写出来,我发现当我的 AND 和 OR 以错误的方式出现时更容易发现舍入或错过了一个 NOT
  • 如果你喜欢用英文写出来,这就是 iso646.h 的用途。
  • @Steve Jessop - 我的意思是在我的回答中,因为它带出了测试的含义,但我同意你的观点。
  • 抱歉,是的,英文布尔运算符别名不是完整的解决方案。但它们可能有助于避免眼睛可以略过 &&、|| 等作为“噪音”的问题。我想不利的一面是,如果您确实使用它们,那么您永远不会学习原始运算符。由于几乎没有人使用它们,因此您也无法阅读其他人的代码。
【解决方案2】:

第一个问题是您使用的是&amp;&amp;,而不是||。 R 不会太高也不会太低。

其次,您确定 R 和 G 会在合理范围内吗?如果您系统上的char 是无符号的,那么如果G 很小,G - ERROR_RANGE 很可能是一个大数字,而不是一个小数字。 最好使用if (abs(R - G) &lt;= ERROR_RANGE) 之类的东西。

【讨论】:

  • 由于 R 和 G 都是单字节,因此它们将在 'int' 支持的合理范围内(并且在比较或计算发生之前将值提升为 'int' ,当然 - 正常的促销活动)。
  • @Jonathan:谢谢你提醒我。但是,如果 char 在这个特定的实现上是未签名的(并且 IIRC 标准允许它是),它不会提升为 unsigned int 吗?在这种情况下,我们仍然遇到了问题。
  • @David:我们能遇到的最坏情况是什么? -128 和 +127 的'signed char',提升为 int?或者'unsigned char' 0和255,都提升为int(不需要去unsigned int);每种情况下的差异为±255,这很容易由'int'处理。我认为没有问题,除非值 0 和 255 相差 1,因为这些值是循环的。
  • @Jonathan:我的错。非常感谢你。我记错了促销规则。
【解决方案3】:

除了已经指出的......

值 0x1010 太大而无法容纳在一个字节中,两个字节的差异永远不会超过 255 (0xff)。您的意思是 1010 二进制(== 10 十进制 == 0xA 十六进制)?

另外,无需读取和复制,直接读取变量即可:

fread(&R, 1, 1, image); //read 1 byte  
fread(&G, 1, 1, image); //read 1 byte   

【讨论】:

  • 是的,我的意思是十进制的 10。非常感谢。
【解决方案4】:

有什么原因你不能使用类似的东西:

if (abs(R-G) > ERROR_RANGE)
    // ...

【讨论】:

    【解决方案5】:

    这是我的尝试,未经测试:

    unsigned char buffer[2];
    int r, g, diff;
    
    image = fopen(fileName, "r");
    fread(&buffer, 2, 1, image);
    
    r = buffer[0];
    g = buffer[1];
    dif = r - g;
    
    if (abs(dif) > 10) { printf... }
    

    它使用abs 函数来使差异始终为正...更容易以这种方式进行比较。一次读取前 2 个字节的性能略有提高。将(无符号)字符分配给整数将使它们易于比较。

    【讨论】:

      猜你喜欢
      • 2012-12-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多