⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wjdlg.cpp

📁 C++MFC图形界面实现
💻 CPP
字号:
// wjDlg.cpp : implementation file
//

#include "stdafx.h"
#include "wj.h"
#include "wjDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

///////////////////////////////////////////////////////////////////////////////
//	名称:可编程计算器
//	功能描述:
//	本计算器可以实现对诸如 3+(1+7)*6+4*((5+4))这样的表达式的计算,
//      目前仅限于带括号的 +, * 运算
//	实现描述:
//	本计算器的是在教材 pp.49, 文法 (3.8)基础上稍加修改后,
//      利用自上而下的递归程序实现。每个非终结符对应一个分析函数。
//		
//		修改后的文法如下所示,其中 e 代表空串
//
//		E-->TE'
//		E'-->+TE'|-TE'|e
//		T-->FT'
//		T'-->*FT'|/FT'|e
//		F-->(E)|num
//
//	程序中使用了一个词法分析函数 yylex,变量yylval代表最近的整数
//      记号的数值。'\0'对应着$符号,预示着输入串结束.
//		
///////////////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>

// 这一段是极好的定义
#define ADD 0
#define MIN 1
#define MUL 2
#define DIV	3
#define LBRACE 4
#define RBRACE 5
#define NUM	6
#define END 7
#define OTHER 8

char input[200];	// 输入串。
int lookahead;
int pCur;
double yylval;
char last;
char before;
CString error;

// 函数声明
int yylex();
void Match(int t);
double T();
double E_();
double E();
double T_();
double F();

// 词法分析器,读入一个记号
int yylex()
{
	char num[20];
	int temp = 0;
	
	// 过滤掉空白
	while ( input[pCur]==' ' ) pCur++;
	
	// 如果是数字(可以带小数点),那么把这个记号的数值计算出来放在 yylval 中
	while (input[pCur] >= '0' && input[pCur] <= '9'||input[pCur]=='.'){
		num[temp++] = input[pCur++];
	}
	if (temp >0) 
	{
		sscanf(num, "%lf", &yylval);
		return NUM;
	}

     last = input[pCur];
     before = input[pCur-1];
	// 其他记号的处理
	switch (input[pCur++])	// 注意:这里指针往前移了一位
	{
	case '+':	return ADD;
	case '-':	return MIN;
	case '*':	return MUL;
	case '/':	return DIV;
	case '(':	return LBRACE;
	case ')':	return RBRACE;
	case '\0':	return END;
	default:	return OTHER;
	}
}

// 匹配函数,若当前记号与参数相同,则读入下一个记号
void Match(int t)
{
	if (lookahead == t) 
		lookahead = yylex();
	else 
	{
		error = "括号不匹配,左括号和右括号必须成对出现!\n";
		throw error;
	}
}

// 处理 E-->TE'
double E()
{
	switch (lookahead)
	{
	case LBRACE:	// FIRST(E)={(,num}
	case NUM:
		return T() + E_();
	case MIN:
		Match(MIN);
        return -T() + E_();
	case END:
		error = "";
		error = error + "表达式不能以字符 " + before +" 结尾!\n表达式只能以右括号或数字结尾!\n";
		throw error;
		break;
	default:
		if(pCur == 1)
		{
			error = "";
			error = error + "表达式不能以字符 "+ last +" 开头!\n表达式只能以左括号或数字开头!\n";
			throw error;
		}
		else
		{
			error = "";
			error = error + "左括号后不能跟字符 "+ last +" !\n左括号后只能跟左括号或数字!\n";
			throw error;
		}
		
	}		
}

// 处理 E'-->+TE'|-TE'|e
double E_()
{
	switch (lookahead)
	{
	case ADD:			// FIRST(E')={+,-,e}
		Match(ADD); 
		return T() + E_();
	case MIN:
		Match(MIN);
		return -T() + E_();
	case RBRACE:	// E'-->e 的情况,这个时候需要处理 FOLLOW集合, FOLLOW(E')={), $}
	case END:
		return 0;
	default:
		error = "不可能发生的错误!";
		throw error; //这个错误一般不会发生,因为在他执行之前如果有错误的话一般会被发现。
	}	
}

