第二天
题目
问题描述
给定n个十六进制正整数,输出它们对应的八进制数。
输入格式
输入的第一行为一个正整数n (1<=n<=10)。
接下来n行,每行一个由09、大写字母AF组成的字符串,表示要转换的十六进制正整数,每个十六进制数长度不超过100000。
输出格式
输出n行,每行为输入对应的八进制正整数。
注意
输入的十六进制数不会有前导0,比如012A。
输出的八进制数也不能有前导0。
样例输入
2
39
123ABC
样例输出
71
4435274
提示
先将十六进制数转换成某进制数,再由某进制数转换成八进制。
分析:
首先想到的就是将十六进制的每位数转换为四位二进制数 然后每三位二进制数转换为八进制数
减少在运算上的计算运用的hashmap来存取每一位数对应的值。
但是发现无法设置map<char,String>
实在想不出来
网上的方法(看似简单的数制转换,也用到了栈)
public class Transform{
public void systemScanner() {
Scanner jin = new Scanner(System.in);
while (jin.hasNext()) {
int length = jin.nextInt();
for (int i = 0; i < length; i++){
String strTmp=jin.next();
tranform(strTmp.toCharArray(), strTmp.length());
}
}
}
public static void main(String[] args) {
new Transform().systemScanner();
}
/*
* 3位16进制等价于4位8进制
*/
int[] stack=new int[40000];//根据测试数据进行的设定
public void tranform(char[] str, int length) {
char[] buff = new char[4];//这个好像是多余的,后面也没有用到buff
int top = -1;
for (int i = length - 1; i >= 0; i -= 3) {
int sum = 0;
for (int j = 0; j < 3 && i - j >= 0; j++) {// i-j>=0防止不够三个的情况
int tmp =( str[i - j] >= '0' && str[i - j] <= '9' )? str[i - j] - '0': str[i - j] - 'A' + 10;//区分是数字,还是字符,进行对应转换
sum+=(tmp<<(4*j));//这句很重要,通过这句就可以从16变成10进制了,不过,不知道为什么?是如何得出的呢?而且进行累加之后就能得到最终的结果很神奇(其实是进行左移位,左移四位就相当于乘了16,8位就是256 16的平方)
}
stack[++top]=sum;//sum的结果是16进制转化10进制的结果,每3个16进制变成10进制,再变8进制(每三位十六进制转换为十进制)
}
while(stack[top]==0){//排除前导为0的判断
top--;
}
// for(int i=top;i>=0;i--){//直接输出会丢失前导0,因为此转化成8进制并不是最左边的情况,应该保留0
// System.out.print(Integer.toOctalString(stack[i]));//从10进制转化成8进制
// }
for(int i=top;i>=0;i--){
String str1=Integer.toOctalString(stack[i]);//从10进制转化成8进制
if(i!=top&&str1.length()<4){
//不是最左边的一个,就不用去掉前导0,而默认是去掉0的,所以要进行补会
for(int y=0;y<4-str1.length();y++)
System.out.print("0");
}
System.out.print(str1);
}
System.out.println();
}