计算器(C语言数据结构课设,带界面详解)

该博客介绍了使用C语言和Easyx图形库实现的一个简单计算器的代码。程序通过鼠标点击图形界面的数字和运算符进行输入,遵循运算符优先级计算表达式的结果。核心算法包括栈的使用,用于处理运算符的优先级和括号。
摘要由CSDN通过智能技术生成

运行结果:

 界面采用easyx图形包,运行前需要下载easyx

源码:

#include <stdio.h>
#include <graphics.h>
#include <conio.h>
#include <time.h>
#include<math.h>
#include <stdlib.h>


#define OK    1
#define ERROR	 0

/* 定义结点结构体 */
typedef struct node
{
	int data;                   //数据域
	struct node* next;         //指针域
}Node;

/* 定义栈结构体 */
typedef struct stack
{
	Node* top;            //栈顶标记
	int count;            //栈内计数器
}Stack;

int Priority(char s);//自定义优先级
int InitStack(Stack* S); //初始化栈
int EmptyStack(Stack* S);//判空
int GetTop(Stack* S);    //获取栈顶
int Push(Stack* S, int e);   //进栈
int Pop(Stack* S);           //出栈
void Paint();            //页面绘制
double dis(int x1, int y1, int x2, int y2);

int main()
{
	Paint();
}


/* 自定义优先级 */
int Priority(char s)
{
	switch (s)
	{
	case '(':				//括号优先级最高
		return 3;
	case '*':
	case '/':
	case '%':
	case '^':	            //乘除取余幂次次之
		return 2;
	case '+':
	case '-':				//加减最低
		return 1;
	default:
		return 0;
	}
}


/* 初始化栈 */
int InitStack(Stack* S)
{
	S->top = NULL;
	S->count = 0;

	return OK;
}


/* 判空 */
int EmptyStack(Stack* S)
{
	return (S->count == 0) ? OK : ERROR;
}


/* 获取栈顶 */
int GetTop(Stack* S)
{
	if (NULL == S->top)
		return ERROR;

	return (S->top->data);
}


/* 进栈 */
int Push(Stack* S, int e)
{
	Node* p = (Node*)malloc(sizeof(Node));   //创建新结点p
	if (p == NULL)   //判断是否申请成功
	{
		return ERROR;
	}
	p->data = e;            //初始化
	p->next = S->top;       //头插法 
	S->top = p;
	S->count++;            //计数器加1

	return OK;
}


/* 出栈 */
int Pop(Stack* S)     //出栈返回一个操作数或者是运算符
{
	int e;

	if (NULL == S->top)    //栈空无法出栈
		return ERROR;

	Node* p = S->top;      
	e = p->data;
	S->top = p->next;
	free(p);
	S->count--;       //计数器减一

	return e;
}

