本文讨论二进制、八进制、十六进制三者之间不限制QString长度的进制转换算法。对于涉及十进制且不限制QString长度的进制转换,本人能力有限,不能解决该问题,故不做讨论。
Qt有提供进制转换,但受限于类型长度,占用最大空间的qint64(qlonglong)类型为8个字节,64位,所能表示的数字有限,所以有长度限制。
如果涉及十进制转换问题,可以暂且使用Qt提供的方法,只是要牺牲不限制字符串长度这一要求。
二进制 至 八进制
3个二进制位即可表示一个八进制数字。所以将二进制字符串以3个为一组,进行转换。
QString twoToEight(const QString& in){
int inLen=in.size();
QString out;
int singleNum=0; //单个八进制数字
for(int i=inLen-1;i>=0;i--){
int num=in.at(inLen-i-1).digitValue(); //从首位开始向后取,与循环方向相反
int mod=i%3; //对应一组中的位置 不同的位置不同的权
switch(mod){
case 0:singleNum+=num;out.append(QString::number(singleNum));singleNum=0;break;
case 1:singleNum+=num*2;break;
case 2:singleNum+=num*4;break;
}
}
return out;
}
二进制 至 十六进制
跟二进制至八进制差不多,不同的是,4个二进制位可表示一个十六进制数字,所以将二进制字符串4个为一组,进行转换。
QString twoToHex(const QString& in){
int inLen=in.size();
QString out;
int singleNum=0; //单个十六进制数字
for(int i=inLen-1;i>=0;i--){
int num=in.at(inLen-i-1).digitValue(); //从首位开始向后取,与循环方向相反
int mod=i%4; //对应一组中的位置 不同的位置不同的权
switch(mod){
case 0:singleNum+=num;out.append(QString::number(singleNum,16));singleNum=0;break;
case 1:singleNum+=num*2;break;
case 2:singleNum+=num*4;break;
case 3:singleNum+=num*8;break;
}
}
return out;
}
八进制 至 二进制
一个八进制字符可以转换为3个二进制字符,与二进制转八进制相反。
QString eightToTwo(const QString& in){
int inLen=in.size();
QString out;
for(int i=0;i<inLen;i++){
quint8 num=in.at(i).digitValue();
quint8 one=num/4;
quint8 two=num%4/2;
quint8 three=num%4%2;
out.append(QString("%1%2%3").arg(one).arg(two).arg(three));
}
while(out.startWith('0'))out.remove(0,1);//清除前面的0
return out;
}
八进制 至 十六进制
因为1个八进制位可以表示为3个二进制位,1个十六进制位可以表示为4个二进制位,3和4不存在整数倍关系,所以不能直接转换,需要先将八进制转化为二进制,再将二进制转化为十六进制。
QString in="76543210"; //八进制字符串
QString hex=twoToHex(eightToTwo(in)); //先将八进制转化为二进制,再将二进制转换为16进制。
十六进制 至 二进制
与八进制转换二进制相似。
QString hexToTwo(const QString& in){
int inLen=in.size();
QString out;
for(int i=0;i<inLen;i++){
quint8 num=in.at(i).digitValue(16);
quint8 one=num/8;
quint8 two=num%8/4;
quint8 three=num%8%4/2;
quint8 four=num%8%4%2;
out.append(QString("%1%2%3%4").arg(one).arg(two).arg(three).arg(four));
}
while(out.startWith('0'))out.remove(0,1);//清除前面的0
return out;
}
十六进制 至 八进制
先将十六进制转换为二进制,再将二进制转换为十六进制。
QString in="FEDCBA9876543210";
QString out=twoToEight(hexToTwo(in));//先将十六进制转化为二进制,再将二进制转换为八进制。
注意
本文的输入是在绝对理想的情况下,输入的字符串决不存在不符合规则的字符。如果输入的字符串中有非法字符的可能,请自行处理。如果数据来源于输入框,可以给输入框设置相应的约束器,使得输入框中不允许输入不合乎规则的字符。