问题描述:
设计一个实现任意长的整数进行四则混合运算的演示程序
基本要求:
利用双向循环链表实现长整数的存储,每个结点含一个整型遍历。任何整型变量的范围是-(2^15-1)~(2^15-1)。输入和输出形式:按中国对于长整数的表示习惯,每四位一组,组间用逗号隔开。
实现长整型的四则混合运算;
实现长整型的乘方和阶乘运算
整型量范围是-(2^n-1)~(2^n-1),其中,n是由程序读人的参量。输入数据的分组方法可以另外规定。
代码如下:
#include<stdio.h>
#include<stdlib.h>
#include<String.h>
#include<conio.h>
//1.定义结构体
typedef struct Node{
int data;
struct Node *prior,*next;
}Node,*LinkList;
//创建菜单
void printStar() //连续输入几十个*,用来设计虚拟界面的边框
{
int i;
for(i=0;i<90;i++)
printf("*");
printf("\n");
}
void menu() //因为C语言无法创建可视化界面,因此这里创建一个虚拟的界面,方便用户操作
{
printStar();
printf("\t\t\t欢迎进入长整型的四则混合运算界面!\n");
printf("\t请从键盘输入数字,完成对应的操作(1到7为有效操作,输入其他退出程序)\n");
printf("\t\ta,b,c链表初始化成功\n");
printf("\t\t 1.重置c链表\n");
printf("\t\t 2.两数相加\n");
printf("\t\t 3.两数相减\n");
printf("\t\t 4.两数相乘\n");
printf("\t\t 5.两数相除\n");
printf("\t\t 6.a的n次方\n");
printf("\t\t 7.a!的阶乘\n");
printStar();
}
//2.初始化结构体
void InitList(LinkList &L){
L=(LinkList)malloc(sizeof(Node));
L->data=0; //数据域的绝对值表示结点的个数,符号表示数据的正负
L->prior=L;
L->next=L;
}
//3.尾部插入法
void ListInsert(LinkList &L,int x) { //在链表的尾部插入一个值为x的结点
LinkList p=(LinkList)malloc(sizeof(Node));
LinkList q=L->prior;
p->data=x;
p->next=L;
p->prior=q;
q->next=p;
L->prior=p;
if(L->data>=0){
L->data++;
}
else {
L->data--;
}
}
//4.头插法
void Listhead(LinkList &L,int x){
LinkList p=(LinkList)malloc(sizeof(Node));
p->data=x;
p->next=L->next;
p->prior=L;
L->next->prior=p;
L->next=p;
L->data++;
// LinkList o=(LinkList)malloc(sizeof(Node));
// o->data=i,o->next=c->next,o->prior=c;
// c->next->prior=o,c->next=o;
// c->data++;
}
//删除时0000的尾结点
void ListDelete(LinkList &L){
if(L->data==0){
return;
}
LinkList p=L->prior;
LinkList q=p->prior;
q->next=L;
L->prior=q;
free(p);
if(L->data>=0){
L->data--;
}
else{
L->data++;
}
}
//调整进位的问题
void Adjust(LinkList &L){
LinkList p=L->next;
while(p!=L){
while(p->data>9999){
if(p->next==L){
ListInsert(L,0);
}
p->next->data=p->next->data+ p->data/10000;
p->data=p->data%10000;
}
p=p->next;
}
while(L->prior->data==0 &&abs(L->data)>1){ //如果是0000,则需要删除这个结点
ListDelete(L);
}
}
//比较异号的两条链表的大小
int Compare(LinkList a,LinkList b){
/*利用头结点的绝对值进行判断
|a->data| > |b->data| return 1
|a->data| < |b->data| return 0
|a->data| = |b->data| return 2
*/
//a的结点不等于b (abs)
if(abs(a->data) != abs(b->data)){
if(abs(a->data) > abs(b->data)){
return 1;
}
else{
return 0;
}
}
//a的结点等于b (abs)
LinkList p=a->prior,q=b->prior;
while(p!=a && q!=b){
if(p->data!=q->data){
if(p->data > q->data){
return 1;
}
else{
return 0;
}
}
p=p->prior;
q=q->prior;
}
return 2;
}
//4.相加 a+b=c
void Add(LinkList a,LinkList b,LinkList &c){
//ab同号
if(a->data * b->data >= 0){
LinkList p=a->next, q=b->next;
while(p!=a && q!=b){
ListInsert(c,p->data + q->data);
p=p->next;
q=q->next;
}
while(p!=a){ //q->next=b
ListInsert(c,p->data);
p=p->next;
}
while(q!=b){ //p->next=a
ListInsert(c,q->data);
q=q->next;
}
if(a->data<0){
c->data=-c->data;
}
}
//ab异号
else{
switch(Compare(a,b)){
case 2: //a=b
ListInsert(c,0);
return;
case 1: //a>b 证明了a的数值比b大 或者 a的结点比b多
{
LinkList p=a->next,q=b->next;
while(p!=a && q!=b){
if(p->data<q->data){
p->next->data--;
p->data=p->data+10000;
}
ListInsert(c,p->data - q->data);
p=p->next;
q=q->next;
}
while(p!=a){ //q->next=b
ListInsert(c,p->data);
p=p->next;
}
if(a->data < 0){
c->data=-c->data; //确定其c链表的符号
}
break;
}
case 0:
{
LinkList p=a->next,q=b->next;
while(p!=a && q!=b){
if(q->data < p->data){
q->next->data--;
q->data=p->data+10000;
}
ListInsert(c,q->data - p->data);
p=p->next;
q=q->next;
}
while(q!=b){ //p->next=a
ListInsert(c,p->data);
q=q->next;
}
if(b->data < 0){
c->data=-c->data;
}
break;
}
}
}
Adjust(c);
}
//5.相减 a-b=c a+(-b)=c
void Sub(LinkList a,LinkList b,LinkList &c){
b->data=-b->data;
Add(a,b,c);
//需要把b链表的值变回来 后面还有乘和除
b->data=-b->data;
}
//6.相乘 a*b=c
void Mul(LinkList a,LinkList b,LinkList &c){
if(abs(a->data)==1 && a->next->data==0 || abs(b->data==1 && b->next->data==0)){
ListInsert(c,0);
return;
}
for(int i=1;i<=(abs(a->data)+abs(b->data));i++){
ListInsert(c,0);
}
LinkList p=a->next;
for(int i=1;p!=a;p=p->next,i++){
LinkList q=b->next;
for(int j=1;q!=b;q=q->next,j++){
int k=i+j-1; //让其指向相应的结点上
LinkList t=c;
while(k--){
t=t->next;
}
t->data=t->data+p->data * q->data;
}
}
if(a->data*b->data < 0){
c->data=-c->data;
}
Adjust(c); //处理结点中的数据的进位的问题
}
相除 这个代码效率太慢了,会导致内存爆满,程序运行不下去 程序一直在建表和删除表的操作中
//void Div(LinkList a,LinkList b,LinkList &c){
// // |a|<|b| ==> c链表插入0
// if(Compare(a,b)==0){
// ListInsert(c,0);
// return;
// }
// // |a|>=|b|
// int i=0;
// LinkList d;
// InitList(d);
// int flag=0;
// int sign=0;
// if(a->data<0){
// a->data=-a->data;
// flag=1;
// }
// if(b->data<0){
// b->data=-b->data;
// sign=1;
// }
// //把a复制给d
// for(LinkList p=a->next;p!=a;p=p->next){
// ListInsert(d,p->data);
// }
// while(Compare(d,b)){
// i+=1;
// LinkList r;
// InitList(r);
// Sub(d,b,r);
// //需要删除d链表
// while(d->data!=0){
// ListDelete(d);
// }
// //把r的链表复制给d
// InitList(d);
// for(LinkList p=r->next;p!=r;p=p->next){
// ListInsert(d,p->data);
// }
// }
// ListInsert(c,i);
// if(flag){
// a->data=-a->data;
// }
// if(sign){
// b->data=-b->data;
// }
// if(a->data*b->data<0)c->data=-c->data;//ab异号
// Adjust(c);
//}
//相除 改进
void Div(LinkList a,LinkList b,LinkList &c){
// |a|<|b| ==> c链表插入0
if(Compare(a,b)==0){
ListInsert(c,0);
return;
}
// |a|>=|b|
int i=0;
LinkList d;
InitList(d);
int sign=0;
if(b->data<0){
b->data=-b->data;
sign=1;
}
//将a高位部分拷给d
for(LinkList p=a->prior;p!=a;p=p->prior){
//使用头插法插入
// LinkList q=(LinkList)malloc(sizeof(Node));
// q->data=p->data,q->next=d->next,q->prior=d;
// d->next->prior=q,d->next=q;
// d->data++;
Listhead(d,p->data);
while(Compare(d,b)){
i+=1;
LinkList r;
InitList(r);
Sub(d,b,r);
//需要删除d链表
while(d->data!=0){
ListDelete(d);
}
//把r的链表复制给d
InitList(d);
for(LinkList p=r->next;p!=r;p=p->next){
ListInsert(d,p->data);
}
}
//使用头插法插入c链表中
// LinkList o=(LinkList)malloc(sizeof(Node));
// o->data=i,o->next=c->next,o->prior=c;
// c->next->prior=o,c->next=o;
// c->data++;
Listhead(c ,i);
i=0;
}
if(sign){
b->data=-b->data;
}
if(a->data*b->data<0)c->data=-c->data;//ab异号
Adjust(c);
}
//乘方
void Impl(LinkList a,LinkList &c){
LinkList d;
InitList(d);
LinkList r;
InitList(r);
int x;
int flag=0;
long int sum=0;
if(a->data<0){
a->data=-a->data;
flag=1;
}
printf("n(>=0)为: ");
scanf("%d",&x);
LinkList p=a->prior;
while(p!=a){
sum=sum*1000+p->data;
p=p->prior;
}
if(sum==0){
printf("0的任何次乘方没有意义\n");
return ;
}
if(sum>0&&x==0){
ListInsert(c,1);
return;
}
//
if(x==1){
for(LinkList h=a->next;h!=a;h=h->next){
ListInsert(c,h->data);
}
}
for(LinkList p=a->next;p!=a;p=p->next){
ListInsert(d,p->data);
}
//x>=2
for(int i=2;i<=x;i++){
Mul(a,d,r);
while(d->data!=0){
ListDelete(d);
}
InitList(d);
for(LinkList p=r->next;p!=r;p=p->next){
ListInsert(d,p->data);
}
if(i<x){
while(r->data!=0){
ListDelete(r);
}
InitList(r);
}
}
for(LinkList h=r->next;h!=r;h=h->next){
ListInsert(c,h->data);
}
if(flag){
a->data=-a->data;
}
if(a->data<0&&x%2!=0){
c->data=-c->data;
}
Adjust(c);
}
//阶乘
void Impl_Factorial(LinkList a,LinkList &c){
LinkList p=a->prior;
long int sum=0;
LinkList d,f,g;
InitList(d);
InitList(f);
InitList(g);
ListInsert(d,1);
if(a->data<0){
printf("负数没有阶乘\n");
return;
}
while(p!=a){
sum=sum*1000+p->data;
p=p->prior;
}
if(sum==0){
ListInsert(c,1);
return;
}
for(int i=1;i<=sum;i++){
ListInsert(f,i);
Mul(d,f,g);
if(i<sum){
while(d->data!=0){
ListDelete(d);
}
InitList(d);
for(LinkList p=g->next;p!=g;p=p->next){
ListInsert(d,p->data);
}
while(f->data!=0){
ListDelete(f);
}
InitList(f);
while(g->data!=0){
ListDelete(g);
}
InitList(g);
}
for(LinkList p=g->next;p!=g;p=p->next){
ListInsert(c,p->data);
}
}
Adjust(c);
}
//输入 限制第一位只能输入正负号,否则报错
int GetNum(LinkList &L){
char ss[100005];
int sum=0;
printf("请输入字符(输入格式是第一位是正负号,后面是0-9的数字):");
scanf("%[^\n]",ss);
getchar();
for(int i=1;i<strlen(ss);i++){
if(!((ss[0]=='-' || ss[0]=='+') && (ss[i]>='0' && ss[i]<='9'))){
return 0;
}
}
int j=0;
for(int i=strlen(ss)-1;i>0;i--){
j++;
if(j==4 || i==1){
int sum=0;
for(int k=i;k<i+j;k++){
sum=sum*10+(ss[k]-'0');
}
ListInsert(L,sum);
j=0;
}
}
if(ss[0]=='-'){
L->data=-L->data;
}
if(L->data==0){
return 0;
}
return 1;
}
//链表的输出
void Output(LinkList &L){
LinkList p=L->prior;
if(L->data<0){
printf("-");
}
while(p!=L){
if(p->next!=L){
printf("%04d",p->data);
}
else{
printf("%d",p->data);
}
if(p->prior!=L){
printf(",");
}
p=p->prior;
}
printf("\n");
}
//主函数
int main(){
int select,flag=1;
LinkList a,b,c;
menu();
InitList(a);
InitList(b);
InitList(c);
printf("请在链表a中输入一个数,并按回车结束\n");
if(!GetNum(a)){
printf("输入的格式有误,输入格式是第一位是正负号,后面是0-9的数字\n");
}
printf("请请在链表b中输入一个数,并按回车结束\n");
if(!GetNum(b)){
printf("输入的格式有误,输入格式是第一位是正负号,后面是0-9的数字\n");
}
while(flag==1){
printf("您选择的操作是:");
fflush(stdin);
int s;
scanf("%d",&select);
switch(select){
case 1:
while(c->data!=0){
ListDelete(c);
}
printf("c链表重置成功\n");
InitList(c);
break;
case 2:
printf("a+b=");
Add(a,b,c);
Output(c);
break;
case 3:
printf("a-b=");
Sub(a,b,c);
Output(c);
break;
case 4:
printf("a*b=");
Mul(a,b,c);
Output(c);
break;
case 5:
printf("a/b=");
if(abs(b->data)==1 && b->next->data==0){ //b为0
printf("分子不能为0");
}
Div(a,b,c);
Output(c);
break;
case 6:
Impl(a,c);
printf("a^n=");
Output(c);
break;
case 7:
printf("a!=");
Impl_Factorial(a,c);
Output(c);
break;
default:
printf("您选择退出程序,欢迎下次光临!\n");
flag=0;
}
}
}