我的算法有什么问题?

6

好的,我已经准备好一些代码来反转十六进制字符,作为我想出的一个有趣的练习的一部分。

目前我拥有以下代码:

#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
等等...

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


4
你需要一些数学计算的余量。使用int替换a和b的char类型。或者转而使用位运算(>> << & 和 |)代替数学运算。 - John Knoeller
@KennyTM:你可能是指 putchar(cc>>4|(cc&0xf)<<4); - mjv
1
另外需要注意的是:在将c除以16之前,无需从a中减去cb = c / 16将会给出完全相同的结果。这就是C语言中整数除法的工作原理。 - AnT stands with Russia
4个回答

7

如果在您的系统中 char 是有符号的,那么当 c 的高位字节为 f 时,c 就是负数,并且 c%16 的结果将为负数。


5

你正在使用一个已签名的(在你的设备上)数据类型。将其转换为未签名的,应该可以正常工作。


2
你已经找到了解决方案,但请注意char的符号取决于具体的实现方式。 - Khaled Alshaya
当然!谢谢!现在,如果我只是使用它,我永远不会学到东西。您介意解释一下char的有符号性为什么很重要吗?或者指向一些资源? - tangrs
2
显然,你的有符号 char 是8位的,因此无法存储像 0xFF(或任何大于127/0x7F的值)。最高位设置的值为负 - 例如,0xF0 实际上是 -16。你的算法只能正确处理正数。 - caf
char的有符号性不应该影响程序,这是实现细节而不是语言规定。如果你在使用C++,处理原始数据时正确的数据类型是byte,它是无符号的。在C中,你可以明确指定char的有符号性或者(如其他人所说)使用位运算,这些运算不受有符号性的影响。 - akappa
akallio:无符号字符与标准库更好地互操作(例如,由strcmp执行的比较是根据解释为“unsigned char”的字符完成的)。 - caf
显示剩余4条评论

0

getcharputchar返回和接受int。更好的是,它们使用char强制转换为unsigned char的值,这意味着对于所有有效字符,putchar将返回一个正值。这对于您的算法是必需的,因为您使用%,否则需要依赖于实现定义的行为。

如果将getchar的值分配给int,则可以通过与EOF进行比较来测试读取失败的原因(不仅仅是流结束)。然后不需要使用feof - 以前它是不够的。

例如:

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

0
我不知道为什么有人会使用 *, /, % 运算符,而简单的位运算就可以完成这些操作。
a = (c & 0x0F) << 4; b = (c & 0xF0) >> 4; c = a|b;

恰恰相反,我不知道为什么有人会使用位运算,当普通的人类算术同样可以做到这件事情。 - AnT stands with Russia
因为对于计算机来说,它们比“普通人的算数”更快。 - vrrathod

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接