实践编程自我检错_蓝桥杯_ 基础练习 十六进制转八进制

来源:互联网 发布:软件开发课程 编辑:程序博客网 时间:2024/06/05 15:21


问题:

问题描述

  给定n个十六进制正整数,输出它们对应的八进制数。

输入格式
  输入的第一行为一个正整数n (1<=n<=10)。
  接下来n行,每行一个由0~9、大写字母A~F组成的字符串,表示要转换的十六进制正整数,每个十六进制数长度不超过100000。

输出格式
  输出n行,每行为输入对应的八进制正整数。

  【注意
  输入的十六进制数不会有前导0,比如012A。
  输出的八进制数也不能有前导0。

样例输入
  2
  39
  123ABC

样例输出
  71
  4435274

  提示

  先将十六进制数转换成某进制数,再由某进制数转换成八进制。

最初思路:

定义n,输入n,定义char **x;char **b;char **o;
最外围做一个n次的for循环,以int i控制,循环内所做的工作如下
以字符串形式输入一个十六进制数,用x[i]把输入的16进制数以字符串的形式存储下来
用while做外循环把字符串中的字符一个一个的读出来并用switch识别,每个十六进制字符转化为四个二进制字符并存储到b[i]下,当循环到'\0'即为x所指字符串读完,结束while
然后先通过strlen计算各个字符串长度,长度不是三的倍数的在字符串最前加0
然后做一个循环,每次循环在b所指的一条字符串中读取3个字符并通过识别转化为对应的八进制数以字符的形式存到o[i]下,循环到'\0'即为b所指字符串读完,结束循环
用puts输出o[i]所指字符串,本次for循环结束,i++,继续下一次
n次for循环完成后,程序结束

实践编程中遇到的问题:

#include <stdio.h>#include <string.h>#include <stdlib.h>int main(){int n;scanf("%d\n",&n);char **x=(char **)malloc(sizeof(char *)*n);char **b=(char **)malloc(sizeof(char *)*n);char **o=(char **)malloc(sizeof(char *)*n);for(int i=0;i<n;i++){x[i]=new char[100001];b[i]=new char[140000];o[i]=new char[400004];}return 0;}
问题原因:所使用的字符指针数组未进行动态内存分配就在使用,是野指针,进行两次动态内存分配后可解决
存在疑惑:这样的话用字符数组岂不是更方便吗,反正都要提前分配那么大的内存才能用,字符数组还更适合访问,关于指针的使用优点和细节不清晰有待加深
#include <stdio.h>#include <string.h>#include <stdlib.h>int main(){int n;scanf("%d\n",&n);char **x=(char **)malloc(sizeof(char *)*n);char **b=(char **)malloc(sizeof(char *)*n);char **o=(char **)malloc(sizeof(char *)*n);for(int i=0;i<n;i++){x[i]=new char[100001];b[i]=new char[140000];o[i]=new char[400004];}char *p,*q,*m;int a;for(int i=0;i<n;i++){p=x[i];q=b[i];m=o[i];a=0;scanf("%s",x[i]);while(p[a]!='\0'){switch(p[a])       {         case '0': strcat(q,"0000"); break;            case '1': strcat(q,"0001"); break;              case '2': strcat(q,"0010"); break;             case '3': strcat(q,"0011"); break;               case '4': strcat(q,"0100"); break;               case '5': strcat(q,"0101"); break;              case '6': strcat(q,"0110"); break;               case '7': strcat(q,"0111"); break;              case '8': strcat(q,"1000"); break;              case '9': strcat(q,"1001"); break;              case 'A': strcat(q,"1010"); break;              case 'a': strcat(q,"1010"); break;            case 'B': strcat(q,"1011"); break;   case 'b': strcat(q,"1011"); break;            case 'C': strcat(q,"1100"); break;               case 'c': strcat(q,"1100"); break;               case 'D': strcat(q,"1101"); break;               case 'd': strcat(q,"1101"); break;             case 'E': strcat(q,"1110"); break;               case 'e': strcat(q,"1110"); break;               case 'F': strcat(q,"1111"); break;               case 'f': strcat(q,"1111"); break;             default:printf("输入的16进制数有错误!请重新输入!"); exit(1);break;       }       a++;}printf("%s\n",q);}return 0;}
问题:转换后的二进制字符串首部都多了三个乱码,经排除法检查发现是new的问题,改用
x[i]=(char *)malloc(sizeof(char *)*100001);
b[i]=(char *)malloc(sizeof(char *)*140000);
o[i]=(char *)malloc(sizeof(char *)*400004);
不过暂时不知道为什么用new会错,待解决