// 处理 T-->FT'
double T()
{
	switch (lookahead)
	{
	case LBRACE:	// FIRST(T)={(,num}
	case NUM:
		return F()*T_();
	case END:
		error = "";
		error = error + "\n表达式不能以操作符 "+ before +" 结尾!\n";
		throw error;
	default:
		error = "";
		error = error + "表达式中操作符 "+ before +" 后的字符 "+ last +" 不合法!\n操作符 "+ before +" 后只能跟数字或者左括号!\n";
		throw error;
	}
}

// 处理 T'-->*FT'|/FT'|e
double T_()
{
	switch (lookahead)
	{
	case MUL:	// FIRST(T')={*,/,e}
		Match(MUL);
		return F() * T_();
	case DIV:
		Match(DIV);
		return 1/F() * T_();
	case ADD:	// T'-->e 的情况,这个时候需要处理 FOLLOW集合, FOLLOW(T')={+,-,),$}
	case MIN:
	case RBRACE:
	case END:
		return 1;
	case NUM:
		error = "右括号后不能直接跟数字,只能跟+、-、*、/操作符!";
		throw error;
	default:
		error = "";
		error = error + "字符 + before + 后不能跟字符 " + last + " !\n数字或右括号后只能跟+、-、*、/和右括号!\n";
		throw error;
	}		
}

// 处理 F-->(E)|num
double F()
{
	double temp;
	
	switch(lookahead)
	{
	case LBRACE:	// FIRST((E))={(}
		Match(LBRACE);
		temp = E();
		Match(RBRACE);
		return temp;
	case NUM:		// FIRST(num) = {num}
		temp = yylval;
		Match(NUM);
		return temp;
	case END:
		error = "";
		error = error + "表达式不能以操作符 " + before + " 结尾!\n";
		throw error;
	default:
		error = "";
		error = error + "表达式中操作符 "+ before +" 后的字符 "+ last +" 不合法!\n操作符 "+ before +" 后只能跟数字或者左括号!\n";
		throw error;
	}
}
/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog
{
public:
	CAboutDlg();

// Dialog Data
	//{{AFX_DATA(CAboutDlg)
	enum { IDD = IDD_ABOUTBOX };
	//}}AFX_DATA

	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CAboutDlg)
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
	//}}AFX_VIRTUAL

// Implementation
protected:
	//{{AFX_MSG(CAboutDlg)
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
	//{{AFX_DATA_INIT(CAboutDlg)
	//}}AFX_DATA_INIT
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CAboutDlg)
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
	//{{AFX_MSG_MAP(CAboutDlg)
		// No message handlers
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CWjDlg dialog

CWjDlg::CWjDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CWjDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CWjDlg)
	m_air = _T("");
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CWjDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CWjDlg)
	DDX_Text(pDX, IDC_EDIT1, m_air);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CWjDlg, CDialog)
	//{{AFX_MSG_MAP(CWjDlg)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_BUTTON1, OnButton1)
	ON_BN_CLICKED(IDC_BUTTON2, OnButton2)
	ON_BN_CLICKED(IDC_BUTTON3, OnButton3)
	ON_BN_CLICKED(IDC_BUTTON4, OnButton4)
	ON_BN_CLICKED(IDC_BUTTON5, OnButton5)
	ON_BN_CLICKED(IDC_BUTTON6, OnButton6)
	ON_BN_CLICKED(IDC_BUTTON7, OnButton7)
	ON_BN_CLICKED(IDC_BUTTON8, OnButton8)
	ON_BN_CLICKED(IDC_BUTTON9, OnButton9)
	ON_BN_CLICKED(IDC_BUTTON10, OnButton10)
	ON_BN_CLICKED(IDC_BUTTON11, OnButton11)
	ON_BN_CLICKED(IDC_BUTTON12, OnButton12)
	ON_BN_CLICKED(IDC_BUTTON13, OnButton13)
	ON_BN_CLICKED(IDC_BUTTON14, OnButton14)
	ON_BN_CLICKED(IDC_BUTTON15, OnButton15)
	ON_BN_CLICKED(IDC_BUTTON16, OnButton16)
	ON_BN_CLICKED(IDC_BUTTON17, OnButton17)
	ON_BN_CLICKED(IDC_BUTTON18, OnButton18)
	ON_BN_CLICKED(IDC_BUTTON19, OnButton19)
	ON_BN_CLICKED(IDC_BUTTON20, OnButton20)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CWjDlg message handlers

