【问题标题】:What is wrong with my algorithm?我的算法有什么问题?
【发布时间】:2010-02-07 07:15:02
【问题描述】:

好的,我已经编写了一些代码来反转十六进制字符,作为我编造的有趣练习的一部分。

这是我目前拥有的:

#include <stdio.h>  
int main() {  
    char a,b,c;  
    while (1) {  
        c = getchar();  
        if (!feof(stdin)) {  
            a = c % 16;  
            b = (c - a) / 16;  
            c = (a*16) + b;  
            putchar(c);  
        }else{break;}  
    }  
return 0;  
}  

它适用于大多数值。比如 0xA0 变成 0x0A 等等……

但是,它不适用于以“F”开头的值。

0xF1 变成 0x10
0xFF 变为 0xF0
等等……

有人能指出我正确的方向吗?

【问题讨论】:

  • 你需要一些空间来让你的数学工作。对 a 和 b 使用 int 而不是 char。或者切换到使用按位运算(>>
  • @KennyTM:你的意思可能是putchar(cc&gt;&gt;4|(cc&amp;0xf)&lt;&lt;4);
  • 附加说明:在除以 16 之前,无需从 c 中减去 ab = c / 16 将得到完全相同的结果。这就是 C 中整数除法的工作原理。

标签: c algorithm math


【解决方案1】:

如果你的系统上是char签名,那么当c的高半字节为f时,c为负数,c%16会给出负数结果。

【讨论】:

    【解决方案2】:

    您正在使用签名(在您的机器上)数据类型。将其切换为无符号,它应该可以正常工作。

    【讨论】:

    • 您已经得到了解决方案,但请注意 char 可以签名或未签名,具体取决于实现。
    • 确实!谢谢!现在,因为如果我只是使用它,我将永远不会学习。您不介意解释为什么签名在 char 中很重要吗?或者指出一些来源?
    • 你可能会觉得这个链接有点过于笼统,但它实际上是一篇非常有趣的文章:en.wikipedia.org/wiki/Integer_(computer_science)
    • Tangrs:显然您的签名 char 是 8 位,因此不能存储像 0xFF 这样的值(或任何大于 127 / 0x7F 的值)。最高位设置的值是负数 - 例如,0xF0 实际上是 -16。您的算法仅适用于正数。
    • char 的签名应该无关紧要,这就是为什么它是由实现而不是由语言固定的细节。如果您使用的是 C++,则在处理原始数据时使用的正确数据类型是字节,它是无符号的。在 C 中,或者您明确声明 char 的符号性或(如其他人所述)仅使用不受符号性影响的按位运算。
    【解决方案3】:

    我不知道为什么有人在做 *, /, % 操作,而简单的按位操作可以做这些事情。

    a = (c & 0x0F) b = (c & 0xF0) >> 4;
    c = a|b;

    【讨论】:

    • 恰恰相反。我不知道为什么有人会使用按位运算,而正常的人类算术也能做到这一点。
    • 因为机器比“正常的人类算术”要快
    【解决方案4】:

    getcharputchar 返回并获取 ints。甚至比这更好,他们使用char 转换为unsigned char 的值,这意味着对于所有有效字符putchar 将返回一个正值。这是您的算法所必需的,因为您使用 %,否则您将需要依赖实现定义的行为。

    如果您将getchar 的值分配给int,那么您可以通过与EOF 进行比较来测试读取是否因任何原因(不仅仅是流结束)而失败。使用feof 就没有必要了——以前还不够。

    例如

    int main(void) {  
        int c;  
        while ((c = getchar()) != EOF) {  
            /* algorithm goes here */
            putchar(c);  
        }  
        return 0;  
    }
    

    【讨论】:

      猜你喜欢
      • 2013-12-25
      • 2013-12-25
      • 1970-01-01
      • 1970-01-01
      • 2011-12-03
      • 2016-09-19
      • 1970-01-01
      • 2011-08-22
      • 2014-12-27
      相关资源
      最近更新 更多