#include <stdio.h>#include <string.h>#include <stdlib.h>int main(){int n;scanf("%d\n",&n);char **x=(char **)malloc(sizeof(char *)*n);char **b=(char **)malloc(sizeof(char *)*n);char **o=(char **)malloc(sizeof(char *)*n);for(int i=0;i<n;i++){x[i]=(char *)malloc(sizeof(char *)*100001);b[i]=(char *)malloc(sizeof(char *)*140000);o[i]=(char *)malloc(sizeof(char *)*400004);}char *p,*q,*m;int a;for(int i=0;i<n;i++){p=x[i];q=b[i];m=o[i];a=0;scanf("%s",x[i]);while(p[a]!='\0'){switch(p[a])       {         case '0': strcat(q,"0000"); break;            case '1': strcat(q,"0001"); break;            case '2': strcat(q,"0010"); break;             case '3': strcat(q,"0011"); break;               case '4': strcat(q,"0100"); break;               case '5': strcat(q,"0101"); break;              case '6': strcat(q,"0110"); break;               case '7': strcat(q,"0111"); break;              case '8': strcat(q,"1000"); break;              case '9': strcat(q,"1001"); break;              case 'A': strcat(q,"1010"); break;              case 'a': strcat(q,"1010"); break;            case 'B': strcat(q,"1011"); break;   case 'b': strcat(q,"1011"); break;            case 'C': strcat(q,"1100"); break;               case 'c': strcat(q,"1100"); break;               case 'D': strcat(q,"1101"); break;               case 'd': strcat(q,"1101"); break;             case 'E': strcat(q,"1110"); break;               case 'e': strcat(q,"1110"); break;               case 'F': strcat(q,"1111"); break;               case 'f': strcat(q,"1111"); break;             default:printf("输入的16进制数有错误!请重新输入!"); exit(1);break;       }       a++;}printf("%s\n",q);if(strlen(q)%3==2) strcat(q,"0");if(strlen(q)%3==1) strcat(q,"00");printf("%s\n",q);}return 0;}
问题:不知道怎么在字符串首加字符,上面的最后是加在了字符串尾部
char *t=(char *)malloc(sizeof(char *)*140000);if(strlen(b[i])%3==2){strcat(t,"0");strcat(t,b[i]);strcpy(b[i],t);}if(strlen(b[i])%3==1){strcat(t,"00");strcat(t,b[i]);strcpy(b[i],t);}
解决方法:以字符串t做中转达成目的,对字符串操作的函数不够熟悉