BOOL CWjDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// Add "About..." menu item to system menu.

	// IDM_ABOUTBOX must be in the system command range.
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		CString strAboutMenu;
		strAboutMenu.LoadString(IDS_ABOUTBOX);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon
	
	// TODO: Add extra initialization here
	
	return TRUE;  // return TRUE  unless you set the focus to a control
}

void CWjDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialog::OnSysCommand(nID, lParam);
	}
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CWjDlg::OnPaint() 
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

// The system calls this to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CWjDlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}

void CWjDlg::OnButton1() 
{
	// TODO: Add your control notification handler code here
		m_air=m_air+"1";
	UpdateData(FALSE);
}

void CWjDlg::OnButton2() 
{
	// TODO: Add your control notification handler code here
		m_air=m_air+"2";
	UpdateData(FALSE);
}

void CWjDlg::OnButton3() 
{
	// TODO: Add your control notification handler code here
		m_air=m_air+"3";
	UpdateData(FALSE);
}

void CWjDlg::OnButton4() 
{
	// TODO: Add your control notification handler code here
		m_air=m_air+"4";
	UpdateData(FALSE);
}

void CWjDlg::OnButton5() 
{
	// TODO: Add your control notification handler code here
		m_air=m_air+"5";
	UpdateData(FALSE);
}

void CWjDlg::OnButton6() 
{
	// TODO: Add your control notification handler code here
		m_air=m_air+"6";
	UpdateData(FALSE);
}

void CWjDlg::OnButton7() 
{
	// TODO: Add your control notification handler code here
		m_air=m_air+"7";
	UpdateData(FALSE);
}

void CWjDlg::OnButton8() 
{
	// TODO: Add your control notification handler code here
		m_air=m_air+"8";
	UpdateData(FALSE);
}

void CWjDlg::OnButton9() 
{
	// TODO: Add your control notification handler code here
		m_air=m_air+"9";
	UpdateData(FALSE);
}

void CWjDlg::OnButton10() 
{
	// TODO: Add your control notification handler code here
		m_air=m_air+"0";
	UpdateData(FALSE);
}

void CWjDlg::OnButton11() 
{
	// TODO: Add your control notification handler code here
		m_air=m_air+"(";
	UpdateData(FALSE);
}

void CWjDlg::OnButton12() 
{
	// TODO: Add your control notification handler code here
		m_air=m_air+")";
	UpdateData(FALSE);
}

void CWjDlg::OnButton13() 
{
	// TODO: Add your control notification handler code here
		m_air=m_air+"+";
	UpdateData(FALSE);
}

void CWjDlg::OnButton14() 
{
	// TODO: Add your control notification handler code here
	m_air=m_air+"-";
	UpdateData(FALSE);
}

void CWjDlg::OnButton15() 
{
	// TODO: Add your control notification handler code here
		m_air=m_air+"*";
	UpdateData(FALSE);
}

void CWjDlg::OnButton16() 
{
	// TODO: Add your control notification handler code here
		m_air=m_air+"/";
	UpdateData(FALSE);
}

void CWjDlg::OnButton17() 
{
	// TODO: Add your control notification handler code here
	pCur = 0;
	UpdateData(TRUE); // 从控件把文本传送到变量
	int i;
	for(i=0; i< m_air.GetLength(); i++)
		input[i] = m_air[i];
	input[i] = '\0';
	lookahead = yylex();
	double answer;
	try
	{
		answer = E();
	}
	catch(CString error)
	{
		AfxMessageBox(error);
		return;
	}
	if(lookahead != END)
	{
		AfxMessageBox("没有左括号和最后的右括号匹配!");
		return;
	}
	char output[20];
	_gcvt(answer, 5, output);
	m_air = output;
	if(m_air[m_air.GetLength()-1] == '.')
	{
		output[m_air.GetLength()-1] = '\0';
		m_air = output;
	}
	UpdateData(FALSE);	//	从变量把文本传送到控件

}


void CWjDlg::OnButton18() 
{
	// TODO: Add your control notification handler code here
	m_air="";
	UpdateData(FALSE);
}

void CWjDlg::OnButton19() 
{
	// TODO: Add your control notification handler code here
	m_air.Delete(m_air.GetLength()-1);
	UpdateData(FALSE);
}

void CWjDlg::OnButton20() 
{
	// TODO: Add your control notification handler code here
	m_air=m_air+".";
	UpdateData(FALSE);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -