如果您有一个在"0"到"9"范围内的字符,如何将其转换为0到9 的int值
然后你怎么把它转换回来?
同样给定字母"A"到"Z"或"A"到"Z",如何将它们转换为0-25的范围,然后再转换回来?
可以针对ASCII 进行优化
C++指定的基本字符编码使转换到"0"-"9"变得容易。
C++指定:
在源和执行基本字符集中,上述十进制数字列表中0之后的每个字符的值都应比前一个字符的值大一。
这意味着,无论"0"的整数值是什么,"1"的整值都是'0' + 1
,"2"的积分值是'0' + 2
,依此类推。使用这些信息和基本的算术规则,您可以轻松地将char转换为int并返回:
char c = ...; // some value in the range '0' - '9'
int int_value = c - '0';
// int_value is in the range 0 - 9
char c2 = '0' + int_value;
将字母"a"到"z"转换为0到25之间的数字并不容易,因为C++没有指定这些字母的值是连续的。在ASCII中,它们是连续的,您可以编写依赖于类似于"0"-"9"的上述代码的代码。(如今ASCII在任何地方都被广泛使用)。
可移植代码将使用查找表或对每个字符进行特定检查:
char int_to_char[] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'};
int char_to_int[CHAR_MAX + 1] = {};
for (int i=0; i<sizeof(int_to_char); ++i) {
char_to_int[int_to_char[i]] = i;
}
// convert a lowercase char letter to a number in the range 0 - 25:
int i = char_to_int['d'];
// convert an int in the range 0 - 25 to a char
char c = int_to_char[25];
在C99中,您可以直接初始化char_to_int[]
数据,而无需循环。
int char_to_int[] = {['a'] = 0, ['b'] = 1, ['c'] = 2, ['d'] = 3, ['e'] = 4, ['f'] = 5, ['g'] = 6, ['h'] = 7, ['i'] = 8, ['j'] = 9, ['k'] = 10, ['l'] = 11, ['m'] = 12, ['n'] = 13, ['o'] = 14, ['p'] = 15, ['q'] = 16, ['r'] = 17, ['s'] = 18, ['t'] = 19, ['u'] = 20, ['v'] = 21, ['w'] = 22, ['x'] = 23, ['y'] = 24, ['z'] = 25};
同样支持C99的C++编译器也可以在C++中支持这一点,作为扩展。
这里有一个完整的程序,可以生成在这些转换中使用的随机值。它使用C++,加上C99指定的初始化扩展。
#include <cassert>
int digit_char_to_int(char c) {
assert('0' <= c && c <= '9');
return c - '0';
}
char int_to_digit_char(int i) {
assert(0 <= i && i <= 9);
return '0' + i;
}
int alpha_char_to_int(char c) {
static constexpr int char_to_int[] = {['a'] = 0, ['b'] = 1, ['c'] = 2, ['d'] = 3, ['e'] = 4, ['f'] = 5, ['g'] = 6, ['h'] = 7, ['i'] = 8, ['j'] = 9, ['k'] = 10, ['l'] = 11, ['m'] = 12, ['n'] = 13, ['o'] = 14, ['p'] = 15, ['q'] = 16, ['r'] = 17, ['s'] = 18, ['t'] = 19, ['u'] = 20, ['v'] = 21, ['w'] = 22, ['x'] = 23, ['y'] = 24, ['z'] = 25};
assert(0 <= c && c <= sizeof(char_to_int)/sizeof(*char_to_int));
int i = char_to_int[c];
assert(i != 0 || c == 'a');
return i;
}
char int_to_alpha_char(int i) {
static constexpr char int_to_char[] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'};
assert(0 <= i && i <= 25);
return int_to_char[i];
}
#include <random>
#include <iostream>
int main() {
std::random_device r;
std::seed_seq seed{r(), r(), r(), r(), r(), r(), r(), r()};
std::mt19937 m(seed);
std::uniform_int_distribution<int> digits{0, 9};
std::uniform_int_distribution<int> letters{0, 25};
for (int i=0; i<20; ++i) {
int a = digits(m);
char b = int_to_digit_char(a);
int c = digit_char_to_int(b);
std::cout << a << " -> '" << b << "' -> " << c << 'n';
}
for (int i=0; i<20; ++i) {
int a = letters(m);
char b = int_to_alpha_char(a);
int c = alpha_char_to_int(b);
std::cout << a << " -> '" << b << "' -> " << c << 'n';
}
}
有两种主要的转换方法:查找和数学
在这个答案中,所有ASCII值都用十进制概念表示
请注意,在ASCII中:'0' is 48
、'A' is 65
和'a' is 97
查找:
在查找版本中,您有一个char
数组,然后将映射的值放置在该数组中,并创建一个int数组以转换回:
为了在将char
映射到int
时验证并获得相应的值:
0 will be a sentinal value to mean not mapped: out of range
all results will be one more than expected
unsigned char
用于确保正确处理带符号的负字符
而'C'允许符号{[A']=1,['B']=2,…},C++没有,因此通常可以使用以下代码来填充查找表:
void fill_lookups(unsigned char * from_table, int from_size, int * to_table)
{
for (int i = 0; i < from_size; ++i)
{
to_table[from_table[i]]=i+1; // add one to support 0 as "out of range"
}
}
unsigned char int_to_char[]={ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
unsigned char int_to_lower[]={'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
'u', 'v', 'w', 'x', 'y', 'z'};
unsigned char int_to_upper[]={'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
'U', 'V', 'W', 'X', 'Y', 'Z'};
int char_to_int[UCHAR_MAX+2] = {}; // This will return 0 for non digits
int letter_to_offset[UCHAR_MAX+2] = {}; // This will return 0 for non alpha
fill_lookups(int_to_char, sizeof(int_to_char), char_to_int);
fill_lookups(int_to_lower, sizeof(int_to_lower), letter_to_offset);
fill_lookups(int_to_upper, sizeof(int_to_upper), letter_to_offset);
// Helper function to check in range and always reduce in range lookups by 1
int to_int(int * table, unsigned char c, bool * in_range)
{
int ret = table[c];
if (ret)
{
*in_range=(1==1); // for C/C++ true
--ret;
}
else
{
*in_range=(0==1); // for C/C++ false
}
return ret;
}
bool in_range; // always true in these cases
int a=to_int(char_to_int, '7', &in_range); // a is now 7
char b=int_to_char[7]; // b is now '7'
int c=to_int(letter_to_offset, 'C', &in_range); // c=2
int d=to_int(letter_to_offset, 'c', &in_range); // d=2
char e=int_to_upper[2]; // e='C'
char f=int_to_lower[2]; // f='c'
虽然这是可行的,如果需要验证或其他查找,这可能是有意义的,但是。。。
通常,更好的方法是使用数学方程。
数学(alpha适用于ASCII)
假设转换已经被验证在正确的范围内:(C型铸造用于C或C++)
请注意,"0"-"9"在C和C++中是连续的
对于ASCII,"A-Z"one_answers"A-Z"不仅是连续的,而且'A' % 32
和'a' % 32
都是1
int a='7'-'0'; // a is now 7 in ASCII: 55-48=7
char b=(char)7+'0'; // b is now '7' in ASCII: 7 + 48
int c='C' % 32 - 1; // c is now 2 in ASCII : 67 % 32 = 3 - 1 = 2
-或者-我们知道它是大写的
int c='C'-'A'; // c is now 2 in ASCII : 67 - 65 = 2
int d='c' % 32 - 1; // d is now 2 in ASCII : 99 % 32 = 3 - 1 = 2
-或者-,我们知道它是小写的
int d='c'-'a'; // d is now 2 in ASCII : 99 - 97 = 2
char e=(char)2 + 'A'; // e is 'C' in ASCII : 65 + 2 = 67
char f=(char)2 + 'a'; // f is 'c' in ASCII : 97 + 2 = 99
如果您知道字符c
是字母或数字,您可以执行以下操作:
int cton( char c )
{
if( 'a' <= c ) return c-'a';
if( 'A' <= c ) return c-'A';
return c-'0';
}
在c
上添加任何需要的错误检查。
要将整数n
转换回char
,只需执行'0'+n
(如果需要数字)、'A'+n
(如果需要大写字母)和'a'+n
(如果需要小写字母)即可。
注意:这适用于ASCII(因为OP被标记了。)不过请参阅Pete的信息性评论。
如果我理解正确,你想这样做:
#include <ctype.h> /* for toupper */
int digit_from_char(char c) {
return c - '0';
}
char char_from_digit(int d) {
return d + '0';
}
int letter_from_char(char c) {
return toupper(c) - 'A';
}
char char_from_letter(int l) {
return l + 'A';
}