📄 unit1.pas
字号:
Unit Unit1;
Interface
Uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ComCtrls, OleCtnrs, ExtCtrls, Buttons;
Type
TFormMain = Class(TForm)
TabSheet1 : TTabSheet;
Label7 : TLabel;
EditFormula : TRichEdit;
BtnDeleteAll1 : TButton;
TabSheet2 : TTabSheet;
Label1 : TLabel;
Label2 : TLabel;
Label3 : TLabel;
Label4 : TLabel;
Label5 : TLabel;
NongDuA : TEdit;
MassA : TEdit;
NongDuB : TEdit;
NongDuMixed : TEdit;
MassMixed : TEdit;
Memo1 : TMemo;
BtnCalc : TButton;
MassB : TEdit;
BtnDeleteAll2 : TButton;
TabSheet3 : TTabSheet;
Label11 : TLabel;
Button2 : TButton;
PageControl : TPageControl;
Label14 : TLabel;
TabSheet4 : TTabSheet;
Memo6 : TMemo;
Panel1 : TPanel;
EditReactor : TRichEdit;
Memo2 : TMemo;
Memo3 : TMemo;
AddToReactor : TButton;
DeleteIt1 : TButton;
Panel2 : TPanel;
EditOut : TRichEdit;
Memo4 : TMemo;
Memo5 : TMemo;
Label9 : TLabel;
Label6 : TLabel;
Label10 : TLabel;
BtnBalance : TButton;
Label8 : TLabel;
Label12 : TLabel;
Label13 : TLabel;
AddToOut : TButton;
DeleteIt2 : TButton;
BtnDelete : TButton;
Procedure FormCreate(Sender : TObject);
Procedure BtnDeleteAll2Click(Sender : TObject);
Procedure BtnDeleteAll1Click(Sender : TObject);
Procedure BtnDeleteClick(Sender : TObject);
Procedure DeleteIt1Click(Sender : TObject);
Procedure AddToReactorClick(Sender : TObject);
Procedure EditFormulaKeyDown(Sender : TObject; Var Key : Word;
Shift : TShiftState);
Procedure TabSheet1Show(Sender : TObject);
Procedure EditFormulaKeyPress(Sender : TObject; Var Key : Char);
Procedure EditFormulaChange(Sender : TObject);
Procedure Button2Click(Sender : TObject);
Procedure BtnCalcClick(Sender : TObject);
Procedure BtnBalanceClick(Sender : TObject);
private
EditFormulaShiftPress : Boolean; //记录化学式输入框是否接收到Shift
EditFormulaWordKey : Byte; //记录化学式输入框接收到的键值
public
Procedure NumberOnlyEditKeyDown(Sender : TObject; Var Key : Word; Shift : TShiftState); //溶液信息编辑框只可接收数字的实现
Procedure NumberOnlyEditEnter(Sender : TObject);
End;
TSolution = Record //溶液的信息
NongDu : Single; //溶液的浓度
Mass : Single; //溶液的体积
End;
IntArray = Array Of Integer; //整数组
SingleArray = Array Of Single; //小数组
TReactorOrOutPut = Record //反应物或生成物信息类
IsReactor : Boolean; //是否是反应物
Str : String; //反应物或生成物的化学式
Mass : Single;
EachElementCou : IntArray; //每个化学式中的每个元素的数目
Num : Integer; //配平结果
End;
TEquation = Record //一元一次方程类
Nums : IntArray; //未知数的系数
Constant : Integer; //常数
End;
TEqArr = Array Of TEquation;
TFraction = Record //模拟分数的一个类 Fraction:分数
Numerator : Integer; //分子
Denominator : Integer; //分母
End;
TResultArr = Array Of TFraction; //分数组
TBalancer = Class
private
Procedure RebuildReactors; //重构各反应物与生成物,获取每种元素出现次数
Procedure GetElementTypes; //获取所用到的各种元素
Procedure PrepareEquations; //准备方程组
Procedure GetNums; //通过解方程获得各反应物或生成物的系数
///////分数处理函数////////////////////
Function Fraction_CreateOne(Numerator, Denominator : Integer) : TFraction; //生成一个分数
Function Fraction_MinMultiple(Num1, Num2 : Integer) : Integer; //获得两数的最小公倍数;Multiple:倍数
Function Fraction_MaxDivisor(Num1, Num2 : Integer) : Integer; //获得两数的最大公约数
Function Fraction_Minus(Num1, Num2 : TFraction) : TFraction; //两分数相减,Num1-Num2
Function Fraction_Multiplination(Num1, Num2 : TFraction) : TFraction; //两分数相乘
Function Fraction_Division(Num1, Num2 : TFraction) : TFraction; //两分数相除,Num1/Num2
Procedure Fraction_Simplify(Var Num : TFraction); //对分数进行化简
public
Elements : TStringList; //记载所有用到的元素
Actors : Array Of TReactorOrOutPut; //反应物与生成物
ReactorsCou, OutPutCou : Integer; //分别记载反应物与生成物的数目
AllCou : Integer; //记载反应物与生成物的总数目
Equations : TEqArr; //方程
Procedure Work; //进行配平
Procedure MyInitialization; //进行初始化
End;
Var
FormMain : TFormMain;
SolutionEdits : Array[1..6] Of TEdit;
Const
ErrInfo : String = '发生错误!';
//一些字符集
Alpha : Set Of Char = ['a'..'z', 'A'..'Z'];
LowAlpha : Set Of Char = ['a'..'z'];
HighAlpha : Set Of Char = ['A'..'Z'];
NumberSet : Set Of Char = ['0'..'9', '.'];
Optor : Set Of Char = ['*', '/'];
Var
Elements : TStringList; //元素的名称列表
MOfElements : Array[1..88] Of Single; //元素的相对原子质量
AllElements : TStringList; // 为GetMassOfElement函数准备,被RebuildReactors调用时进行元素出现次数的统计
ReactorOrOutPut : ^TReactorOrOutPut;
Function GetMassOfElement(ElementName : String) : Single; //获取元素的相对原子质量; Mass:n.质量 ; Element:元素
Function GetMassOfFormula(Exp : String; WorkState : Byte = 1) : String; //计算任意化学式的式量,被RebuildReactors调用时进行元素出现次数的统计; Formula:式子
Function GetEquationResult(Equation : String) : Single; //包涵 +-*/()的一元一次方程求解器,未知数只能为一个字母
Procedure Simplify(Exp : String; Unknown : Char; Var Num1, Num2 : Single); //对所给的一元一次式子进行化简,将未知数系数存入Num1,将化简的常数存入Num2; Simplify:v.化简
Implementation
{$R *.dfm}
Procedure TFormMain.NumberOnlyEditKeyDown(Sender : TObject; Var Key : Word;
Shift : TShiftState);
Begin //溶液信息编辑框只可接收数字的实现
If Key In [48..57, 46, 13, 8, 189, 190] Then
TEdit(Sender).ReadOnly := False
Else
TEdit(Sender).ReadOnly := true;
End;
Procedure TFormMain.NumberOnlyEditEnter(Sender : TObject);
Begin
TEdit(Sender).ReadOnly := False;
End;
Procedure TFormMain.FormCreate(Sender : TObject);
Var
i : Integer;
Begin
EditFormulaShiftPress := False;
SolutionEdits[1] := NongDuA;
SolutionEdits[2] := NongDuB;
SolutionEdits[3] := NongDuMixed;
SolutionEdits[4] := MassA;
SolutionEdits[5] := MassB;
SolutionEdits[6] := MassMixed;
//设置溶液信息编辑框只可接收数字
For i := 1 To 6 Do
With SolutionEdits[i] Do Begin
OnKeyDown := NumberOnlyEditKeyDown;
OnEnter := NumberOnlyEditEnter;
End;
//化学式输入框只可输入大小写字母、数字、()
EditFormula.OnEnter := NumberOnlyEditEnter;
End;
Procedure TFormMain.BtnDeleteAll2Click(Sender : TObject);
Begin //全部清空溶液混合计算中的输入框
NongDuA.Text := '';
MassA.Text := '';
NongDuB.Text := '';
MassB.Text := '';
NongDuMixed.Text := '';
MassMixed.Text := '';
End;
Procedure TFormMain.BtnDeleteAll1Click(Sender : TObject);
Begin //全部清空方程式配平中的输入框
EditFormula.Lines.Clear;
EditReactor.Lines.Clear;
EditOut.Lines.Clear;
EditReactor.Clear;
Memo2.Clear;
Memo3.Clear;
Memo4.Clear;
Memo5.Clear;
BtnBalance.Enabled := true;
AddToReactor.Enabled := true;
DeleteIt1.Enabled := true;
AddToOut.Enabled := true;
DeleteIt2.Enabled := true;
End;
Procedure TFormMain.BtnDeleteClick(Sender : TObject);
Begin
EditFormula.Lines.Clear; //清空化学式输入框
End;
Procedure TFormMain.DeleteIt1Click(Sender : TObject);
Var
Edit : TRichEdit;
i : Integer;
Begin
Case (Sender As TComponent).tag Of //哪个Edit获得焦点
1 : Edit := EditReactor;
2 : Edit := EditOut;
End;
i := SendMessage(Edit.Handle, $0400 + 54, 0, Edit.SelStart); //用WinAPI函数获取行号
Edit.Lines.Delete(i); //删除所选行
End;
Procedure TFormMain.AddToReactorClick(Sender : TObject);
Var
Edit : TRichEdit;
Begin //拷贝化学式到反应物或生成物输入框
If EditFormula.Text = '' Then Exit;
EditFormula.SelectAll; //全选
EditFormula.CopyToClipboard; //拷入剪切板
Case (Sender As TComponent).tag Of //哪个Edit获得焦点
1 : Edit := EditReactor;
2 : Edit := EditOut;
End;
Edit.ReadOnly := False; //必需设为可写入才可粘贴
Edit.PasteFromClipboard; //粘贴自剪切板
Edit.ReadOnly := true;
End;
Procedure TFormMain.EditFormulaKeyPress(Sender : TObject; Var Key : Char);
Begin
EditFormulaWordKey := Integer(Key); //存储按下了哪个字母
End;
Procedure TFormMain.EditFormulaChange(Sender : TObject);
Begin
Label14.Caption := 'M=?';
If (EditFormulaShiftPress = False) And (EditFormulaWordKey In [48..57]) Then Begin //如果输入数字
EditFormula.SelStart := EditFormula.SelStart - 1;
EditFormula.SelLength := 1;
EditFormula.SelAttributes.Size := 9;
EditFormula.SelLength := 0;
EditFormula.SelStart := EditFormula.SelStart + 1;
//变数字为小字体,更好看一些
End;
EditFormulaShiftPress := False;
EditFormula.SelAttributes.Size := 12;
End;
Procedure TFormMain.EditFormulaKeyDown(Sender : TObject; Var Key : Word;
Shift : TShiftState);
Begin //化学式输入框只可输入大小写字母、数字、()
If Key In [48..57, 16, 65..90, 8, 46] Then Begin
If ssShift In Shift Then Begin //按住Shift,再按字母键或"9","0"键时输入大写字母或"()"
EditFormulaShiftPress := true;
If Key In [65..90, 48, 57] Then //48为"0"键的编号,57为"9"键的编号,65..90为字母键编号
EditFormula.ReadOnly := False //可接收此字符
Else
EditFormula.ReadOnly := true; //不可接收此字符
Exit;
End;
EditFormula.ReadOnly := False //可接收此字符
End Else
EditFormula.ReadOnly := true; //不可接收此字符
End;
Procedure TFormMain.TabSheet1Show(Sender : TObject);
Var
Sheet : TTabSheet;
Begin //方程式配平与相对原子质量计算 关于浓度的计算 共用一个化学式编辑器
Case (Sender As TComponent).tag Of
1 : Sheet := TabSheet1;
2 : Sheet := TabSheet3;
End;
EditFormula.Parent := Sheet; //将EditFormula移入指定Sheet
BtnDelete.Parent := Sheet; //将BtnDelete移入指定Sheet
End;
Procedure TFormMain.Button2Click(Sender : TObject);
Begin
Try
Label14.Caption := 'M=' + GetMassOfFormula(EditFormula.Text) //输出式量
Except
On E : Exception Do //发生错误,输入的化学式无法计算式量
MessageDlg(ErrInfo, mtError, [mbOK], 0);
End;
End;
Procedure TFormMain.BtnCalcClick(Sender : TObject);
Var
i, t : Integer;
RM : Single; //临时变量,存方程的解
Formula : String;
Begin
{
本过程利用方程方法求解
方程一:MassA.Text + MassB = MassMixed
方程二:MassA.Text * NongDuA + MassB * NongDuB = MassMixed * NongDuMixed
}
Try
t := 0;
For i := 4 To 6 Do
If SolutionEdits[i].Text = '' Then
t := i; //得到哪个质量输入框是空的
If t = 0 Then //哪个质量输入框是也不是空的.发生错误
Raise Exception.Create('');
SolutionEdits[t].Text := 'X*1';
Formula := MassA.Text + '+' + MassB.Text + '=' + MassMixed.Text; //生成方程
RM := GetEquationResult(Formula);
If RM < 0 Then Raise Exception.Create('');
SolutionEdits[t].Text := FloatToStr(RM); //输出解
t := 0;
For i := 1 To 3 Do
If SolutionEdits[i].Text = '' Then
t := i; //得到哪个浓度输入框是空的
If t = 0 Then //哪个浓度输入框是也不是空的.发生错误
Raise Exception.Create('');
SolutionEdits[t].Text := 'X*1';
Formula := NongDuA.Text + '*' + MassA.Text + '/100' + '+' + NongDuB.Text + '*' + MassB.Text +
'/100' + '=' + NongDuMixed.Text + '*' + MassMixed.Text + '/100'; //生成方程
RM := GetEquationResult(Formula); //求解
If RM < 0 Then Raise Exception.Create('');
SolutionEdits[t].Text := FormatFloat('0.00', RM); //格式化并输出解
Except //发生错误
On E : Exception Do Begin
MessageDlg(ErrInfo, mtError, [mbOK], 0);
For i := 1 To 6 Do
SolutionEdits[i].Text := '';
End;
End;
End;
Procedure TFormMain.BtnBalanceClick(Sender : TObject);
Var
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -