第二次博客园作业. 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理解:函数本身存在是为了使代码看着更加清楚明了,便于人们读懂程序,为函数取好他们的名字,正确的调用,可以让你的代码更加简洁,更加有趣。

posted @ 2019-11-08 00:12  Leesu  阅读(208)  评论(0编辑  收藏  举报