【GESP/CSP】编程武器库-3, 十六进制转换十进制
前文(【GESP/CSP】编程武器库-2, 十进制转换十六进制),我们介绍了从十进制到十六进制的处理手段,很显然这只做到了一半。在之前做过的【GESP】C++四级真题 luogu-B3869 [GESP202309 四级] 进制转换题目中,需要将不同进制的数字转换成十进制表示出来,其中十六进制由于涉及字母,相对特殊,其他进制类比即可,今天就专门总结下这个知识点,希望下次遇到可以”信手拈来”。
当前武器库清单
分类 | 功能 | 教程 |
---|---|---|
字符判断 | 判断是否为数字(0-9) | 【GESP/CSP】编程武器库-1, 字符类型判断 |
字符判断 | 判断是否为字母(a-z/A-Z) | 【GESP/CSP】编程武器库-1, 字符类型判断 |
字符判断 | 判断是否为大写字母(A-Z) | 【GESP/CSP】编程武器库-1, 字符类型判断 |
字符判断 | 判断是否为小写字母(a-z) | 【GESP/CSP】编程武器库-1, 字符类型判断 |
进制转换 | 十进制和十六进制转换 | 【GESP/CSP】编程武器库-2, 十进制转换十六进制 |
本人也是边学、边实验、边总结。因此本文更多的不是一个教程,而是个人知识梳理,如有遗漏、疏忽,欢迎指正、交流。
一、十六进制值(整型变量)直接输出
在 C++ 代码中,可以直接写十六进制常量。它们一般以 0x
开头,例如 0xFF
。编译器会自动识别为十进制数存储。所以,如果只想把十六进制整数常量显示为十进制,直接输出即可:
1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>
using namespace std;
int main() {
int a = 0xFF; // 十六进制 0xFF 转换后存储为十进制 255
int b = 0x1A; // 十六进制 0x1A 转换后存储为十进制 26
cout << "a = " << a << endl; // 255
cout << "b = " << b << endl; // 26
cout << "a + b = " << a + b << endl; // 281
return 0;
}
输出:
1
2
3
a = 255
b = 26
a + b = 281
说明:
- 虽然书写时用了十六进制,但变量内部保存的就是对应的十进制数。
- 之后就能像普通整数一样进行运算。
这种情况下其实是不涉及什么转换操作的。因此,如果题目是可以用整型进行存储计算的,那么当从控制台读取输入的时候,也直接将十六进制输入格式,读取成整数就好了。
用户直接输入十六进制格式整数,可以使用 输入控制符 hex
:
1
2
3
4
5
6
7
8
9
10
11
#include <iostream>
using namespace std;
int main() {
int num;
cout << "请输入一个十六进制数 (如 FF 或 0x1A): ";
cin >> hex >> num; // 按十六进制解析输入
cout << "对应的十进制是: " << dec << num << endl;
return 0;
}
运行示例:
1
2
输入:FF/0xFF
输出:对应的十进制是: 255
二、十六进制字符串转换
有时十六进制数以 字符串形式 存在,例如 "FF"
、"0x1A"
;或者是用户 从控制台输入的字符串。 这时需要额外的转换。
1. 内置函数stoi
方法
C++11 提供了 stoi
函数,可以直接把字符串转为整数,并指定进制:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
#include <string>
using namespace std;
int main() {
string s1 = "FF"; // 十六进制字符串
string s2 = "0x1A"; // 带 0x 前缀
int num1 = stoi(s1, nullptr, 16); // 转换为十进制
int num2 = stoi(s2, nullptr, 16);
cout << "num1 = " << num1 << endl; // 255
cout << "num2 = " << num2 << endl; // 26
return 0;
}
输出:
1
2
num1 = 255
num2 = 26
说明:
stoi
的函数原型大致是这样的:
1
int stoi(const string& str, size_t* pos = 0, int base = 10);
- 第一个参数
str
:要转换的字符串。 - 第二个参数
pos
:指向size_t
类型的指针,用来存储“第一个未被转换字符”的下标位置。 - 第三个参数
base
:进制,常用10
(十进制)、16
(十六进制)等。
第一、第三个参数都好理解,举例介绍下第二个参数的作用,感兴趣的了解即可,实际使用中,基本可以无脑传nullptr
。
1.1 补充介绍stoi第二个参数用法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>
#include <string>
using namespace std;
int main() {
string s = "0xFFend";
size_t idx;
int num = stoi(s, &idx, 16);
cout << "num = " << num << endl; // 输出 255
cout << "idx = " << idx << endl; // 输出 5, 表示第一个未被转换字符的下标位置
cout << "剩余部分: " << s.substr(idx) << endl; // 输出 end
return 0;
}
输出:
1
2
3
num = 4094
idx = 5
剩余部分: nd
👉 stoi
只解析 "0xFF"
,把 end
留了下来。
2. 手动算法
如果你不习惯记忆函数用法,或者某些题目有特殊要求,你也可以按照进制转换逻辑,手动实现一个进制转换的函数
进制转换的基本逻辑为:十六进制 "1A"
= 1 × 16^1 + 10 × 16^0 = 26
。
因此代码实现的核心思想为:把十六进制字符串从左到右逐位扫描,每遇到一位就将其转换成 0–15 的数值,然后“高位先走”——把前面已经算好的结果整体乘以 16,再加上当前这一位的值。
一句话:“逢位乘 16 再加新值”,循环一遍就把整个十六进制字符串累加成了十进制整数。
代码示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <iostream>
#include <string>
using namespace std;
int hexToDec(const string& s) {
int result = 0;
for (char c : s) {
int value;
if (c >= '0' && c <= '9') {
value = c - '0';
} else if (c >= 'A' && c <= 'F') {
value = c - 'A' + 10;
} else if (c >= 'a' && c <= 'f') {
value = c - 'a' + 10;
} else {
continue; // 跳过不合法字符
}
result = result * 16 + value;
}
return result;
}
int main() {
string s = "FE";
cout << hexToDec(s) << endl; // 输出 254
return 0;
}
输出:
1
254
上述代码为十六进制字符串转换成十进制整数核心逻辑。不支持有进制前缀0x
的情况,如果有前缀,你只需要先截取掉,在按上述代码处理即可。这里就不再赘述,留作读者自己实现。
所有代码已上传至Github:https://github.com/lihongzheshuai/yummy-code
GESP 学习专题站:GESP WIKI
“luogu-”系列题目可在洛谷题库进行在线评测。
“bcqm-”系列题目可在编程启蒙题库进行在线评测。
欢迎加入:Java、C++、Python技术交流QQ群(982860385),大佬免费带队,有问必答
欢迎加入:C++ GESP/CSP认证学习QQ频道,考试资源总结汇总
欢迎加入:C++ GESP/CSP学习交流QQ群(688906745),考试认证学员交流,互帮互助