一、 问题描述:
利用线性表相关知识,编程实现一个大整数计算器,该计算器可以完成大整数的加、减、乘、除四则运算。
二、设计与实现:
这里用带头结点的循环双链表的相关操作来模拟大整数计算器的四则运算过程。
#include <stdio.h>
……
三、代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
#define MAX 1000
typedef struct Node{
int data;
struct Node *prev;
struct Node *next;
}Node;
typedef struct {
Node *head;
int len;
}List;
// 定义带头结点的循环双链表
List *CreateList() {
List *l = (List*)malloc(sizeof(List)); // 创建头节点
l->head = (Node*)malloc(sizeof(Node));
l->head->prev = l->head;
l->head->next = l->head;
l->len = 0;
return l; // 返回头节点指针
}
//在链表前端插入元素
void insertFront(List *l, int data) {
Node *newNode = (Node*)malloc(sizeof(Node));
newNode->data = data;
newNode->prev = l->head->prev;
newNode->next = l->head;
l->head->prev->next = newNode;
l->head->prev = newNode;
l->len++;
}
//在链表末尾插入元素
void insertEnd(List *l, int data) {
Node *newNode = (Node*)malloc(sizeof(Node));
newNode->data = data;
newNode->next = l->head->next;
newNode->prev = l->head;
l->head->next->prev = newNode;
l->head->next = newNode;
l->len++; // 头节点存储数字的位数加1
}
// 从字符串中读取大整数并转换成循环双链表的函数
List *fromString(char *str) {
List *l =CreateList();
int len = strlen(str);
int i;
for (i = len - 1; i >= 0; i--) {
insertFront(l, str[i] - '0');
}
return l;
}
//输出链表
void printList(List *l) {
Node *p = l->head->prev;
int cnt=0;
while(p->data==0) p=p->prev;
while (p != l->head) {
printf("%d",p->data);
cnt++;
p = p->prev;
}
if(cnt==0)
printf("0");
}
//释放链表
void freeList(List *l) {
Node *p = l->head->next;
while (p != l->head) {
Node *tmp = p->next;
free(p);
p = tmp;
}
free(l->head);
free(l);
}
//循环双链表的加法运算
List *add(List *a, List *b) {
List *c =CreateList();
Node *pa = a->head->next;
Node *pb = b->head->next;
int carry = 0; // 进位标志
while (pa != a->head || pb != b->head) {
int x = pa == a->head ? 0 : pa->data;
int y = pb == b->head ? 0 : pb->data;
int sum = x + y + carry;
insertFront(c, sum % 10);
carry = sum / 10;
if (pa != a->head) pa = pa->next;
if (pb != b->head) pb = pb->next;
}
if (carry > 0) {
insertFront(c, carry);
}
return c;
}
//循环双链表的减法运算
List *sub(List *a, List *b) {
List *c =CreateList();
Node *pa = a->head->next;
Node *pb = b->head->next;
int borrow = 0; // 借位标志
while (pa != a->head) {
int x = pa->data - borrow;
int y = pb == b->head ? 0 : pb->data;
int diff = x - y;
if (diff < 0) {
borrow = 1;
diff += 10;
} else {
borrow = 0;
}
insertFront(c, diff);
pa = pa->next;
if (pb != b->head) pb = pb->next;
}
// 去除高位的0
Node *pc=c->head->prev;
while(pc->data==0){
pc=pc->prev;
c->len--;
}
c->head->prev=pc;
pc->next=c->head;
return c;
}
// 循环双链表的乘法运算
List *mul(List *a, List *b) {
List *c =CreateList();
Node *pa = a->head->next;
Node *pb = b->head->next;
int cnt=0;
while (pb != b->head) {
List *tmp =CreateList();
int i;
for(i=0;i<cnt;i++){
insertFront(tmp,0);
}
cnt++;
int carry = 0;
while (pa != a->head) {
int x = pa->data;
int y = pb->data;
int sum= x * y + carry;
insertFront(tmp,sum% 10);
carry =sum/ 10;
pa = pa->next;
}
if (carry > 0) {
insertFront(tmp, carry);
}
c = add(c, tmp);
freeList(tmp);
pb = pb->next;
pa = a->head->next;
}
return c;
}
//比较链表中数字大小
int cmp(List *a,List *b){
if(a->len>b->len)
return 1;
else if(a->len<b->len)
return 0;
Node *pa=a->head->prev;
Node *pb=b->head->prev;
int n=a->len;
int i;
for(i=0;i<n;i++){
if(pa->data>pb->data)
return 1;
else if(pa->data<pb->data)
return 0;
pa=pa->prev;
pb=pb->prev;
}
return 2;
}
// 循环双链表的除法运算
List *div(List *a, List *b) {
int i;
List *c =CreateList();
List *tmp =CreateList();
List *y=CreateList();
List *s =CreateList();
Node *pa=a->head;
Node *q;
for(i=0;i<b->len;i++) pa=pa->prev;
q=pa->prev;
while(pa!=a->head){
insertFront(tmp,pa->data);
pa=pa->next;
}
pa=q;
for(i=0;i<=a->len-b->len;i++){
int cnt=0; // 统计商的位数
while(1){
int jud=cmp(b,tmp);
if(jud==1){
insertFront(c,cnt);
break;
}else if(jud==0){
tmp=sub(tmp,b);
cnt++;
}else{
tmp=CreateList();
cnt++;
insertFront(c,cnt);
break;
}
}
insertEnd(tmp,pa->data);
pa=pa->prev;
}
Node *pc=c->head->next;
while(pc->data==0) pc=pc->next;
while(pc!=c->head){
printf("%d",pc->data);
pc=pc->next;
}
return c;
}
int main() {
int op;
char s1[MAX], s2[MAX];
List* num1, *num2;
printf("****************************************\n");
printf("| ★大整数四则运算计算器★ |\n");
printf("****************************************\n");
printf(" || 1--加法运算 || \n");
printf(" || 2--减法运算 || \n");
printf(" || 3--乘法运算 || \n");
printf(" || 4--除法运算 || \n");
printf(" || 5--重新开始 || \n");
printf(" || 0--退出 || \n");
printf("****************************************\n");
printf("■请选择菜单(0-5):");
scanf("%d",&op);
while(!(op==1||op==2||op==3||op==4||op==5||op==0)){
printf("■输入选择不明确,请重输:");
scanf("%d",&op);
}
while(1){
if(op!=5&&op!=0) {
printf("■请输入第1个长整数:");
scanf("%s",&s1);
printf("■请输入第2个长整数:");
scanf("%s",&s2);
num1 = fromString(s1);
num2 = fromString(s2);
}
if(op==1){
List *res=add(num1,num2);
printf("■%s+%s=",s1,s2);
printList(res);
break;
}else if(op==2){
List *res=sub(num1,num2);
printf("■%s-%s=",s1,s2);
printList(res);
break;
}else if(op==3){
List *res=mul(num1,num2);
printf("■%s×%s=",s1,s2);
printList(res);
break;
}else if(op==4){
printf("■%s÷%s=",s1,s2);
List *res=div(num1,num2);
break;
}else if(op==5){
continue;
}else if(op==0){
printf("欢迎下次使用!");
printf("\n");
exit(0);
}
}
printf("\n\n");
printf("※按任意键返回主菜单,继续其他类型运算...※");
printf("\n\n");
Sleep(100000);
return 0;
}
四、运行结果