因此,对于作业,我必须将字符(0
- F
)转换为整数(0
- 15
),0
- { {1}}工作正常,但如果给出任何字母,则会打印一个随机数:例如,对于9
,它会C
,而19
则会返回D
这是我的方法:
20
起初我的if语句是这样的:
int char2int(char digit) {
int i = 0;
if (digit == 0 || 1 || 2 || 3 || 4 || 5 || 6 || 7 || 8 || 9)
i = digit - '0';
else
if (digit == 'A' || 'B' || 'C' || 'D' || 'E' || 'F')
i = digit - '9';
else
i = -1;
return i;
}
但这造成了一些错误。你可以告诉我我不太了解C.我当前的If声明有效,但我确定它不必要很长。
答案 0 :(得分:4)
if(digit == 0 || 1 || 2 || 3 || 4 || 5 || 6 || 7 || 8 || 9)
这不是条件表达式在C中的工作方式。
您需要将digit
分别与每个数字进行比较
if (digit == '0' || digit == '1' || digit == '2' ...
或以聪明的方式做到:
if(digit >= '0' && digit <= '9')
^^ not =<
请注意,我将'
放在数字周围,因为您要将数字与字母0 进行比较,而不是数字(不同的数字请参见here所有ASCII字符值)。
答案 1 :(得分:1)
当你开始时,你走的是正确的道路,但是稍微走开了。试试这个
#include <ctype.h>
int char2int(char d) {
if (!isxdigit(d)) {
return -1;
}
if (isdigit(d)) {
return d - '0';
}
return (tolower(d) - 'a') + 10;
}
如果你更喜欢接近范围测试的方法,你可以这样做:
int char2int(char d) {
if (d >= '0' && d <= '9') {
return d - '0';
}
d = tolower(d);
if (d >= 'a' && d <= 'f') {
return (d - 'a') + 10;
}
return -1;
}
答案 2 :(得分:1)
假设ASCII以下内容从字符(0-9,a-f,A-F)转换为相关的无符号整数(0-15)。任何其他字符也将转换为... 0-15范围内的某个随机值。垃圾进,垃圾出。
unsigned hexToUnsigned(char ch) {
return ((ch | 432) * 239'217'992 & 0xffff'ffff) >> 28;
}
具有32位整数的CPU通常能够忽略0xffff&#39; ffff屏蔽。在我的机器上,编译器将此函数转换为:
hexToUnsigned PROC
movsx eax, cl
or eax,1B0h
imul eax, eax, 0E422D48h
shr eax, 1ch
ret 0
hexToUnsigned ENDP
另一种常见的方法是减少明显的操作(只有三个),返回无效字符的总垃圾(这可能没问题),但也需要除法(将其从最高点取出):
return ((ch | ('A' ^ 'a')) - '0') % 39;
为了说明编译器对除法的看法,他们(至少在x64上)将其变为倒数乘以得到乘积,然后再乘以并减去,如果你需要余数:
hexToUnsigned PROC
; return ((ch | ('A' ^ 'a')) - '0') % 39;
movsx r8d, cl
mov eax, -770891565
or r8d, 32
sub r8d, 48
imul r8d
add edx, r8d
sar edx, 5
mov ecx, edx
shr ecx, 31
add edx, ecx
imul ecx, edx, 39
sub r8d, ecx
mov eax, r8d
ret 0
hexToUnsigned ENDP
答案 3 :(得分:0)
返回值不是随机的。每个ascii字符在内存中用值表示。每个ascii字符的值可以在。中找到 Ascii Table
其他响应会告诉您条件表达式的错误,但另一个错误是如果字符是A,B,C,D,E或F,则需要将其转换为int {{1这意味着取A,B,C,D,E或F的值减去最小值A,然后加到该值。
此外,您可以看到,如果您不需要字符的确切值,则可以在不使用ascii表的情况下使用字母连续的属性。
答案 4 :(得分:0)
如果您愿意将char
等假设编码为ASCII和2的补码,则以下内容非常有效。
此代码不是为了提高可读性。如果需要考虑,请使用其他解决方案。这是为了严格编码。对于给定的处理器,它大约是10条指令。您的结果会有所不同。
减1.这使char
值向下移动1.特别是,A-Z现在是64-89,a-z在96-121范围内。
测试一个位(64位)是否清除:在'0' - '9'的范围内。如果是这样,则增加7并使用掩码保持该位(64位)清零。
否则屏蔽一下以将a-z折叠到A-Z范围内。
现在'0'到'9'和'A'到'Z'处于连续范围内。只需减去54.除unsigned char
,0-9
和A-Z
以外的所有a-z
值都将具有值&gt; 35.这对任何以36为基础的基础用途都很有用。
int Value(char ch) {
if (!(--ch & 64)) { // decrement, if ch in the '0' to '9' area ...
ch = (ch + 7) & (~64); // move 0-9 next to A-Z codes
} else {
ch &= ~32;
}
ch -= 54; // -= 'A' - 10 - 1
if ((unsigned char)ch > 15) {
; // handle error
}
return (unsigned char)ch;
}
答案 5 :(得分:0)
在redis中
https://github.com/antirez/redis/blob/3.2.8/src/sds.c#L892
int hex_digit_to_int(char c) {
switch(c) {
case '0': return 0;
case '1': return 1;
case '2': return 2;
case '3': return 3;
case '4': return 4;
case '5': return 5;
case '6': return 6;
case '7': return 7;
case '8': return 8;
case '9': return 9;
case 'a': case 'A': return 10;
case 'b': case 'B': return 11;
case 'c': case 'C': return 12;
case 'd': case 'D': return 13;
case 'e': case 'E': return 14;
case 'f': case 'F': return 15;
default: return 0;
}
}