#include <stdio.h>#include <string.h>#include <stdlib.h>int main(){int n;scanf("%d\n",&n);char **x=(char **)malloc(sizeof(char *)*n);char **b=(char **)malloc(sizeof(char *)*n);char **o=(char **)malloc(sizeof(char *)*n);for(int i=0;i<n;i++){x[i]=(char *)malloc(sizeof(char *)*100001);b[i]=(char *)malloc(sizeof(char *)*140000);o[i]=(char *)malloc(sizeof(char *)*400004);}char *p,*q,*m;int a;for(int i=0;i<n;i++){p=x[i];q=b[i];m=o[i];a=0;scanf("%s",x[i]);while(p[a]!='\0'){switch(p[a])       {         case '0': strcat(b[i],"0000"); break;              case '1': strcat(b[i],"0001"); break;              case '2': strcat(b[i],"0010"); break;             case '3': strcat(b[i],"0011"); break;               case '4': strcat(b[i],"0100"); break;               case '5': strcat(b[i],"0101"); break;              case '6': strcat(b[i],"0110"); break;               case '7': strcat(b[i],"0111"); break;              case '8': strcat(b[i],"1000"); break;              case '9': strcat(b[i],"1001"); break;              case 'A': strcat(b[i],"1010"); break;              case 'a': strcat(b[i],"1010"); break;            case 'B': strcat(b[i],"1011"); break;   case 'b': strcat(b[i],"1011"); break;            case 'C': strcat(b[i],"1100"); break;               case 'c': strcat(b[i],"1100"); break;               case 'D': strcat(b[i],"1101"); break;               case 'd': strcat(b[i],"1101"); break;             case 'E': strcat(b[i],"1110"); break;               case 'e': strcat(b[i],"1110"); break;               case 'F': strcat(b[i],"1111"); break;               case 'f': strcat(b[i],"1111"); break;             default:printf("输入的16进制数有错误!请重新输入!"); exit(1);break;       }       a++;}char *t=(char *)malloc(sizeof(char *)*140000);if(strlen(b[i])%3==2){strcat(t,"0");strcat(t,b[i]);strcpy(b[i],t);}if(strlen(b[i])%3==1){strcat(t,"00");strcat(t,b[i]);strcpy(b[i],t);}//至此十六进制转换为二进制完毕 a=0;char s='0';while(*q){if(*q==s){q++;if(*q==s){q++;if(*q==s) strcat(o[i],"0");else strcat(o[i],"1");}else {q++;if(*q==s) strcat(o[i],"2");else strcat(o[i],"3");}}else {q++;if(*q==s){q++;if(*q==s) strcat(o[i],"4");else strcat(o[i],"5");}else {q++;if(*q==s) strcat(o[i],"6");else strcat(o[i],"7");}}q++;}}for(int j=0;j<n;j++){printf("%s\n",o[j]);}return 0;}
最终代码,运行成功,结果符合,不过运行超时,于是改良
#include <stdio.h>#include <string.h>#include <stdlib.h>char x[10][100001];char b[10][140000];char o[10][400004];int main(){int n,i,j;scanf("%d\n",&n);for(i=0;i<n;i++){j=0;scanf("%s",x[i]);while(x[i][j]){switch(x[i][j])       {         case '0': strcat(b[i],"0000"); break;              case '1': strcat(b[i],"0001"); break;              case '2': strcat(b[i],"0010"); break;             case '3': strcat(b[i],"0011"); break;               case '4': strcat(b[i],"0100"); break;               case '5': strcat(b[i],"0101"); break;              case '6': strcat(b[i],"0110"); break;               case '7': strcat(b[i],"0111"); break;              case '8': strcat(b[i],"1000"); break;              case '9': strcat(b[i],"1001"); break;              case 'A': strcat(b[i],"1010"); break;              case 'a': strcat(b[i],"1010"); break;            case 'B': strcat(b[i],"1011"); break;   case 'b': strcat(b[i],"1011"); break;            case 'C': strcat(b[i],"1100"); break;               case 'c': strcat(b[i],"1100"); break;               case 'D': strcat(b[i],"1101"); break;               case 'd': strcat(b[i],"1101"); break;             case 'E': strcat(b[i],"1110"); break;               case 'e': strcat(b[i],"1110"); break;               case 'F': strcat(b[i],"1111"); break;               case 'f': strcat(b[i],"1111"); break;             default:printf("输入的16进制数有错误!请重新输入!"); exit(1);break;       }       j++;}j=0;if(strlen(b[i])%3==2){if(b[i][j]=='0'){j++;if(b[i][j]=='0') {}else {strcat(o[i],"1");}}else {j++;if(b[i][j]=='0') {strcat(o[i],"2");}else {strcat(o[i],"3");}}j++;}if(strlen(b[i])%3==1){if(b[i][j]=='0') {}else {strcat(o[i],"1");}j++;}while(b[i][j]){if(b[i][j]=='0'){j++;if(b[i][j]=='0'){j++;if(b[i][j]=='0') {}else {strcat(o[i],"1");}}else {j++;if(b[i][j]=='0') {strcat(o[i],"2");}else {strcat(o[i],"3");}}}else {j++;if(b[i][j]=='0'){j++;if(b[i][j]=='0') {strcat(o[i],"4");}else {strcat(o[i],"5");}}else {j++;if(b[i][j]=='0') {strcat(o[i],"6");}else {strcat(o[i],"7");}}}j++;}}for(i=0;i<n;i++){printf("%s\n",o[i]);}return 0;}

大幅修改,仍然运行超时,不能理解,switch和if else应该是很节省运行时间的吧,毕竟在我看来它们都通过条件判断选择执行的一部分代码

完全修改思路,既然确定是十六进制转八进制,那可以先补全输入的字符串为3的整数被,然后每循环一次取出3个十六进制数转化为4个八进制数:

