第二次博客园作业. 2019.11.08
一. 程序运行截图
二. 函数介绍
1.函数声明
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdbool.h>
void two(int n);//输入二进制数
void eight(int n);//输入八进制数
void ten(int n);//输入十进制数
void sixteen(int n);//输入十六进制数
void two_to_eight(char num[1000]);//把二进制转换为八进制
void two_to_ten(char num[1000]);//把二进制转换为十进制
void two_to_sixteen(char num[1000]);//把二进制转换为十六进制
void eight_to_two(char num[1000]);//把八进制转二进制
void eight_to_ten(char num[1000]);//把八进制转十进制
void eight_to_sixteen(char num[1000]);//把八进制转十六进制
void ten_to_two(char num[1000]);//把十进制转二进制
void ten_to_eight(char num[1000]);//把十进制转八进制
void ten_to_sixteen(char num[1000]);//把十进制转十六进制
void sixteen_to_two(char num[1000]);//把十六进制转二进制
void sixteen_to_eight(char num[1000]);//把十六进制转八进制
void sixteen_to_ten(char num[1000]);//把十六进制转十进制
bool judge(int n, char num[1000]);//判断输入的数是否符合
int mypow(int x, int cnt);
这个题目鉴于自身水平有限,做的可能比较复杂,为了输入各进制数以及各进制的相互转换,定义了较多的函数,基本上实现了整个程序都由调用函数组成。
2.裁判函数
//裁判
bool judge(int n, char num[1000])
{
//二进制判断
if (n == 2)
{
for (int idx = 0; idx < strlen(num); idx++)
if (num[idx] != '1' && num[idx] != '0')return false;
return true;
}
//八进制判断
if (n == 8)
{
for (int idx = 0; idx < strlen(num); idx++)
if (num[idx] < 48 || num[idx] > 55)return false;
return true;
}
//十进制判断
if (n == 10)
{
for (int idx = 0; idx < strlen(num); idx++)
if (num[idx] < 48 || num[idx] > 57)return false;
return true;
}
//十六进制判断
if (n == 16)
{
for (int idx = 0; idx < strlen(num); idx++)
if (num[idx] < 48 || num[idx] > 70)return false;
return true;
}
}
根据输入的各进制,对其中出现的各位数遍历,一旦发现不符合的数,立刻返回false,否则,在遍历结束后返回true。本函数利用了返回布尔值的真假进行裁判,也可以改用int型返回0和1,只是因为true和false比较直观才使用而已。
3.指数函数
//指数
int mypow(int x, int cnt)
{
int sum = 1;
for (int idx = 0; idx < cnt; idx++)sum *= x;
return sum;
}
简单的指数函数,用于后面转换十进制使用。
4.二进制的输入与转换
//二进制
void two(int n)
{
char str[1000];
printf("请输入您的数字:");
scanf("%s", str);
if (!judge(n, str))printf("ERROR\n");
else
{
two_to_eight(str);
two_to_ten(str);
two_to_sixteen(str);
}
}
首先是二进制的输入函数,二进制可以说是本题令人讨厌的地方,为了满足二进制与各进制的相互转换,我们不能简单的使用格式控制完成本题,因此,我对本题的所有数字都采取了数组存放的方式。
根据提示输入你的数字后,如果裁判返回false,就会提示你的输入有误,否则,将调用三个进制转换函数。
void two_to_eight(char num[1000])//把二进制转换为八进制
{
int str[1000];
int ans = 1;
int cnt = 0, sum = 0;
memset(str, 0, sizeof(str));
for (int idx = strlen(num) - 1; idx >= 0; idx--)
{
cnt++;
sum = sum + (num[idx] - 48) * mypow(2, cnt - 1);
if (cnt == 3)
{
str[ans++] = sum;
sum = 0;
cnt = 0;
}
}
if (sum)str[ans++] = sum;
printf("八进制: ");
for (int idx = ans; idx >= 1; idx--)printf("%d", str[idx]);
printf("\n");
}
void two_to_ten(char num[1000])//把二进制转换为十进制
{
int str[1000];
int sum = 0;
memset(str, 0, sizeof(str));
for (int idx = strlen(num) - 1, i = 0; idx >= 0; idx--, i++)
{
sum = sum + (num[i] - 48) * mypow(2, idx);
}
printf("十进制: ");
printf("%d", sum);
printf("\n");
}
void two_to_sixteen(char num[1000])//把二进制转换为十六进制
{
char str[1000];
int ans = 1;
int cnt = 0, sum = 0;
memset(str, 0, sizeof(str));
for (int idx = strlen(num) - 1; idx >= 0; idx--)
{
cnt++;
sum = sum + (num[idx] - 48) * mypow(2, cnt - 1);
if (cnt == 4)
{
if (sum == 10)str[ans++] = 'A';
else if (sum == 11)str[ans++] = 'B';
else if (sum == 12)str[ans++] = 'C';
else if (sum == 13)str[ans++] = 'D';
else if (sum == 14)str[ans++] = 'E';
else if (sum == 15)str[ans++] = 'F';
else str[ans++] = sum + 48;
sum = 0;
cnt = 0;
}
}
if (sum) str[ans++] = sum + 48;
printf("十六进制: ");
printf("OX");
for (int idx = ans - 1; idx >= 1; idx--)printf("%c", str[idx]);
printf("\n");
}
非常简单的函数命名,就是二进制转换到八进制,十进制和十六进制,memset是将数组都初始化为零,它存放在
<string.h>中,考虑到八进制的一位数对于二进制的三位数,我引入了计数器cnt,每三个二进制数转化成一个八进制数,并对其求和,最终得到一个八进制数,然后多一位输出,保证八进制的以0为开头,实现八进制的正确显示
接下来的十进制就是简单的按位累乘求和,十六进制的转化类似八进制,每四个数字为一位十六进制,并且要将1015转化为AF,最后,要为十六进制的前面加上OX,表示十六进制数的输出。
5.八进制的输入与转换
//八进制
void eight(int n)
{
char str[1000];
printf("请输入您的数字:");
scanf("%s", str);
if (!judge(n, str))printf("ERROR\n");
else
{
eight_to_two(str);
eight_to_ten(str);
eight_to_sixteen(str);
}
}
void eight_to_two(char num[1000])//把八进制转二进制
{
int str[1000];
memset(str, 0, sizeof(str));
for (int i = strlen(num) - 1; i >= 0; i--)
{
int cnt = 2;
int number = num[i] - 48;
do {
if (number % 2)str[i * 3 + cnt] = 1;
else str[i * 3 + cnt] = 0;
cnt--;
number /= 2;
} while (number > 0);
}
printf("二进制: ");
for (int i = 0; i < strlen(num) * 3; i++)
{
printf("%d", str[i]);
if ((i + 1) % 3 == 0)printf(" ");
}
printf("\n");
}
void eight_to_ten(char num[1000])//把八进制转十进制
{
int str[1000];
int sum = 0;
memset(str, 0, sizeof(str));
for (int idx = strlen(num) - 1, i = 0; idx >= 0; idx--, i++)
{
sum = sum + (num[i] - 48) * mypow(8, idx);
}
printf("十进制: ");
printf("%d", sum);
printf("\n");
}
void eight_to_sixteen(char num[1000])//把八进制转十六进制
{
char str[1000];
int sum = 0, ans = 0;
memset(str, 0, sizeof(str));
for (int idx = strlen(num) - 1, i = 0; idx >= 0; idx--, i++)
{
sum = sum + (num[i] - 48) * mypow(8, idx);
}
do {
int number = sum % 16;
if (number == 10)str[ans++] = 'A';
else if (number == 11)str[ans++] = 'B';
else if (number == 12)str[ans++] = 'C';
else if (number == 13)str[ans++] = 'D';
else if (number == 14)str[ans++] = 'E';
else if (number == 15)str[ans++] = 'F';
else str[ans++] = number + 48;
sum /= 16;
} while (sum > 0);
printf("十六进制: ");
printf("OX");
for (int idx = ans - 1; idx >= 0; idx--)printf("%c", str[idx]);
printf("\n");
}
6.十进制的输入与转换
//十进制
void ten(int n)//输入十进制数
{
char str[1000];
printf("请输入您的数字:");
scanf("%s", str);
if (!judge(n, str))printf("ERROR\n");
else
{
ten_to_two(str);
ten_to_eight(str);
ten_to_sixteen(str);
}
}
void ten_to_two(char num[1000])//把十进制转二进制
{
int str[1000];
memset(str, 0, sizeof(str));
int cnt = 0, sum = 0;
for (int i = 0; i < strlen(num); i++)sum = sum * 10 + num[i] - 48;
do {
int number = sum % 2;
if (number % 2)str[cnt++] = 1;
else str[cnt++] = 0;
sum /= 2;
} while (sum > 0);
cnt--;
printf("二进制: ");
for (int i = cnt; i >= 0; i--)printf("%d", str[i]);
printf("\n");
}
void ten_to_eight(char num[1000])//把十进制转八进制
{
int str[1000];
int sum = 0, ans = 0;
memset(str, 0, sizeof(str));
for (int i = 0; i < strlen(num); i++)sum = sum * 10 + num[i] - 48;
do {
int number = sum % 8;
str[ans++] = number;
sum /= 8;
} while (sum > 0);
printf("八进制: ");
for (int i = ans; i >= 0; i--)printf("%d", str[i]);
printf("\n");
}
void ten_to_sixteen(char num[1000])//把十进制转十六进制
{
char str[1000];
int sum = 0, ans = 0;
memset(str, 0, sizeof(str));
for (int i = 0; i < strlen(num); i++)sum = sum * 10 + num[i] - 48;
do {
int number = sum % 16;
if (number == 10)str[ans++] = 'A';
else if (number == 11)str[ans++] = 'B';
else if (number == 12)str[ans++] = 'C';
else if (number == 13)str[ans++] = 'D';
else if (number == 14)str[ans++] = 'E';
else if (number == 15)str[ans++] = 'F';
else str[ans++] = number + 48;
sum /= 16;
} while (sum > 0);
printf("十六进制: ");
printf("OX");
for (int idx = ans - 1; idx >= 0; idx--)printf("%c", str[idx]);
printf("\n");
}
7.十六进制的输入与转换
//十六进制
void sixteen(int n)//输入十六进制数
{
char str[1000];
printf("请输入您的数字:");
scanf("%s", str);
for (int i = 0; i < strlen(str); i++)
if (islower(str[i]))str[i] = toupper(str[i]);
if (!judge(n, str))printf("ERROR\n");
else
{
sixteen_to_two(str);
sixteen_to_eight(str);
sixteen_to_ten(str);
}
}
void sixteen_to_two(char num[1000])//把十六进制转二进制
{
int str[1000], number;
memset(str, 0, sizeof(str));
for (int i = strlen(num) - 1; i >= 0; i--)
{
int cnt = 3;
if (num[i] == 'A') number = 10;
else if (num[i] == 'B') number = 11;
else if (num[i] == 'C') number = 12;
else if (num[i] == 'D') number = 13;
else if (num[i] == 'E') number = 14;
else if (num[i] == 'F') number = 15;
else number = num[i] - 48;
do {
if (number % 2)str[i * 4 + cnt] = 1;
else str[i * 4 + cnt] = 0;
cnt--;
number /= 2;
} while (number > 0);
}
printf("二进制: ");
for (int i = 0; i < strlen(num) * 4; i++)
{
printf("%d", str[i]);
if ((i + 1) % 4 == 0)printf(" ");
}
printf("\n");
}
void sixteen_to_eight(char num[1000])//把十六进制转八进制
{
int str[1000];
int sum = 0, number, ans = 0;
for (int i = strlen(num) - 1; i >= 0; i--)
{
if (num[i] == 'A') number = 10;
else if (num[i] == 'B') number = 11;
else if (num[i] == 'C') number = 12;
else if (num[i] == 'D') number = 13;
else if (num[i] == 'E') number = 14;
else if (num[i] == 'F') number = 15;
else number = num[i] - 48;
sum = sum + number * mypow(16, strlen(num) - 1 - i);
}
do {
number = sum % 8;
str[ans++] = number;
sum /= 8;
} while (sum > 0);
ans--;
printf("八进制: ");
printf("0");
for (int i = ans; i >= 0; i--)printf("%d", str[i]);
printf("\n");
}
void sixteen_to_ten(char num[1000])//把十六进制转十进制
{
int sum = 0, number;
for (int i = strlen(num) - 1; i >= 0; i--)
{
if (num[i] == 'A') number = 10;
else if (num[i] == 'B') number = 11;
else if (num[i] == 'C') number = 12;
else if (num[i] == 'D') number = 13;
else if (num[i] == 'E') number = 14;
else if (num[i] == 'F') number = 15;
else number = num[i] - 48;
sum = sum + number * mypow(16, strlen(num) - 1 - i);
}
printf("十进制: ");
printf("%d", sum);
printf("\n");
}
这几种进制转换其实大同小异,为了实现main函数的简洁性,建立了比较多的函数。
特别的是,我在十六进制的输入中利用了<ctype.h>中的函数,将用户输入的小写字母全部转换成了大写字母,保证了正确识别十六进制数。
三.main函数的展示
int main()
{
int n;
while (1)
{
printf("请选择您所要输入的进制:");
scanf("%d", &n);
if (!n) break;
switch (n)
{
case 2:two(n); break;
case 8:eight(n); break;
case 10:ten(n); break;
case 16:sixteen(n); break;
default:printf("ERROR\n"); break;
}
printf("-------------------------------\n");
}
return 0;
}
用while做了一个死循环,只有当用户输入0的时候才会退出,根据用户输入的数字进入对于的进制输入与转换页面,同时,对于不属于2、8、10、16进制的数,会提示ERROR,并重新输入。
四.思维导图
五.问题与解决:
问题:本来想偷懒用宏来代替for循环,减少我的工作量,后来发现程序出现BUG,会输出错误答案。
int idx;
#define myfor(n) for(idx = 0;idx<n;idx++)
解决:发现是我设的全局变量和宏在调用函数时重复使用,导致全局变量的值产生偏差,引发了错误,于是我就删掉了全局变量和宏。
六.代码互评
刚好有同学已经提交了作业,我看了一下他们的函数,感觉都对我有启发,就一一对比一下。
1.网络1913 杨涛
int Tennum(char a[],int b)//将输入的数字转换为10进制数
{
int len, i, num;
int sum = 0;
len = strlen(a);//求字符长度
for (i = 0; i < len; i++)
{
if (a[i] >= '0' && a[i] <= '9')
{
num = a[i] - '0';
}
else if (a[i] >= 'A' && a[i] <= 'F')
{
num = a[i] - 'A' + 10;
}
sum = sum * b + num;
}
return sum;
}
我感觉这是个很棒的创意,很好的运用了秦九韶算法,完美的将各类进制转成十进制,节省了许多空间和时间,而我则是为每一种进制都建立了一个转换成十进制的函数,其实没有必要。
2 . 网络1914 林洁颖
int binaryconversion(int number){
if(number/2==0){
return number%2;
}
else{
return number%2+binaryconversion(number/2)*10;
}
}
让人眼前一亮的递归,我才明白原来可以用这种写法,对比我自己的二进制转换,我的代码就显得有些笨重了,不过,利用递归的话在处理较大数的时候很可能会栈溢出,我试了一下在输入六位数左右就会得到错误的值。
3.网络1913 陈汉煜
void TenToSixteen()
{
char ai[] = "0123456789ABCDEF";
char h[16];
int i = 0;
int j = 0;
int num = 0, g;
printf("输入一个整数:");
scanf_s("%d", &num);
g = num;
if (num < 0)
num = -num;
while (num)
{
h[i++] = ai[num % 16]; //对十进制数求余并最终与h数组中的字符匹配
num = num / 16;
}
printf("十进制数转换成十六进制数是:");
if (g < 0)
printf("-");
for (j = i - 1; j >= 0; --j)
printf("%c", h[j]);
printf("\n");
}
又是一个挺棒的主意,利用了打表的方法,简洁的完成了十六进制的转换。
七.总结
1.收获:对比了一下提交了同学的代码,我写得显得有些繁琐了,在这之中,我又学到了一些很棒的主意,同时,在这次作业完成的过程中,加深了我对进制转换的应用,也尝试了一些有趣的主意,比如把main函数做的很少,基本靠函数的调用来实现程序
2理解:函数本身存在是为了使代码看着更加清楚明了,便于人们读懂程序,为函数取好他们的名字,正确的调用,可以让你的代码更加简洁,更加有趣。