public IEnumerator <T> GetEnumerator() { IValuesAndLink <T> value = _count > 0 ? _arr[_firstIndex] : null; while (value != null) { yield return(value.Value); value = value.Next; } ; }
public bool Remove(IValuesAndLink <T> elementNode) { var flag = false; var variable = _arr[_firstIndex]; while (variable._enable) { if (variable.Equals(elementNode)) { Removing(variable._index); flag = true; break; } variable = variable.Next; } return(flag); }
//далее исполнены все стандартные методы, необходимые для выполнения идеологии листа public void AddAfter(IValuesAndLink <T> elementNode, T elenet) { Count++; var newIndex = _arr[_lastIndex]._nextIndex; var node = (ValuesAndLink)elementNode; Removing(_arr[_lastIndex]._nextIndex); if (node._index == _lastIndex) { _lastIndex = newIndex; } Count++; _arr[newIndex].Value = elenet; _arr[newIndex]._enable = true; _arr[newIndex]._nextIndex = node._nextIndex; node._nextIndex = newIndex; _arr[newIndex]._previousIndex = node._index; }
//тут определяем знак и его приоритет private char FindOperand(ref IValuesAndLink <char> charter, out int intPreor) { if (charter == null) { intPreor = 0; return(default(char)); } switch (charter.Value) { case '+': case '-': charter = charter.Next ?? throw new Exception("Отсутствует слагаемое в конце"); intPreor = 0; return(charter.Previous.Value); case '*': case '/': charter = charter.Next ?? throw new Exception("Отсутствует множитель в конце"); intPreor = 1; return(charter.Previous.Value); case '^': charter = charter.Next ?? throw new Exception("Отсутствует показатель в конце"); intPreor = 2; return(charter.Previous.Value); case ')': if (_braketsNumber == 0) { throw new Exception("Лишня скобка"); } _braketsNumber--; var temp = charter.Value; charter = charter.Next; intPreor = -1; return(temp); default: intPreor = 1; return('*'); } }
//определение функции private void FindFunc(ref IValuesAndLink <char> nodeValue, out FuncEnum funcValue) { funcValue = FuncEnum.Nun; var strFunc = ""; while (nodeValue != null && !NumbersPredicate(nodeValue.Value) && nodeValue.Value != UnoMinus && nodeValue.Value != OpenBracket && nodeValue.Value != CharVariable) { strFunc += nodeValue.Value; nodeValue = nodeValue.Next; } switch (strFunc) { case "sin": { funcValue = FuncEnum.Sin; break; } case "cos": { funcValue = FuncEnum.Cos; break; } case "log": { funcValue = FuncEnum.Log; break; } default: { if (strFunc.Length > 0) { throw new Exception("Введён неверный оператор"); } break; } } }
//определение значения, вычисление унарных минусов как перед, так и внутри функции, всё здесь private IOperand FindValue(ref IValuesAndLink <char> charter) { if (charter == null) { return(null); } //if(charter == null) throw new Exception("Закрывайте скобки"); var blUno1 = false; var blUno2 = false; IOperand aValue; var strNumbs = ""; //унарный минус перед функцией if (charter.Value == UnoMinus) { blUno1 = true; charter = charter.Next; } //определяем наличие функции FindFunc(ref charter, out FuncEnum funcValue); if (charter.Value == OpenBracket) { //рекурсия для скобок charter = charter.Next; _braketsNumber++; aValue = StrResult(false, ref charter, out char tempOper, out int tempPreor); } else { //унарный минус внутри функции if (charter.Value == UnoMinus) { blUno2 = true; charter = charter.Next; } //само число while (charter != null && NumbersPredicate(charter.Value)) { strNumbs += charter.Value; charter = charter.Next; } //x с числом if (charter?.Value == CharVariable) { aValue = strNumbs == "" ? (IOperand) new Variable() : new Umn(new Const(Double.Parse(strNumbs.Replace('.', ','))), new Variable()); charter = charter.Next; } //x без числа else { if (strNumbs == "") { throw new Exception("не указан аргумент функции"); } aValue = new Const(strNumbs == "" ? 1 : Double.Parse(strNumbs.Replace('.', ','))); } //вычисление внутреннего унарного минуса if (blUno2) { aValue = UnoOperand(aValue, FuncEnum.Min); } } //подсчёт функции aValue = UnoOperand(aValue, funcValue); //подсчёт унарного минуса перед функцией if (blUno1) { aValue = UnoOperand(aValue, FuncEnum.Min); } return(aValue); }
/// <summary> /// вычисляет результат операций внутри скобки /// </summary> /// <param name="preOperand">наличие знака перед последовательностью опарандов высшего порядка</param> /// <param name="sValue">каретка</param> /// <param name="lastOperand">тип операнда после скобки</param> /// <param name="lastOperandPreor">и его преоритет</param> /// <returns></returns> private IOperand StrResult(bool preOperand, ref IValuesAndLink <char> sValue, out char lastOperand, out int lastOperandPreor) { if (sValue == null) { lastOperand = default(char); lastOperandPreor = -1; return(null); } //определяем первое число. Тут же вычисляются все унарные опреаторы. var a = FindValue(ref sValue); //знак var operand = FindOperand(ref sValue, out int operandPreor); //если скобка закрывается или последовательность операндов высшего приоритета завершена, то возвращаемся по дереву if (operand == CloseBracket || preOperand && operandPreor < 2) { lastOperand = operand; lastOperandPreor = operandPreor; return(a); } do { //сложение вычисляем в самом конце. if (operandPreor == 0) { var m = StrResult(true, ref sValue, out lastOperand, out lastOperandPreor); if (m == null && operand == default(char)) { return(a); } var p = DuoOperand(a, m, operand); return(p); } var b = FindValue(ref sValue); var nextOperand = FindOperand(ref sValue, out int nextOperandPreor); //сравниваем приоритеты if (operandPreor >= nextOperandPreor) { if (b == null && operand == default(char)) { break; } a = DuoOperand(a, b, operand); operand = nextOperand; operandPreor = nextOperandPreor; } else { //если приоритет меньше, то перед нами последовательность операндов высшего приоритетов (возведение в степень) a = DuoOperand(a, DuoOperand(b, StrResult(true, ref sValue, out char tempOperand, out operandPreor), nextOperand), operand); operand = tempOperand; } } while (operand != CloseBracket && sValue != null); lastOperand = default(char); lastOperandPreor = -1; return(a); }