第二次博客园作业
一、代码运行截图
说明: 除非用户主动选择退出 ,否则可一直进行进制转换。 而当再次输入数字时,界面会清屏。
二、额外拓展
- 当程序输入的进制与该数不符会报错
- 输入的目标进制非二、八、十、十六会报错
- 完成一次进制转换后能自主选择是否结束
三、代码里的函数介绍
(除十六进制外)任意进制转十进制函数:
int wantonly_to_decimalism(int num, int p) //num表示需转换的原数,p表示该数的原进制数 { int result = 0; int product = 1; //product用来存储原进制数的幂 while (num != 0) { //按权展开求数的十进制 result = result + num % 10 * product; num /= 10; product *= p; } return result; }
说明:此函数只适用于二、八、十进制转十进制。思路在代码里面。
十进制数转二进制函数:
int decimalism_to_binary(int num) /*十进制转二进制*/ { int op[100]; //定义一个足够大的数组来存储需转换数除二的余数 int result = 0; int i; int count = 0; //count用来存放每个余数的序号,方便后面按想要的顺序取余数 while (num != 0) { //正序求余,并存放入数组op op[count++] = num % 2; num /= 2; } for (i = count - 1; i >= 0; i--) { //倒序取余数即为该数转换为二进制的结果 result = result * 10 + op[i]; } return result; }
说明:此函数是用来求二进制数的,思路在代码里。
十进制数转八进制函数:
int decimalism_to_octal(int num)/*十进制转八进制*/ { int result = 0; int op[100]; int i; int count = 0; while (num != 0) { op[count++] = num % 8; num /= 8; } for (i = count - 1; i >= 0; i--) { result = result * 10 + op[i]; } return result; }
说明:十进制转八进制和十进制转二进制方法其实是一样的,不同之处在于取余时的除数不同,十进制转二进制和八进制的函数可以优化在一起写成一个函数,加多一个变量用来存储目标进制即可。
十六进制转十进制函数:
void decimalism_to_hexadecimal(int num) /*十进制转十六进制*/ { int op[100]; /*定义一个数组来储存每个位子上数字的位子*/ char hex[16] = { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' }; //定义一个标志字符串,用来将原十进制数转换成对应的字符 int i; int m; //用来存放原数除16的余数,便于后面在数组hex中对应字符的取用 int count = 0; while (num != 0) //正序求余,存放进数组op中 { op[count++] = num % 16; num /= 16; } for (i = count - 1; i >= 0; i--) //倒序取余数 { m = op[i]; printf("%c", hex[m]); //让每位子数字输出对应的字符 } printf("\n"); }
说明:此函数用来输出十进制转十六进制的字符,无返回值,在主函数中调用即可直接输出。思路在代码里。
十进制转十六进制函数:
long hexadecimal_to_decimalism(char num[]) /*十六进制转十进制*/ { int count; int i; int is = 1; /*用来储存16的幂*/ long result = 0; count = strlen(num); /*计算字符串的长度*/ for (i = count - 1; i >= 0; i--) //倒序取字符串里的各个数据,同时转换为16进制的数 { result = result + is * charactor_to_number(num[i]); is = is * 16; //这里调用了一个字符转整型的函数,在第六小点有介绍 } return result; }
说明:因为十六进制有别于其他进制,所以无法按十进制转二进制或八进制的正序求余,倒序取余的方法得到。十六进制的数每个位上最大数为15即字母F或f,而二进制或者八进制数每个位上的数上线不超过最大数字限度,即用不到字母。而十六进制的转换则需要定义一个标志字符串1到9加上代表10到15的字母a到f。
十六进制字符串类型转整型函数:
int charactor_to_number(char cn) /*十六进制的字符转整型数字*/ { if (cn >= '0' && cn <= '9') { return cn - '0'; } if (cn >= 'A' && cn <= 'F') /*将A-F对应的数字即10-15返回*/ { return cn - 'A' + 10; } if (cn >= 'a' && cn <= 'f') /*将a-f对应的数字即10-15返回*/ { return cn - 'a' + 10; } return -1; //由于正确数据返回中含有0,所以取不满足条件返回-1,以达到目的 }
说明:这是一个应用于十六进制转十进制将十六进制中的字符转换成整型数据的函数,在此转换器中,十六进制的数据是用字符串的形式存储的,将其转换成十进制得先将字符转换成对应整型数字。思路在代码里。
数据检查函数:
int inspect(char number[], int system) /*数据检查(用于检查输入的数据是否与其进制符合)*/ { int flag = 1; int count; /*计算字符串的长度*/ int i; count = strlen(number); /*调用strlen函数计算字符串长度*/ switch (system) /*讨论数据是否满足原进制的要求*/ { case 2: /*二进制的数每个位子上数字最大为1最小为0*/ for (i = 0; i < count; i++) { if (number[i] >= '2' || number[i] < '0') { flag = 0; break; } } break; case 8: /*八进制的数每个位子上数字最大为7最小为0*/ for (i = 0; i < count; i++) { if (number[i] >= '8' || number[i] < '0') { flag = 0; break; } } break; case 10: /*十进制的数每个位子上数字最大为9最小为0*/ for (i = 0; i < count; i++) { if (number[i] >= '0' && number[i] <= '9') { flag = 1; } else { flag = 0; break; } } break; case 16: /*十六进制数每个位子上数字最大为F(即15)最小为0*/ for (i = 0; i < count; i++) { if (number[i] >= '0' && number[i] < '9'|| number[i] >= 'A' && number[i] < 'F'|| number[i] >= 'a' && number[i] < 'f') { flag = 1; } else { flag = 0; break; } } break; default: /*对除二、八、十、十六进制以为的所有进制做报错处理*/ flag = 0; break; } return flag; /*符合要求的返回1反之返回0*/ }
说明:此函数的作用是,当用户输入数与进制后,系统判断该数是不是与进制相符,不符合的返回0,系统报错,提醒用户输入数据有误,符合的则继续运行。思路在代码里。
- 计算字符串的有效长度的函数:
strlen()
此函数是库函数里的,调用时要用到头文件 #include<stdlib.h>
.此函数用来计算字符串的有效长度即字符个数。
- 将字符转换成整型的函数:
atoi()
此函数也是库函数里的,使用后直接将字符型的数字转换成整型数字。
四、main函数
int main() { printf("\n****欢迎使用进制转换器****\n"); int flag = 1; char op[100]; /*定义字符串存储用户输入的待转换的数据*/ int origin; /*表示待转换数据的原进制类型*/ int objective; /*表示待转换数据的原进制类型*/ int integer; /*用来存储字符串转为整型的数据*/ int result; while (flag) { begin:printf("\n请输入您需要转换的数:"); scanf("%s", op); printf("\n该数的原进制为: "); scanf("%d", &origin); if (inspect(op, origin) == 0) /*检查输入的数据有错误的情况*/ { error:printf("\n您输入的数据有误\n\n重新输入请按 1 ,结束请按 0 \n"); int sign; /*定义个变量来作用于程序是否进行下去*/ scanf("%d", &sign); if (sign) { goto begin; /*进行则回到最初输入数据那一步*/ } else { goto last; /*结束则跳到程序末,结束程序*/ } } else if (inspect(op, origin)) /*数据检查通过,数据正确则进行目标进制的输入*/ { printf("\n转换的目标进制为: "); scanf("%d", &objective); if (origin == 16) /*因为十六进制的转换和别的进制不一样,所以这里进行特殊判断处理*/ { integer = hexadecimal_to_decimalism(op); /*十六进制转成十进制*/ } else { integer = wantonly_to_decimalism(atoi(op), origin); /*二或八进制转为十进制数*/ } switch (objective) /*对目标进制分二、八、十、十六进制进行讨论*/ { case 2: result = decimalism_to_binary(integer); printf("\n该数的%d进制数为:%d", objective, result); break; case 8: result = decimalism_to_octal(integer); printf("\n该数的%d进制数为:%d", objective, result); break; case 10: result = integer; printf("\n该数的%d进制数为:%d", objective, result); break; case 16: printf("\n该数的%d进制数为:",objective); decimalism_to_hexadecimal(integer); /*十进制转十六进制是无返回(void)型的,调用直接输出结果*/ break; default:goto error; break; /*若目标进制非二、八、十、十六进制则提示用户数据错误*/ } } printf("\n继续请按 1 ,退出按 0 .\n"); /*一次转换结束,询问用户是否继续,或者结束程序*/ scanf("%d", &flag); if (flag == 0) { goto last; } system("cls"); /*当用户选择继续,系统则会执行一次清屏指令,是界面整洁*/ } last:printf("****谢谢使用本进制转换器****\n"); return 0; }
五、思维导图
六、遇到的问题与解决方法
问题:
- 用整型无法存储十六进制的数。
- 用字符串存储数据的话,无法进行整型计算,不会编写程序计算字符串的有效长度。
- 十六进制转换成十进制过程中,分别代表10-15的A-F,不会将其转换成对应的数字。
- 多次输入数据,界面繁杂。
解决方法:
- 加学字符串的知识,用字符串存储十六进制数。
- 将字符串里的每个字符都转换成整型,然后在转的过程中,学习到库函数里有个直接计算字符串长度的函数,这使字符转换成整型更简便了些。
- 老师给予了一个新的思路,定义个标志字符串,在字符串下标0到15分别存储0到9和A到F,这使后面取字符可以直接根据下标来取。
- 班助教会一个
system("cls")
清屏,使程序多次运行输入数据时界面不会繁杂凌乱,视觉体验感及其低下。
七、代码互评
网络1913 李欣欣
优点:
定义了一个全局变量,使后面变量的使用减少的繁杂的又再定义。而我的代码里没有定义并使用全局变量。
编写的字符转数字和数字转字符函数能适用于所有进制的数,而我的则需分二、八、十进制与十六进制,相比之下她的方法更简便。
上图为李欣欣同学的代码
我的二、八进制字符型数字转成整型则是用了库函数里的atoi()
函数,而我十六进制的转换自己另写了一个,如下图所示:
缺点:
- 当多次运行后,界面繁杂缭乱,这是需改进的地方。
八、总结
收获:
以前写程序,都是完成一个pta题目类型的,从来没有自己编写过一个完整的程序之类的东西,这是一个全新的体验。也让自己对自己所编写程序需要完善和壮大的意识。在程序不断完善,每个细节都能按照自己的想法实现的时候,心情是无法言喻的。当一个转换器真的写出来并且能成功运行的那一刻,内心激动无比,对编程奇妙的世界有了更深的向往。
对函数的理解:
自己定义的函数,能根据需求编写,调用起来简单方便,当让函数所实现的功能也是能写在main里面的,可是自定义的函数能让main函数简洁,清晰。它增强了代码的灵活性。
2019.11.10