#include <iostream>  #include <string>using namespace std;int main(){string x,o;      int n,i;      cin>>n;    for(i=0;i<n;i++){cin>>x;int len=x.length();if(len%3){string x2="0";string x1="00";len%3==2?x=x2+x:x=x1+x;}int pos=0;while(pos!=len){string t=x.substr(pos,3);pos+=3;int a=0;int m[3]={256,16,1};for(int j=0;j<3;j++){t[j]<60?a+=(t[j]-48)*m[j]:t[j]<95?a+=(t[j]-55)*m[j]:a+=(t[j]-87)*m[j];}t.clear();t[j]}             }    return 0;  }
已把那三个十六进制数利用ascii码转换成对应的十进制数,然后怎么转化为八进制的字符存储到string o呢.....

经实际运行substr处抛出异常,不知具体原因,等我看看源代码后续更改,或者求看到这博客的大神解答

异常无法处理,换实现方法:
#include <iostream>  #include <string>using namespace std;int main(){    string x,o=new char[140000];      int n,i;      cin>>n;    for(i=0;i<n;i++){cin>>x;int len=x.length();if(len%3){string x2="0";string x1="00";len%3==2?x=x2+x:x=x1+x;}int xpos=0;int opos=0;while(xpos!=len){int a=0;int m[3]={256,16,1};for(int j=0;j<3;j++){x[xpos]<60?a+=(x[xpos]-48)*m[j]:x[xpos]<95?a+=(x[xpos]-55)*m[j]:a+=(x[xpos]-87)*m[j];xpos++;}o[opos]=a/512+48; o[opos+1]=(a/64)%8+48; o[opos+2]=(a/8)%8+48; o[opos+3]=a%8+48;opos+=4;}o[opos+1]='\0';if(o[0]==48)if(o[1]==48){o.erase(0,2);}else{o.erase(0,1);}        }    return 0;  }

未知错误...

经排查是我不应该直接对那片内存空间存储数据,这样会造成string类中的lenth等内部数据与真实数据不一样,应该调用string类自己的函数来存储数据

另外我发现当我用new分配很大的内存空间时总会在前面莫名出现一段乱码如下:



一直都是p和一个笑脸,很奇怪的乱码,留个坑以后探究一下new的原型再回来完善

另外最后的代码出来了:

#include <iostream>  #include <string>using namespace std;int main(){    int n,i;      cin>>n;    string o[n];    for(i=0;i<n;i++){    string x;cin>>x;int len=x.length();if(len%3){string x2="0";string x1="00";len%3==2?x=x2+x:x=x1+x;}int xpos=0;int m[3]={256,16,1};while(x[xpos]){int a=0;for(int j=0;j<3;j++){x[xpos]<60?a+=(x[xpos]-48)*m[j]:x[xpos]<95?a+=(x[xpos]-55)*m[j]:a+=(x[xpos]-87)*m[j];xpos++;}char o1;o1=a/512+48;o[i]+=o1; o1=(a/64)%8+48;o[i]+=o1; o1=(a/8)%8+48;o[i]+=o1;o1=a%8+48;o[i]+=o1;}if(o[i][0]==48){if(o[i][1]==48){if(o[i][2]==48){o[i].erase(0,3);}else{o[i].erase(0,2);}}else{o[i].erase(0,1);}        }}for(i=0;i<n;i++){    cout<<o[i]<<endl;}    return 0;  }

通过OJ,成功搞定一道.......

缺漏知识:

1.指针必须在赋初值后使用,任何类型指针

2.gets(s)函数与 scanf("%s",&s) 相似,但不完全相同,使用scanf("%s",&s) 函数输入字符串时存在一个问题,如果输入了空格会认为字符串结束,空格后的字符将作为下一个输入项处理,但gets()函数将接收输入的整个字符串直到遇到换行为止

两者在接受字符串时:

1.不同点:

scanf不能接受空格、制表符Tab、回车等;

gets能够接受空格、制表符Tab和回车等;

2.相同点:

字符串接受结束后自动加'\0'。

3.用malloc申请的空间在使用完毕后要free掉,用new申请的要delete掉,申请过后最好判断一下是否申请成功,失败则提示并异常退出,另外new是C++中的

4.上面红色的各个坑以后慢慢填



0 0
原创粉丝点击