C++进制转换除了求余、求商之外还可以通过st::string和std::stringstream来实现,至于二进制的运算可以由std::bitset来实现。
进制、类型转换 常用方法:
// C++ 进制、类型转换常用方法
std::string to_string( int value );
std::string to_string( long value );
std::string to_string( long long value );
std::string to_string( unsigned value );
std::string to_string( unsigned long value );
std::string to_string( unsigned long long value );
std::string to_string( float value );
std::string to_string( double value );
std::string to_string( long double value );
int stoi ( const std::string& str, std::size_t* pos = nullptr, int base = 10 );
long stol ( const std::string& str, std::size_t* pos = nullptr, int base = 10 );
long long stoll( const std::string& str, std::size_t* pos = nullptr, int base = 10 );
float stof ( const std::string& str, std::size_t* pos = nullptr );
double stod ( const std::string& str, std::size_t* pos = nullptr );
long double stold( const std::string& str, std::size_t* pos = nullptr );
【#include <string>】 https://en.cppreference.com/w/cpp/string/basic_string/to_string
int ivalue = 8;
std::string svalue = "";
std::stringstream ss; // 字符串流
ss << std::hex << ivalue;
// [std::dec, std::hex, std::oct](https://en.cppreference.com/w/cpp/io/manip/hex)
ss >> svalue;
ss.str(""); // 清空缓存
ss.clear(); // 清除标志位
【#include <sstream>】 https://en.cppreference.com/w/cpp/io/basic_stringstream
int ivalue = 8;
std::string svalue = "00111100";
std::bitset<N> bitivalue(ivalue); // int >> bitset<N>
std::bitset<N> bitsvalue(svalue); // string >> bitset<N>
bitivalue<<=2; // 左移2位 <<
bitsvalue>>=5; // 右移5位 <<
unsigned long ivalue = bitivalue.to_ulong(); // bitset<N> >> unsigned long
std::string svalue = bitsvalue.to_string();// bitset<N> >> std::string
【#include <bitset>】 https://en.cppreference.com/w/cpp/utility/bitset
下面调试了 C++ 进制、类型转换方法(实操):
std::cout<< "------------------------------------------------------------【C++ int】\n";
int decvalue = 99999; // 默认十进制
int binvalue = 0b111; // 二进制以 0b 开头
int octvalue = 07777; // 八进制以 0 开头
int hexvalue = 0xfff; // 16进制以 0x 开头
std::cout<< decvalue++ << "-"<< binvalue++ << "-"<< octvalue++ << "-"<< hexvalue++ << "\n";
std::cout<< decvalue << "-"<< binvalue << "-"<< octvalue << "-"<< hexvalue << "\n";
std::cout<< "------------------------------------------------------------【C++ <string>】\n";
int avalueint = 666;
std::string avluestr = std::to_string(avalueint); // int >> string
std::string bvluestr = "111";
int bvalueint = std::stoi(bvluestr); // string >> int(dec)
int bvaluebin = std::stoi(bvluestr, nullptr, 2); // string >> int(bin)
int bvalueoct = std::stoi(bvluestr, nullptr, 8); // string >> int(oct)
int bvaluehex = std::stoi(bvluestr, nullptr, 16); // string >> int(hex)
std::cout<< avalueint << "-\""<< avluestr << "\n";
std::cout<< bvluestr << "\"-"<< bvalueint << "-"<< bvaluebin << "-"<< bvalueoct << "-"<< bvaluehex << "\n";
/* reference
int stoi ( const std::string& str, std::size_t* pos = nullptr, int base = 10 );
long stol ( const std::string& str, std::size_t* pos = nullptr, int base = 10 );
long long stoll( const std::string& str, std::size_t* pos = nullptr, int base = 10 );
float stof ( const std::string& str, std::size_t* pos = nullptr );
double stod ( const std::string& str, std::size_t* pos = nullptr );
long double stold( const std::string& str, std::size_t* pos = nullptr );
index https://en.cppreference.com/w/cpp/string/basic_string/to_string
*/
std::cout<< "------------------------------------------------------------【C++ <sstream>】\n";
int ivalue = 8;
std::string svalue = "";
std::stringstream ss;
// 十进制整数 >> 十六进制字符串
ss << std::hex << "5a1f05";
ss << std::hex << ivalue;
ss >> svalue;
ss.str(""); // 清空缓存
ss.clear(); // 清除标志位
std::cout<<"十进制 >> 16进制 "<< ivalue << " - " << svalue <<"\n";
std::transform(svalue.begin(),svalue.end(), svalue.begin(), ::toupper);// 字母转大写
// https://en.cppreference.com/w/cpp/algorithm/transform
std::cout<<"十进制 >> 16进制 "<< ivalue << " - " << svalue <<"\n";
// 十进制整数 >> 字符串
ss << std::dec << ivalue;
ss >> svalue;
ss.str(""); // 清空缓存
ss.clear(); // 清除标志位
std::cout<<"十进制 >> 十进制 "<< ivalue << " - " << svalue <<"\n";
// 十进制整数 >> 八进制字符串
ss << std::oct << ivalue;
ss >> svalue;
ss.str(""); // 清空缓存
ss.clear(); // 清除标志位
std::cout<<"十进制 >> 八进制 "<< ivalue << " - " << svalue <<"\n";
// 十进制整数 >> 二进制字符串
ss << std::bitset<32>(ivalue);
ss >> svalue;
ss.str(""); // 清空缓存
ss.clear(); // 清除标志位
std::cout<<"十进制 >> 二进制 "<< ivalue << " - " << svalue <<"\n";
std::cout<< "------------------------------------------------------------【C++ <bitset>】\n";
int decnum = 7;
std::string strnumbin = "00111100";
std::string strnumhex = "A5D3F";
std::bitset<20> bitnumdec(decnum); // int >> bitset<N>
std::bitset<20> bitnumstrbin(strnumbin); // string(bin) >> bitset<N>
std::bitset<20> bitnumstrhex(std::stoi(strnumhex,nullptr,16));// string(hex) >> bitset<N>
bitnumdec<<=1; // 左移 <<
// index https://zh.cppreference.com/w/cpp/utility/bitset
unsigned long bit2intnum = bitnumdec.to_ulong(); // bitset<N> >> unsigned long
std::string bit2strnum = bitnumdec.to_string();// bitset<N> >> string(bin)
stringstream sss; // bitset<N> >> string(hex)
std::string bit2strhex = "";
sss << std::hex << stoi( bitnumdec.to_string(), nullptr, 2);
sss >> bit2strhex;
sss.str(""); // 清空缓存
sss.clear(); // 清除标志位
std::transform(bit2strhex.begin(),bit2strhex.end(), bit2strhex.begin(), ::toupper);// 字母转大写
std::cout<< decnum << "-" << bitnumdec <<"+" << strnumbin <<"-"<< bitnumstrbin << "-"<< bitnumstrhex << "\n";
std::cout<< bitnumdec << "-" << bit2intnum << "-" << bit2strnum << "-" << bit2strhex << "\n";
运行结果如下
------------------------------------------------------------【C++ int】
99999-7-4095-4095
100000-8-4096-4096
------------------------------------------------------------【C++ <string>】
666-"666 111"-111-7-73-273
------------------------------------------------------------【C++ <sstream>】
十进制 >> 16进制 8 - 5a1f058
十进制 >> 16进制 8 - 5A1F058
十进制 >> 十进制 8 - 8
十进制 >> 八进制 8 - 10
十进制 >> 二进制 8 - 00000000000000000000000000001000
------------------------------------------------------------【C++ <bitset>】
7-00000000000000001110+00111100-00000000000000111100-10100101110100111111
00000000000000001110-14-00000000000000001110-E
std::string 是在标准库 <string>(注意不是 C 语言中的 <string.h> 库)中提供的一个类,本质上是 std::basic_string<char> 的别称。以下是string常用方法:
std::string s;
std::string::size_type s.size(); // 返回 string 的长度
std::string::size_type s.length();
std::string::size_type s.find(str); // 查找字符串中 某 字符/字符串 第一次出现的位置
std::string::size_type s.find(str, pos); // 查找字符串中 某 字符/字符串 在 pos(含)之后第一次出现的位置
// 如果没有找到,则返回 std::string::npos
std::string substr(pos, len); // 从 pos 位置开始截取最多 len 个字符组成的字符串
// 如果从 pos 开始的后缀长度不足 len 则只截取这个后缀
std::string s.insert(index, count, 'c'); // 在 index 处连续插入 count 次字符 'c'
std::string s.insert(index, "str") // 在 index 处插入字符串 "str"
std::string s.erase(index,count); // 删除字符串 index 位置开始(含)的 count 个字符
std::string s.erase(index); // 删除 index 位置及以后的所有字符
std::string s.replace(pos, count, str); // 将从 pos 位置开始 count 个字符的子串替换为 str
std::string s.replace(first, last, str); // 将以 first 开始(含)、last 结束(不含)的子串替换为 str,其中 first 和 last 均为迭代器。
【#include <string>】https://en.cppreference.com/w/cpp/string/basic_string
在 C 语言里,也有很多字符串的函数,但是它们的参数都是 char 指针类型的,为了方便使用,string 有两个成员函数能够将自己转换为 char 指针——
data()/c_str()(它们几乎是一样的,但最好使用 c_str(),因为 c_str() 保证末尾有空字符,而 data() 则不保证)
参考 string - OI Wiki (oi-wiki.org)
虽然 int 和 char 可以互相转换,依据 ASII码 实现简单的判别或转换。
但对于单个字符而言,有如下些许常用的professional的方法:
int isalnum(int c); // 检查字符是否为字母或数字
int isalpha(int c); // 检查字符是否为字母
int islower(int c); // 检查字符是否为小写
int isupper(int c); // 检查字符是否为大写字符
int isdigit(int c); // 检查字符是否为数字
int isxdigit(int c); // 检查字符是为十六进制字符
int iscntrl(int c); // 检查字符是否为控制字符
int isgraph(int c); // 检查字符是否为图形字符
int isspace(int c); // 检查字符是否为空白间隔字符
int isblank(int c); // 检查字符是否为空白字符
int isprint(int c); // 检查字符是否为打印字符
int ispunct(int c); // 检查字符是否为标点符
int tolower(int c); // 转换字符为小写
int toupper(int c); // 转换字符为大写
【#include <cctype>】https://en.cppreference.com/w/cpp/header/cctype
// C++标准库 `<cctype>` 原作为 `<ctype.h>` 存在于 C 标准库
字符串是一种容器,可以直接调用 std::sort 对若干字符串进行排序。以下是字符串常用方法:
std::transform(svalue.begin(),svalue.end(), svalue.begin(), ::tolower);// 字母转小写
std::transform(svalue.begin(),svalue.end(), svalue.begin(), ::toupper);// 字母转大写
【#include <algorithm>】https://zh.cppreference.com/w/cpp/algorithm/transform // 字符变换
std::vector<int> v {3, 1, -4, 1, 5, 9};
std::vector<int>::iterator result = std::min_element(v.begin(), v.end()); // 容器中的最小值
std::vector<int>::iterator result = std::min_element(v.begin(), v.end(), [](int a, int b){ return std::abs(a) > std::abs(b); });
【#include <algorithm>】https://zh.cppreference.com/w/cpp/algorithm/min_element // 查找最小值
std::vector<int>::iterator result = std::max_element(v.begin(), v.end()); // 容器中的最大值
std::vector<int>::iterator result = std::max_element(v.begin(), v.end(), [](int a, int b){ return std::abs(a) < std::abs(b); });
【#include <algorithm>】https://zh.cppreference.com/w/cpp/algorithm/max_element // 查找最大值
int count = std::count(v.cbegin(), v.cend(), int target); // 计算容器内中 target 出现的个数
// 由 lambda 表达式计算能被 4 整除的元素个数
int count = std::count_if(v.begin(), v.end(), [](int i) { return i % 4 == 0; });
【#include <algorithm>】https://en.cppreference.com/w/cpp/algorithm/count // 容器计数
std::sort(v.begin(), v.end());
std::sort(v.begin(), v.end(), [](int a, int b){ return a > b; });
【#include <algorithm>】https://en.cppreference.com/w/cpp/algorithm/sort // 容器排序
有关容器的具体用法可以参考 C++常用标准库容器算法
std::stringstream ss;
ss << std::hex << "5a1f05";
ss.str(""); // 清空缓存
ss.clear(); // 清除标志位
【#include <sstream>】https://en.cppreference.com/w/cpp/io/basic_stringstream
std::bitset 是标准库中的一个存储 0/1 的大小不可变容器。严格来讲,它并不属于 STL。由于内存地址是按字节即 byte 寻址,而非比特 bit,一个 bool 类型的变量,虽然只能表示 0/1, 但是也占了 1 byte 的内存。std::bitset 就是通过固定的优化,使得一个字节的八个比特能分别储存 8 位的 0/1。其常用方法如下:
// 构造函数
std::bitset(); // 每一位都是 false
std::bitset(unsigned long val); // 整数
std::bitset(const string& str); // 值为 01 字符串
operator<<
operator<<= // 二进制左移
operator>>
operator>>= // 二进制右移
operator== // 比较其内容
operator&= // 二进制与
operator|= // 二进制或
operator^= // 二进制异或
operator~ // 二进制非
operator[] // 访问指定的位
bool x.all(); // 检查所有位是否全为 true
bool x.any(); // 检查存在被设为 true 的位
bool x.none(); // 检查没有被设为 true 的位
std::size_t x.count(); // 返回设置为 true 的位的数量
std::size_t x.size(); // 返回x的位数
std::bitset& x.set(); // 将所有位设置为 true
std::bitset& x.set(pos, value); // 将 pos 设置为 value
std::bitset& x.reset(); // 将所有位设置为 false
std::bitset& x.reset(pos); // 将 pos 设置为 false
std::bitset& x.flip(); // 翻转所有位的值
std::bitset& x.flip(pos); // 翻转 pos 的值
std::string x.to_string('0', '1'); // 转换为字符串表示 (对应值为 false 的位,值为 true 的位)
unsigned long x.to_ulong(); // 转换为整数表示
unsigned long long x.to_ullong(); // 转换为整数表示
【#include <bitset>】https://en.cppreference.com/w/cpp/utility/bitset
与
std::bitset相对应的是std::vector的一个特化std::vector<bool>(可以理解为节省空间的动态 bitset),其储存方式同std::bitset一样,区别在于后者支持动态开空间,std::bitset则和一般的静态数组一样,是在编译时就开好了的。然而,bitset 有一些好用的库函数,不仅方便,而且有时可以避免使用 for 循环而没有实质的速度优化。因此,一般不使用std::vector<bool>。
参考 bitset - (oi-wiki.org)
此外,由 GNU Compiler Collection (GCC) 提供支持的位操作:
auto x = 0ULL; // 无符号整数 (unsigned long long)
auto y = x; // 无符号整数 (unsigned long long)
__builtin_popcount(x);
__builtin_popcountl(x);
__builtin_popcountll(x); // 对应二进制中1的个数
__builtin_ctz(x);
__builtin_ctzl(x);
__builtin_ctzll(x); // 二进制下x末尾0的个数 (x=0 时结果未定义)
__builtin_clz(x);
__builtin_clzl(x);
__builtin_clzll(x); // 二进制下x前导0的个数 (x=0 时结果未定义)
【-】https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html // 编译器内置方法
对于无符号整数类型(即 unsigned char 、 unsigned short 、 unsigned int 、 unsigned long 、 unsigned long long 或扩展无符号整数类型)自 C++20 起支持如下位操作方法:
auto x = 0ULL; // 无符号整数 (unsigned long long)
auto y = x; // 无符号整数 (unsigned long long)
int std::popcount(x);
【#include <bit>】https://en.cppreference.com/w/cpp/numeric/popcount // 对应二进制中 1 的个数
int std::countl_zero(x); // 从最高位(“左”)起连续为 0 的位的数量
【#include <bit>】https://en.cppreference.com/w/cpp/numeric/countl_zero
int std::countl_one(x); // 从最高位(“左”)起连续为 1 的位的数量
【#include <bit>】https://en.cppreference.com/w/cpp/numeric/countl_one
int std::countr_zero(x); // 从最低位(“右”)起连续为 0 的位的数量
【#include <bit>】https://en.cppreference.com/w/cpp/numeric/countr_zero
int std::countr_one(x); // 从最低位(“右”)起连续为 1 的位的数量
【#include <bit>】https://en.cppreference.com/w/cpp/numeric/countr_one
bool std::has_single_bit(x);
【#include <bit>】https://en.cppreference.com/w/cpp/numeric/has_single_bit // 判断x是否为二的整数次幂
y = std::bit_ceil(x);
【#include <bit>】https://en.cppreference.com/w/cpp/numeric/bit_ceil // 不小于x的最小的二的整数次幂
y = std::bit_floor(x);
【#include <bit>】https://en.cppreference.com/w/cpp/numeric/bit_floor // 不大于x的最大的二的整数次幂
y = std::bit_width(x);
【#include <bit>】https://en.cppreference.com/w/cpp/numeric/bit_width // 计算存储x所需的位数
y = std::byteswap(x);
【#include <bit>】https://en.cppreference.com/w/cpp/numeric/byteswap // 翻转给定整数值 x 中的字节
y = std::rotl(x,3); // 左循环移位3位
【#include <bit>】https://en.cppreference.com/w/cpp/numeric/rotl // 将 x 左旋 s 位 (循环移位)
y = std::rotr(x,3); // 右循环移位3位
【#include <bit>】https://en.cppreference.com/w/cpp/numeric/rotr // 将 x 右旋 s 位 (循环移位)
- C++常用算术及标准库容器算法(Standard Template Library Containers, STLC)
- C++代码片段std::string 字符串分割
- C++数据类型及标准库容器(Standard Template Library Containers, STL)
- ...
代码调试不易,转载请标明出处!
如果感觉本文对您有帮助,请留下您的赞,您的支持是我坚持写作分享的最大动力,谢谢!
References
0.Standard C++
1.cppreference.com
2.apiref.com/cpp-zh
3.cplusplus.com
4.C++ 标准库参考 | Microsoft Learn
5.C++ 教程 | 菜鸟教程
6.C++ 二进制、字符串、十六进制、十进制
7.C++中substr()函数用法
可以肯定的是学海无涯,这篇文章也会随着对 C++ 的深入学习而持续更新,
欢迎各位在评论区留言进行探讨交流。