问题描述
给定n个十六进制正整数,输出它们对应的八进制数。
输入格式
输入的第一行为一个正整数n (1<=n<=10)。
接下来n行,每行一个由0~9、大写字母A~F组成的字符串,表示要转换的十六进制正整数,每个十六进制数长度不超过100000。
输出格式
输出n行,每行为输入对应的八进制正整数。
【注意】
输入的十六进制数不会有前导0,比如012A。
输出的八进制数也不能有前导0。
样例输入
2
39
123ABC
样例输出
71
4435274
#include<stdio.h> #include<string> #include<iostream> #include<string.h> using namespace std; char a[16][5] = {"0000","0001","0010","0011","0100","0101","0110","0111","1000","1001","1010","1011","1100","1101","1110","1111"}; int main(){ int n; char x[100000]; scanf("%d",&n); while(n--){ scanf("%s",x); string y; int lon = strlen(x); for(int i = 0; i < lon;i++){ int num; // 根据16进制字符串 从前往后 构建拼接 二进制字符串 if(x[i] >= 65 && x[i] <= 70){ //如果是 十六进制ABCDEF num = x[i] - 55; y.append(a[num]); }else{//十六进制的数字 num = x[i] -48; y.append(a[num]); } } int mk; int lon2 = y.size(); if(y[0] == '0'){ //如果该二进制字符串首字符是'0' for(int i = 1; i < lon2;i++) if(y[i] != '0'){ mk = i; break; }//二进制字符串首部有几位连续的'0' //按照'0'的位数向前移动字符串 for(int i = 0; i < lon2-mk;i++) y[i] = y[i+mk]; //将字符串最后由于移动而无效的位置删除 y.erase(lon2-mk,mk); } //由于字符串可能向前移动,所以一定要重新获取字符串的长度 lon2 = y.size(); int j = 0; int all = 0; int cc = 1; string resu;//最后的8进制串 //从二进制变为八进制,是将二进制字符串从后往前 //每3位一组【不满3位的,前面补字符'0'】,转换成对应的十进制字符,拼接构造 //为了简化补字符'0'的操作,直接将二进制字符串从后往前,每3位一组,每组按照百位、十位、个位求和 //不够3位的,由于补的是'0',所以直接无视这个操作,求和就行 char kk[2]; for(int i = lon2-1;i >= 0;i--){ int num = y[i]-48; //将字符'1' '0'变为 1 0,方便求和 all += num*cc; cc = cc * 10;//不断变化的百、十、个位 j++; if(j == 3 || i == 0){ // j == 3 是满足了 “三个一组” if(all == 1) // i == 0是满足了“到达二进制串的末尾,无视不够3位一组的情况下补'0'操作” kk[0] = '1'; if(all == 10) kk[0] = '2'; if(all == 11) kk[0] = '3'; if(all == 100) kk[0] = '4'; if(all == 101) kk[0] = '5'; if(all == 110) kk[0] = '6'; //char kk[2]的目的是,append()操作只针对字符串,所以一个长度为2的字符串数组搞定 if(all == 111) // 第一位放置 字符,第二位放字符串结束符' ' kk[0] = '7'; if(all == 0) kk[0] = '0';//根据求和的数字,匹配对应的8进制字符 resu.append(kk);//拼接构建 all = 0; cc = 1; j = 0; } } int lon3 = resu.size(); for(int i = lon3 - 1;i >= 0;i--)//反向输出,,因为二进制串是从后往前扫描,而append()是加到后面的 printf("%c",resu[i]); cout<<endl; } return 0; }