Текст программы с комментариями
Класс Рациональных чисел.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace WindowsFormsApplication1
{
class ratcion
{
int chislit, znamenat;
#region Доп_методы
int NOD(int a, int b) // Наименьший общий делитель (Нужен для сокращения)
{
return b != 0 ? NOD(b, a % b) : a;
}
void sokr() // Сокращение
{
int a = NOD(Math.Abs(this.chislit), Math.Abs(this.znamenat));
if (a > 1) { this.chislit /= a; this.znamenat /= a; }
}
void test()
{}
#endregion
#region Свойства_конструкторы
public int Chislit // Свойства числителя
{
get { return chislit; }
set { chislit = value; }
}
public int Znamenat // Свойства Знаменателя
{
get { return znamenat; }
set
{
while (value == 0)
{
Console.WriteLine("Введите знаметаль ещё раз");
value = int.Parse(Console.ReadLine());
}
znamenat = value;
}
}
public ratcion() // Конструктор без параметров
{
chislit = 0;
znamenat = 1;
}
public ratcion(int chislit) // Конструктор с параметром числителя
{
this.chislit = chislit;
this.znamenat = 1;
}
public ratcion(int chislit, int znamenat) //Сложный конструктор для числителя и знаменателя
{
this.chislit = chislit;
this.znamenat = znamenat;
this.test();
}
public ratcion(ratcion a) // Конструктор присваивания
{
this.chislit = a.chislit;
this.znamenat = a.znamenat;
}
#endregion
public override string ToString() //Переопределения метода ToString для преобразования в строку
{
string s = "";
if (this.chislit * this.znamenat < 0) s = "-"; // Условие для вывода "-"
if (Math.Abs(chislit) < Math.Abs(znamenat))
{
s += Math.Abs(chislit) + "/" + Math.Abs(znamenat); // Вывод при Числитель>Знаменатель
return s;
}
else
{
int a = Math.Abs(this.chislit) / Math.Abs(this.znamenat); // Вывод при Числитель<Знаменатель
int b = Math.Abs(this.chislit) % Math.Abs(this.znamenat);
s += a + " (" + b + "/" + Math.Abs(znamenat) + ")";
return s;
}
}
#region Арифметика
public static ratcion operator *(ratcion a, ratcion b) // Переопределение Арифметических операций
{
ratcion c = new ratcion();
c.chislit = a.chislit * b.chislit;
c.znamenat = a.znamenat * b.znamenat;
c.sokr();
return c;
}
public static ratcion operator /(ratcion a, ratcion b)
{
ratcion c = new ratcion();
if (b.chislit == 0) { Console.WriteLine("Деление на 0"); return c; }
else
{
c.chislit = a.chislit * b.znamenat;
c.znamenat = a.znamenat * b.chislit;
c.sokr();
return c;
}
}
public static ratcion operator +(ratcion a, ratcion b)
{
ratcion c = new ratcion();
c.znamenat = a.znamenat * b.znamenat;
c.chislit = a.chislit * b.znamenat + b.chislit * a.znamenat;
c.sokr();
return c;
}
public static ratcion operator -(ratcion a, ratcion b)
{
ratcion c = new ratcion();
c.znamenat = a.znamenat * b.znamenat;
c.chislit = a.chislit * b.znamenat - b.chislit * a.znamenat;
c.sokr();
return c;
}
public static ratcion operator *(ratcion a, int b)
{
ratcion c = new ratcion();
c.chislit = a.chislit * b;
c.znamenat = a.znamenat;
return c;
}
public static ratcion operator *(int b, ratcion a)
{
ratcion c = new ratcion();
c.chislit = a.chislit * b;
c.znamenat = a.znamenat;
return c;
}
#endregion
}
}
Класс Form1 с методами Полиза.
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button2_Click(object sender, EventArgs e) // Определение кнопки Выход
{
Application.Exit();
}
static public int prior(char a) // Функция возвращения приоритета
{
switch (a)
{
case '+': return 1;
case '-': return 1;
case '*': return 2;
case '/': return 2;
case '^': return 3;
case '(': return -4;
case ')': return 0;
default: return 0;
}
}
static public object[] vihod(string s) //Метод для создания полиза
{
int j = 0;
object[] Vihod = new object[s.Length];
Stack a = new Stack(s.Length); // Инициализация стека
for (int i = 0; i < s.Length; i++)
{
if (Char.IsLetter(s[i])) // Проверка на Переменные
{
Vihod[j] = s[i];
j++;
}
else
if (Char.IsDigit(s[i])) //Проверка на целые числа
{
int k = i;
string s1 = "";
do
{
s1 += s[k];
k++;
i++;
}
while (k < s.Length && Char.IsDigit(s[k])); //соединение нескольких цифр в одно число
Vihod[j] = int.Parse(s1);
j++;
i--;
}
else
{
if (a.Count == 0 || prior((char)a.Peek()) < Math.Abs(prior(s[i]))) a.Push(s[i]); //добавление в стек на основе приоритета
else
{
if (s[i] == ')')
{
while (a.Count > 0 && prior((char)a.Peek()) >= prior(s[i])) // Добавление в Полиз выражения в скобках
{
Vihod[j] = a.Pop();
j++;
}
a.Pop();
}
else
{
while (a.Count > 0 && prior((char)a.Peek()) >= prior(s[i])) // Добавление в полиз операции и большим приоритетом
{
Vihod[j] = a.Pop();
j++;
}
a.Push(s[i]);
}
}
}
}
while (a.Count > 0) // Добавление в полиз остатка стека
{
Vihod[j] = a.Pop();
j++;
}
return Vihod;
}
public void Resh() // Метод решения по полизу
{
object[] s = vihod(textBox1.Text);
foreach (object x in s) textBox2.AppendText(x + " "); // вывод полиза
int l = 0;
try
{
while (l < s.Length && s[l].GetType().Name != "") l++; // Определение количества задействованных ячеек в массиве
}
catch { }
object[] a = new object[l]; // Создание массива объектов для хранения операций, операндов и констант.
for (int i = 0, j = 0; i < l; i++, j++)
{
if (Char.IsLetter(s[i].ToString(), 0)) // Проверка на переменную
{
ratcion z = new ratcion();
using (Form2 h = new Form2())
{
h.Text = "Ввод переменной " + s[i].ToString();
h.ShowDialog();
if (h.DialogResult == DialogResult.OK) // Вспомогательная форма для заполнения переменной
{
try
{
z.Chislit = int.Parse(h.textBox1.Text);
z.Znamenat = int.Parse(h.textBox2.Text);
}
catch {}
}
}
textBox4.AppendText(s[i].ToString() + " = " + z.ToString() + "\n");
a[j] = z;
for (int k = i+1; k < l; k++) if (s[k].GetType().Name=="Char"&&(char)s[k] == (char)s[i]) s[k] = a[j]; // замена всех одинаковых переменных в строке
}
else
if (s[i].GetType().Name == "Int32") //Превращение констант int в объект класса ratcion
{
ratcion z = new ratcion((int)s[i]);
a[j] = z;
}
else a[j] = s[i];
}
for (int i = 0; i < l; i++)
{
if (a[i].GetType().Name == "Char") // выполнение операций
switch (Convert.ToChar(a[i]))
{
case '+': a[i - 2] = (ratcion)a[i - 2] + (ratcion)a[i - 1]; i -= 2; for (int n = i + 1; n < l - 2; n++) a[n] = a[n + 2]; l -= 2; break;
case '-': a[i - 2] = (ratcion)a[i - 2] - (ratcion)a[i - 1]; i -= 2; for (int n = i + 1; n < l - 2; n++) a[n] = a[n + 2]; l -= 2; break;
case '*': a[i - 2] = (ratcion)a[i - 2] * (ratcion)a[i - 1]; i -= 2; for (int n = i + 1; n < l - 2; n++) a[n] = a[n + 2]; l -= 2; break;
case '/': a[i - 2] = (ratcion)a[i - 2] / (ratcion)a[i - 1]; i -= 2; for (int n = i + 1; n < l - 2; n++) a[n] = a[n + 2]; l -= 2; break;
}
}
textBox3.AppendText(a[0].ToString()); //Возвращение результата
}
private void button1_Click(object sender, EventArgs e) //Событие клика по кнопке "Решить"
{
try
{
textBox2.Clear(); // Очистка полей
textBox3.Clear();
textBox4.Clear();
Resh();
}
catch { MessageBox.Show("Введите выражение"); } // Искличительная ситуация когда вырожение пустое.
}
private void textBox1_KeyPress(object sender, KeyPressEventArgs e) // Запрет на ввод пробела в полизе
{
if (e.KeyChar == ' ') e.KeyChar = '\0';
}
}
}
Form2 Вспомогательная
namespace WindowsFormsApplication1
{
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
private void Form2_Load(object sender, EventArgs e)
{
}
void test() // Вывод сообщения об ошибке
{
MessageBox.Show("Введите знаменатель ещё раз");
textBox2.Clear();
}
private void textBox2_KeyPress(object sender, KeyPressEventArgs e) //Собитие запрета нажатия "0"
{
if (textBox2.Text.Length == 0 && e.KeyChar == '0')
{
test();
e.KeyChar = '\0';
}
}
}
}