namespace MoleculeMass
{
partial class Form1
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.label1 = new System.Windows.Forms.Label();
this.textBoxEquation = new System.Windows.Forms.TextBox();
this.buttonCalculate = new System.Windows.Forms.Button();
this.textBoxResult = new System.Windows.Forms.TextBox();
this.SuspendLayout();
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(12, 14);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(52, 13);
this.label1.TabIndex = 0;
this.label1.Text = "Equation:";
//
// textBoxEquation
//
this.textBoxEquation.Location = new System.Drawing.Point(70, 11);
this.textBoxEquation.Name = "textBoxEquation";
this.textBoxEquation.Size = new System.Drawing.Size(321, 20);
this.textBoxEquation.TabIndex = 1;
//
// buttonCalculate
//
this.buttonCalculate.Location = new System.Drawing.Point(397, 9);
this.buttonCalculate.Name = "buttonCalculate";
this.buttonCalculate.Size = new System.Drawing.Size(75, 23);
this.buttonCalculate.TabIndex = 2;
this.buttonCalculate.Text = "Calculate";
this.buttonCalculate.UseVisualStyleBackColor = true;
this.buttonCalculate.Click += new System.EventHandler(this.buttonCalculate_Click);
//
// textBoxResult
//
this.textBoxResult.BackColor = System.Drawing.SystemColors.Window;
this.textBoxResult.Location = new System.Drawing.Point(12, 38);
this.textBoxResult.Multiline = true;
this.textBoxResult.Name = "textBoxResult";
this.textBoxResult.ReadOnly = true;
this.textBoxResult.Size = new System.Drawing.Size(460, 311);
this.textBoxResult.TabIndex = 3;
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(484, 361);
this.Controls.Add(this.textBoxResult);
this.Controls.Add(this.buttonCalculate);
this.Controls.Add(this.textBoxEquation);
this.Controls.Add(this.label1);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "Form1";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "Molecule Mass";
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Label label1;
private System.Windows.Forms.TextBox textBoxEquation;
private System.Windows.Forms.Button buttonCalculate;
private System.Windows.Forms.TextBox textBoxResult;
}
}
Token.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MoleculeMass
{
public class Token
{
public EnumTokenType TokenType { get; set; }
public string Value { get; set; }
public int Lenght { get; set; }
}
public enum EnumTokenType
{
Operator,
Element,
Number,
Error
}
}
Date :
2014-11-22 14:45:05
By :
ห้ามตอบเกินวันละ 2 กระทู้
No. 17
Guest
Form1.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace MoleculeMass
{
public partial class Form1 : Form
{
private DataTable atomicData;
public Form1()
{
InitializeComponent();
this.atomicData = this.AtomicData();
}
private void buttonCalculate_Click(object sender, EventArgs e)
{
double startCounter = DateTime.Now.TimeOfDay.TotalSeconds;
this.textBoxResult.Text = string.Empty;
string rawInfix = Regex.Replace(this.textBoxEquation.Text.Replace(" ", string.Empty), "[•\\.]|\\)\\(", "+").Trim(("()").ToCharArray());
if (this.IsValid(rawInfix))
{
string preInfix = this.PreInifx(rawInfix);
string infix = this.ToInfix(preInfix);
string assign = this.AssignValue(infix);
double answer = this.Calculate(infix);
if (answer >= 0)
{
this.textBoxResult.Text += "= " + rawInfix + Environment.NewLine;
this.textBoxResult.Text += "= " + preInfix + Environment.NewLine;
this.textBoxResult.Text += "= " + infix + Environment.NewLine;
this.textBoxResult.Text += "= " + assign + Environment.NewLine;
this.textBoxResult.Text += "= " + answer.ToString("#,##0.0") + Environment.NewLine;
this.textBoxResult.Text += Environment.NewLine;
this.textBoxResult.Text += string.Format("Total time: {0} seconds", (DateTime.Now.TimeOfDay.TotalSeconds - startCounter).ToString("#,##0.0###"));
}
else
{
this.textBoxResult.Text = "*** ERROR ***";
}
}
}
private double Calculate(string infix)
{
double result = 0.0;
try
{
foreach (string element in infix.Split('+'))
{
double mass = atomicData.AsEnumerable().Where(a => a.Field<string>("Symbol") == Regex.Match(element, "[a-zA-Z]{1,}").Value).Select(a => a.Field<double>("AtomicMass")).First();
double amount = double.Parse(Regex.Match(element, "[0-9]{1,}").Value);
result += mass * amount;
}
}
catch (Exception)
{
return -1;
}
return result;
}
private string AssignValue(string infix)
{
List<Token> tokens = new List<Token>();
while (infix.Length > 0)
{
Token token = this.GetToken(infix);
tokens.Add(token);
infix = infix.Substring(token.Lenght);
}
string result = string.Empty;
foreach (Token token in tokens)
{
if (token.TokenType == EnumTokenType.Element)
{
double mass = atomicData.AsEnumerable().Where(a => a.Field<string>("Symbol") == token.Value).Select(a => a.Field<double>("AtomicMass")).First();
result += string.Format("*{0}", mass.ToString("#,##0.0"));
}
else
{
result += token.Value;
}
}
return string.Join(")+(", ("(" + result + ")").Split('+'));
}
private string ToInfix(string str)
{
string result = str;
foreach (Match match in Regex.Matches(str, "[0-9]{1,}\\*\\([a-zA-Z0-9\\+]*\\)|\\([a-zA-Z0-9\\+]*\\)\\*[0-9]{1,}"))
{
result = result.Replace(match.Value, this.DoMultiply(match.Value));
}
return result;
}
private string DoMultiply(string str)
{
int multiply = int.Parse(Regex.Match(str, "^[0-9]{1,}").Value.Replace("*", string.Empty));
string elements = Regex.Match(str, "\\([a-zA-Z0-9\\+]{1,}\\)").Value.Trim(("()").ToCharArray());
List<Token> tokens = new List<Token>();
while (elements.Length > 0)
{
Token token = this.GetToken(elements);
tokens.Add(token);
elements = elements.Substring(token.Lenght);
}
foreach (Token token in tokens)
{
if (token.TokenType == EnumTokenType.Number)
{
int newValue = int.Parse(token.Value) * multiply;
token.Value = newValue.ToString();
}
}
return this.TokenToString(tokens);
}
private List<Token> AddOne(List<Token> tokens)
{
List<Token> result = new List<Token>();
Token Previous = null;
foreach (Token token in tokens)
{
if (Previous != null)
{
if (Previous.TokenType == EnumTokenType.Element && token.TokenType != EnumTokenType.Number)
{
result.Add(new Token() { Value = "1", TokenType = EnumTokenType.Number, Lenght = 1 });
}
}
result.Add(token);
Previous = token;
}
if (result.Last().TokenType == EnumTokenType.Element)
{
result.Add(new Token() { Value = "1", TokenType = EnumTokenType.Number, Lenght = 1 });
}
return result;
}
private string PreInifx(string str)
{
List<string> result = new List<string>();
foreach (string s in str.Split('+'))
{
result.Add(this.ConvertToInfix(s.Trim(("()").ToCharArray())));
}
return string.Join("+", result.ToArray());
}
private string ConvertToInfix(string str)
{
List<Token> tokens = new List<Token>();
while (str.Length > 0)
{
Token token = this.GetToken(str);
tokens.Add(token);
str = str.Substring(token.Lenght);
}
List<Token> result = new List<Token>();
Token previous = null;
if (tokens.Count > 0)
{
if (tokens.First().TokenType == EnumTokenType.Number)
{
tokens.Insert(1, new Token() { Value = "(", TokenType = EnumTokenType.Operator, Lenght = 1 });
tokens.Add(new Token() { Value = ")", TokenType = EnumTokenType.Operator, Lenght = 1 });
}
foreach (Token token in tokens)
{
if (result.Count == 0)
{
result.Add(token);
previous = token;
}
else
{
switch (previous.TokenType)
{
case EnumTokenType.Element:
switch (token.TokenType)
{
case EnumTokenType.Element:
result.Add(new Token() { Value = "+", TokenType = EnumTokenType.Operator, Lenght = 1 });
result.Add(token);
previous = token;
break;
case EnumTokenType.Number:
result.Add(token);
previous = token;
break;
case EnumTokenType.Operator:
if (token.Value == "(")
result.Add(new Token() { Value = "+", TokenType = EnumTokenType.Operator, Lenght = 1 });
result.Add(token);
previous = token;
break;
}
break;
case EnumTokenType.Number:
switch (token.TokenType)
{
case EnumTokenType.Element:
result.Add(new Token() { Value = "+", TokenType = EnumTokenType.Operator, Lenght = 1 });
result.Add(token);
previous = token;
break;
case EnumTokenType.Number:
break;
case EnumTokenType.Operator:
if (token.Value != ")" && tokens.First().TokenType == EnumTokenType.Number)
result.Add(new Token() { Value = "*", TokenType = EnumTokenType.Operator, Lenght = 1 });
else if (token.Value != ")")
result.Add(new Token() { Value = "+", TokenType = EnumTokenType.Operator, Lenght = 1 });
result.Add(token);
previous = token;
break;
}
break;
case EnumTokenType.Operator:
switch (token.TokenType)
{
case EnumTokenType.Element:
result.Add(token);
previous = token;
break;
case EnumTokenType.Number:
if (token.Value != ")")
result.Add(new Token() { Value = "*", TokenType = EnumTokenType.Operator, Lenght = 1 });
result.Add(token);
previous = token;
break;
case EnumTokenType.Operator:
break;
}
break;
}
}
}
}
return this.Swap(this.TokenToString(this.AddOne(result)));
}
private string Swap(string str)
{
string result = str;
foreach (Match match in Regex.Matches(str, "\\([a-zA-Z0-9\\+]*\\)\\*[0-9]{1,}"))
{
string[] temp = match.Value.Split('*');
result = result.Replace(match.Value, temp[1] + "*" + temp[0]);
}
foreach (Match match in Regex.Matches(result, "[a-zA-Z]{1,}[0-9]{1,}"))
{
string element = Regex.Match(match.Value, "[a-zA-Z]{1,}").Value;
string amount = Regex.Match(match.Value, "[0-9]{1,}").Value;
result = result.Replace(match.Value, amount + element);
}
return result;
}
private bool IsValid(string str)
{
List<Token> tokens = new List<Token>();
while (str.Length > 0)
{
Token token = this.GetToken(str);
tokens.Add(token);
str = str.Substring(token.Lenght);
}
Token errorToken = tokens.Where(t => t.TokenType == EnumTokenType.Error).FirstOrDefault();
if (errorToken != null)
this.textBoxResult.Text = errorToken.Value;
return (errorToken == null) ? true : false;
}
private Token GetToken(string str)
{
Token token = new Token();
string first = str.Substring(0, 1);
switch (this.TokenType(first))
{
case EnumTokenType.Element:
Match match1 = Regex.Match(str, "^[A-Z][a-z]*");
if (this.IsElement(match1.Value))
{
token.Value = match1.Value;
token.TokenType = EnumTokenType.Element;
token.Lenght = match1.Value.Length;
}
else
{
token.Value = string.Format("Error: unknown '{0}'", match1.Value);
token.TokenType = EnumTokenType.Error;
token.Lenght = match1.Value.Length;
}
break;
case EnumTokenType.Number:
Match match2 = Regex.Match(str, "^[0-9]*");
token.Value = match2.Value;
token.TokenType = EnumTokenType.Number;
token.Lenght = match2.Value.Length;
break;
case EnumTokenType.Operator:
token.Value = first;
token.TokenType = EnumTokenType.Operator;
token.Lenght = 1;
break;
default:
token.Value = string.Format("Error: unknown '{0}'", first);
token.TokenType = EnumTokenType.Error;
token.Lenght = 1;
break;
}
return token;
}
private bool IsElement(string element)
{
return atomicData.AsEnumerable().Where(a => a.Field<string>("Symbol") == element).Count() > 0 ? true : false;
}
private EnumTokenType TokenType(string str)
{
EnumTokenType result;
if ((new string[] { "+", "(", ")" }).Contains(str))
{
result = EnumTokenType.Operator;
}
else if ((new Regex("[0-9]")).Match(str).Success)
{
result = EnumTokenType.Number;
}
else if ((new Regex("[A-Z]")).Match(str).Success)
{
result = EnumTokenType.Element;
}
else
{
result = EnumTokenType.Error;
}
return result;
}
private string TokenToString(List<Token> tokens)
{
string result = string.Empty;
foreach (Token token in tokens)
{
result += token.Value;
}
return result;
}
private DataTable AtomicData()
{
object[][] data = new object[][]
{
new object[] { "H", "Hydrogen", 1.0079, 1 },
new object[] { "He", "Helium", 4.0026, 2 },
new object[] { "Li", "Lithium", 6.941, 3 },
new object[] { "Be", "Beryllium", 9.0122, 4 },
new object[] { "B", "Boron", 10.811, 5 },
new object[] { "C", "Carbon", 12.0107, 6 },
new object[] { "N", "Nitrogen", 14.0067, 7 },
new object[] { "O", "Oxygen", 15.9994, 8 },
new object[] { "F", "Fluorine", 18.9984, 9 },
new object[] { "Ne", "Neon", 20.1797, 10 },
new object[] { "Na", "Sodium", 22.9897, 11 },
new object[] { "Mg", "Magnesium", 24.305, 12 },
new object[] { "Al", "Aluminum", 26.9815, 13 },
new object[] { "Si", "Silicon", 28.0855, 14 },
new object[] { "P", "Phosphorus", 30.9738, 15 },
new object[] { "S", "Sulfur", 32.065, 16 },
new object[] { "Cl", "Chlorine", 35.453, 17 },
new object[] { "K", "Potassium", 39.0983, 19 },
new object[] { "Ar", "Argon", 39.948, 18 },
new object[] { "Ca", "Calcium", 40.078, 20 },
new object[] { "Sc", "Scandium", 44.9559, 21 },
new object[] { "Ti", "Titanium", 47.867, 22 },
new object[] { "V", "Vanadium", 50.9415, 23 },
new object[] { "Cr", "Chromium", 51.9961, 24 },
new object[] { "Mn", "Manganese", 54.938, 25 },
new object[] { "Fe", "Iron", 55.845, 26 },
new object[] { "Ni", "Nickel", 58.6934, 28 },
new object[] { "Co", "Cobalt", 58.9332, 27 },
new object[] { "Cu", "Copper", 63.546, 29 },
new object[] { "Zn", "Zinc", 65.39, 30 },
new object[] { "Ga", "Gallium", 69.723, 31 },
new object[] { "Ge", "Germanium", 72.64, 32 },
new object[] { "As", "Arsenic", 74.9216, 33 },
new object[] { "Se", "Selenium", 78.96, 34 },
new object[] { "Br", "Bromine", 79.904, 35 },
new object[] { "Kr", "Krypton", 83.8, 36 },
new object[] { "Rb", "Rubidium", 85.4678, 37 },
new object[] { "Sr", "Strontium", 87.62, 38 },
new object[] { "Y", "Yttrium", 88.9059, 39 },
new object[] { "Zr", "Zirconium", 91.224, 40 },
new object[] { "Nb", "Niobium", 92.9064, 41 },
new object[] { "Mo", "Molybdenum", 95.94, 42 },
new object[] { "Tc", "Technetium", 98.0, 43 },
new object[] { "Ru", "Ruthenium", 101.07, 44 },
new object[] { "Rh", "Rhodium", 102.9055, 45 },
new object[] { "Pd", "Palladium", 106.42, 46 },
new object[] { "Ag", "Silver", 107.8682, 47 },
new object[] { "Cd", "Cadmium", 112.411, 48 },
new object[] { "In", "Indium", 114.818, 49 },
new object[] { "Sn", "Tin", 118.71, 50 },
new object[] { "Sb", "Antimony", 121.76, 51 },
new object[] { "I", "Iodine", 126.9045, 53 },
new object[] { "Te", "Tellurium", 127.6, 52 },
new object[] { "Xe", "Xenon", 131.293, 54 },
new object[] { "Cs", "Cesium", 132.9055, 55 },
new object[] { "Ba", "Barium", 137.327, 56 },
new object[] { "La", "Lanthanum", 138.9055, 57 },
new object[] { "Ce", "Cerium", 140.116, 58 },
new object[] { "Pr", "Praseodymium", 140.9077, 59 },
new object[] { "Nd", "Neodymium", 144.24, 60 },
new object[] { "Pm", "Promethium", 145.0, 61 },
new object[] { "Sm", "Samarium", 150.36, 62 },
new object[] { "Eu", "Europium", 151.964, 63 },
new object[] { "Gd", "Gadolinium", 157.25, 64 },
new object[] { "Tb", "Terbium", 158.9253, 65 },
new object[] { "Dy", "Dysprosium", 162.5, 66 },
new object[] { "Ho", "Holmium", 164.9303, 67 },
new object[] { "Er", "Erbium", 167.259, 68 },
new object[] { "Tm", "Thulium", 168.9342, 69 },
new object[] { "Yb", "Ytterbium", 173.04, 70 },
new object[] { "Lu", "Lutetium", 174.967, 71 },
new object[] { "Hf", "Hafnium", 178.49, 72 },
new object[] { "Ta", "Tantalum", 180.9479, 73 },
new object[] { "W", "Tungsten", 183.84, 74 },
new object[] { "Re", "Rhenium", 186.207, 75 },
new object[] { "Os", "Osmium", 190.23, 76 },
new object[] { "Ir", "Iridium", 192.217, 77 },
new object[] { "Pt", "Platinum", 195.078, 78 },
new object[] { "Au", "Gold", 196.9665, 79 },
new object[] { "Hg", "Mercury", 200.59, 80 },
new object[] { "Tl", "Thallium", 204.3833, 81 },
new object[] { "Pb", "Lead", 207.2, 82 },
new object[] { "Bi", "Bismuth", 208.9804, 83 },
new object[] { "Po", "Polonium", 209.0, 84 },
new object[] { "At", "Astatine", 210.0, 85 },
new object[] { "Rn", "Radon", 222.0, 86 },
new object[] { "Fr", "Francium", 223.0, 87 },
new object[] { "Ra", "Radium", 226.0, 88 },
new object[] { "Ac", "Actinium", 227.0, 89 },
new object[] { "Pa", "Protactinium", 231.0359, 91 },
new object[] { "Th", "Thorium", 232.0381, 90 },
new object[] { "Np", "Neptunium", 237.0, 93 },
new object[] { "U", "Uranium", 238.0289, 92 },
new object[] { "Am", "Americium", 243.0, 95 },
new object[] { "Pu", "Plutonium", 244.0, 94 },
new object[] { "Cm", "Curium", 247.0, 96 },
new object[] { "Bk", "Berkelium", 247.0, 97 },
new object[] { "Cf", "Californium", 251.0, 98 },
new object[] { "Es", "Einsteinium", 252.0, 99 },
new object[] { "Fm", "Fermium", 257.0, 100 },
new object[] { "Md", "Mendelevium", 258.0, 101 },
new object[] { "No", "Nobelium", 259.0, 102 },
new object[] { "Rf", "Rutherfordium", 261.0, 104 },
new object[] { "Lr", "Lawrencium", 262.0, 103 },
new object[] { "Db", "Dubnium", 262.0, 105 },
new object[] { "Bh", "Bohrium", 264.0, 107 },
new object[] { "Sg", "Seaborgium", 266.0, 106 },
new object[] { "Mt", "Meitnerium", 268.0, 109 },
new object[] { "Rg", "Roentgenium", 272.0, 111 },
new object[] { "Hs", "Hassium", 277.0, 108 }
//new object[] { "Ds", "Darmstadtium", null, 110 },
//new object[] { "Uub", "Ununbium", null, 112 },
//new object[] { "Uut", "Ununtrium", null, 113 },
//new object[] { "Uuq", "Ununquadium", null, 114 },
//new object[] { "Uup", "Ununpentium", null, 115 },
//new object[] { "Uuh", "Ununhexium", null, 116 },
//new object[] { "Uus", "Ununseptium", null, 117 },
//new object[] { "Uuo", "Ununoctium", null, 118 }
};
DataTable dt = new DataTable();
dt.Columns.Add(new DataColumn("Symbol", typeof(string)));
dt.Columns.Add(new DataColumn("ElementName", typeof(string)));
dt.Columns.Add(new DataColumn("AtomicMass", typeof(double)));
dt.Columns.Add(new DataColumn("AtomicNumber", typeof(int)));
foreach (object[] obj in data)
{
DataRow dr = dt.NewRow();
dr.SetField<string>("Symbol", (string)obj[0]);
dr.SetField<string>("ElementName", (string)obj[1]);
dr.SetField<double>("AtomicMass", (double)obj[2]);
dr.SetField<int>("AtomicNumber", (int)obj[3]);
dt.Rows.Add(dr);
}
return dt;
}
}
}