void Paint() {
	int number;
	// 初始化图形模式
	initgraph(300, 600);   //初始化一个300*600的画布
	// 设置背景为深灰色
	setbkcolor(RGB(51, 51, 51));    //设置背景为深灰色
	int c;
	for (int y = 0; y < 20; y++) {
		setcolor(RGB(51, 51, 51));   //设置线条颜色为灰色
		line(0, y, 400, y);      //用循环语句画平行直线Line(x1,y1)(x2,y2)为直线的两个端点的坐标
	}
	//设置文本颜色
	settextcolor(WHITE);      //设置当前文字颜色
	//输出文本信息
	settextstyle(20, 10, L"宋体");//字体的宽+字体的高+字体样式
	//输出文本信息
	outtextxy(10, 0, L"计算器");//文本坐标+文本内容(在指定位置输出字符串)

	settextstyle(40, 0, L"黑体");
	setbkmode(TRANSPARENT); //这个函数用于设置当前设备图案填充和文字输出时的背景模式。背景是透明的。
	//画橙色圆
	setcolor(RGB(220, 95, 8));//设置前景颜色
	setfillcolor(RGB(220, 95, 8));  //设置充填颜色 
	setbkcolor(BLACK);  //背景颜色
	fillcircle(255, 550, 30);  //画有边框的充填原圆(x,y,z)为坐标
	settextcolor(WHITE);      //设置当前文字颜色
	outtextxy(245, 533, L"=");
	setcolor(RGB(247, 143, 0));
	setfillcolor(RGB(247, 143, 0));
	setbkcolor(BLACK);
	settextcolor(WHITE);
	fillcircle(255, 480, 30);
	outtextxy(245, 463, L"+");
	fillcircle(255, 410, 30);
	outtextxy(245, 393, L"-");
	fillcircle(255, 340, 30);
	settextstyle(30, 0, L"黑体");
	outtextxy(240, 325, L"×");
	fillcircle(255, 270, 30);
	outtextxy(240, 255, L"÷");
	//画深色圆
	setcolor(RGB(51, 51, 51));
	setfillcolor(RGB(51, 51, 51));
	setbkcolor(BLACK);
	//右边
	settextcolor(WHITE);
	settextstyle(40, 0, L"黑体");
	fillcircle(185, 550, 30);   //圆
	outtextxy(180, 530, L")");
	fillcircle(185, 480, 30);
	outtextxy(175, 460, L"3");
	fillcircle(185, 410, 30);
	outtextxy(175, 390, L"6");
	fillcircle(185, 340, 30);
	outtextxy(175, 320, L"9");
	/*fillcircle(185, 270, 30);*/
	//中间
	fillcircle(115, 550, 30);
	outtextxy(105, 530, L"0");
	fillcircle(115, 480, 30);
	outtextxy(105, 460, L"2");
	fillcircle(115, 410, 30);
	outtextxy(105, 390, L"5");
	fillcircle(115, 340, 30);
	outtextxy(105, 320, L"8");
	//左边
	fillcircle(45, 550, 30);
	outtextxy(35, 530, L"(");
	fillcircle(45, 480, 30);
	outtextxy(35, 460, L"1");
	fillcircle(45, 410, 30);
	outtextxy(35, 390, L"4");
	fillcircle(45, 340, 30);
	outtextxy(35, 320, L"7");
	//画浅色圆
	setcolor(RGB(165, 165, 165));
	setfillcolor(RGB(165, 165, 165));
	setbkcolor(BLACK);
	settextcolor(WHITE);
	fillcircle(185, 270, 30);
	outtextxy(175, 252, L"%");
	fillcircle(115, 270, 30);
	settextstyle(40, 0, L"黑体");
	outtextxy(105, 265, L"^");
	fillcircle(45, 270, 30);
	outtextxy(20, 255, L"√");

	/*Stack num, opt;*/
	char str[100] = { 0 };
	int i = 0, tmp = 0, j;
	int count = 0;
	MOUSEMSG m;
	int temp = 0, k = 255, go = 0;
	//设置文本颜色
	settextcolor(WHITE);
	//设置文本样式
	settextstyle(40, 0, L"黑体");//字体的宽+字体的高+字体样式
	while (go == 0)
	{
		m = GetMouseMsg();
		switch (m.uMsg)
		{
		case WM_LBUTTONDOWN:
			while (dis(m.x, m.y, 255, 550) > 30)
			{
				if (dis(m.x, m.y, 45, 480) <= 30) {
					str[i] = '1';
				}
				if (dis(m.x, m.y, 115, 480) <= 30) {
					str[i] = '2';
				}
				if (dis(m.x, m.y, 185, 480) <= 30) {
					str[i] = '3';
				}
				if (dis(m.x, m.y, 45, 410) <= 30) {
					str[i] = '4';
				}
				if (dis(m.x, m.y, 115, 410) <= 30) {
					str[i] = '5';
				}
				if (dis(m.x, m.y, 185, 410) <= 30) {
					str[i] = '6';
				}
				if (dis(m.x, m.y, 45, 340) <= 30) {
					str[i] = '7';
				}
				if (dis(m.x, m.y, 115, 340) <= 30) {
					str[i] = '8';
				}
				if (dis(m.x, m.y, 185, 340) <= 30) {
					str[i] = '9';
				}
				if (dis(m.x, m.y, 45, 550) <= 30) {
					str[i] = '(';
				}
				if (dis(m.x, m.y, 115, 550) <= 30) {
					str[i] = '0';
				}
				if (dis(m.x, m.y, 185, 550) <= 30) {
					str[i] = ')';
				}
				if (dis(m.x, m.y, 255, 550) <= 30) {
					str[i] = '=';
				}
				if (dis(m.x, m.y, 255, 480) <= 30) {
					str[i] = '+';
				}
				if (dis(m.x, m.y, 255, 410) <= 30) {
					str[i] = '-';
				}
				if (dis(m.x, m.y, 255, 340) <= 30) {
					str[i] = '*';
				}
				if (dis(m.x, m.y, 255, 270) <= 30) {
					str[i] = '/';
				}
				if (dis(m.x, m.y, 45, 270) <= 30) {
					str[i] = '~';
				}
				if (dis(m.x, m.y, 115, 270) <= 30) {
					str[i] = '^';
				}
				if (dis(m.x, m.y, 185, 270) <= 30) {
					str[i] = '%';
				}
				/*setbkcolor(BLACK);*/
				for (int y = 20; y < 200; y++) {
					setcolor(BLACK);
					line(0, y, 400, y);
				}
				settextcolor(WHITE);
				for (j = 0; j <= count; j++)
				{
					if (count < 12) {
						outtextxy(k - 20 * (count - j), 50, str[j]);
					}
					else if (count < 18) {
						settextstyle(30, 0, L"黑体");
						outtextxy(k - 15 * (count - j), 50, str[j]);
					}
					else {
						settextstyle(20, 0, L"黑体");
						outtextxy(k - 10 * (count - j), 50, str[j]);
					}

				}
				//outtextxy(k, 50, str[i]);
				Sleep(1000);
				i++;
				count++;
				break;
			}
			break;
		case WM_RBUTTONUP:
			//go = 1;
			//number = result(str);



			//从这里开始是核心代码


			Stack num, opt;          

			//申请两个栈


			int i = 0, tmp = 0, j;
			InitStack(&num) != OK || InitStack(&opt) != OK;   
			while (str[i] != '\0' || EmptyStack(&opt) != OK)  
			{
				if (str[i] >= '0' && str[i] <= '9')
				{
					tmp = tmp * 10 + str[i] - '0';//可取出非个位数的数字
					i++;
					if (str[i] < '0' || str[i] > '9')//遇到符号就将符号前的数字压栈
					{
						Push(&num, tmp);
						tmp = 0;  //将数字初始化为0
					}
				}
				else
				{
					//进栈不运算
					if ((EmptyStack(&opt) == OK) || (GetTop(&opt) == '(' && str[i] != ')') ||
						Priority(str[i]) > Priority(GetTop(&opt)))
					{
						Push(&opt, str[i]);
						i++;
						continue;
					}
					//出栈不运算
					if (GetTop(&opt) == '(' && str[i] == ')')
					{
						Pop(&opt);
						i++;
						continue;

					}
					//出栈运算
					if ((str[i] != '\0' && EmptyStack(&opt) != OK) || (str[i] == ')' && GetTop(&opt) != '(') ||
						Priority(str[i]) <= Priority(GetTop(&opt)))
					{
						switch (Pop(&opt))
						{
						case '+':
							Push(&num, Pop(&num) + Pop(&num));//将结果压栈
							break;
						case '-':
							j = Pop(&num);
							Push(&num, Pop(&num) - j);
							break;
						case '*':
							Push(&num, Pop(&num) * Pop(&num));
							break;
						case '/':
							j = Pop(&num);
							Push(&num, Pop(&num) / j);
							break;
						case '%':
							j = Pop(&num);
							Push(&num, Pop(&num) % j);
							break;
						case '^':
							j = Pop(&num);
							Push(&num, pow(Pop(&num), j));
							break;
						case '~':
							j = Pop(&num);
							Push(&num, pow(Pop(&num), 0.5));
							break;
						}
						continue;
					}
				}
			}

			//打印结果
			for (int y = 150; y < 200; y++) {
				setcolor(BLACK);
				line(0, y, 300, y);
			}
			TCHAR s[10];
			int Num = 0, Num1 = 0;
			Num1 = Pop(&num);//标记结果
			Num = Num1;
			int cnt = 0;
			while (Num >= 10) {
				Num /= 10;
				cnt++;
			}
			_stprintf_s(s, _T("%d"), Num1);
			settextcolor(WHITE);
			settextstyle(50, 0, L"黑体");
			outtextxy(255 - 25 * cnt, 150, s);
			break;
		}
	}

	getchar();
}


//判断距离
double dis(int x1, int y1, int x2, int y2) {
	int inX = (x1 - x2) * (x1 - x2);
	int inY = (y1 - y2) * (y1 - y2);
	double r = 0.0;
	r = sqrt(inX + inY);
	return r;
}

  • 6
    点赞
  • 107
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值