Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- scanf("%s",string[80]);
- scanf("%fx^2+%fx+%f=0", &a, &b, &c);
- #include <stdio.h>
- enum States
- {
- // Конечные состояния
- Result_Success, // Успешное завершение
- Result_CoefficientCantBeStored, // Ошибка: массив outCoeffs слишком мал
- Result_UnexpectedSymbolInCoeff, // Ошибка: неожиданный символ в коэффициенте
- Result_UnexpectedEndOfPower, // Ошибка: После знака степени нет самой степени
- Result_UnexpectedEndOfRightSide,// Ошибка: не указана правая часть уравнения
- // Промежуточные состояния
- State_AtCoeffStart, // Первый символ коэффициента (+/-/цифра)
- State_AtCoeff, // Дальнейшие цифры коэффициента
- State_AtX, // Буква "икс"
- State_AtPowerCoeffStart, // Первый символ показателя степени члена
- State_AtPowerCoeff, // Показатель степени члена
- State_AtRightSideStart, // Первый символ справа от знака равенства
- State_AtRightSide, // Дальнейшие цифры справа от знака равенства
- // Первое неконечное состояние (используется при проверке на необходимость выхода)
- FirstInternalState = State_AtCoeffStart
- };
- /**
- * Функция разбора строки с линейным уравнением и вычленения из неё коэффициентов.
- *
- * Переметры:
- *
- * in
- * дескриптов входного символьного потока.
- *
- * outCoeffs
- * указатель на массив, который будет принимать коэффициенты, считанные
- * из уравнения. Коэффициент для N-й степени идёт в outCoeffs[N].
- * Если определённый коэффициент не указан в уравнении, то в соответствующий
- * элемент массива будет записан положительный ноль.
- *
- * coeffsCount
- * Количество элементов в массиве outCoeffs. Если очередная степень приводит
- * к записи за пределами outCoeffs, функция возвращает
- * Result_CoefficientCantBeStored.
- *
- * Возвращаемое значение:
- *
- * Константа из семейства States::Result_*. При возникновении ошибки происходит
- * возврат кода, отличного от Result_Success; массив outCoeffs при этом содержит
- * те коэффициенты, которые были успешно считаны целиком до возникновения ошибки.
- */
- enum States parse(FILE* in, double* outCoeffs, size_t coeffsCount)
- {
- // Зануляем все указанные коэффициенты, вдруг не все из них будут указаны в уравнении
- for(size_t i = 0; i < coeffsCount; ++i)
- outCoeffs[i] = 0.0;
- enum States state = State_AtCoeffStart;
- size_t currentPowCoefficient = 0;
- bool isPositiveCoeff;
- double numBuffer = 0.0;
- bool metDecimalDot = false;
- size_t denomPower = 0;
- // Так как нам может потребоваться попридержать текущий символ до следующего
- // состояния, введём для него промежуточный буфер
- char ch = fgetc(in->stream);
- while(state >= FirstInternalState)
- {
- // Считываем очередной символ и решаем, что с ним делать (решение принимаем
- // с помощью простенького конечного автомата).
- //
- // Да простят меня нелюбители switch-bases FSM, но пробрасывать
- // во вспомогательные функции все параметры и переменные — для учебного
- // примера это, пожалуй, перебор.
- switch(state)
- {
- case State_AtCoeffStart:
- // Сюда мы можем выйти при завершении предыдущего члена.
- // Поэтому именно здесь мы выдаём готовый коэффициент.
- if(coeffsCount > currentPowCoefficient)
- {
- // Чтобы сместить десятичную точку на denomPower позиций
- // вправо, мы могли бы воспользоваться pow(). Однако,
- // для этого потребуется зпрещённая math.h, а потому мы
- //вынуждены крутить цикл
- double decimalPointOffseter = 1.0;
- for(size_t i = 0; i < denomPower; ++i)
- decimalPointOffseter /= 10.0;
- outCoeffs[currentPowCoefficient] = numBuffer
- * (isPositiveCoeff ? 1.0 : -1:0)
- / decimalPointOffseter;
- }
- else
- state = Result_CoefficientCantBeStored;
- // Переходим непосредственно к чтению нового члена
- metDecimalDot = false;
- if(ch == '-')
- {
- numBuffer = 0.0;
- isPositiveCoeff = false;
- ch = fgetc(in->stream);
- state = State_AtCoeff;
- }
- else if(ch == '=')
- {
- ch = fgetc(in->stream);
- state = State_AtRightSideStart;
- }
- else if(ch == EOF)
- {
- state = Result_Success;
- }
- else
- {
- numBuffer = 0.0;
- isPositiveCoeff = true;
- state = State_AtCoeff;
- }
- break;
- case State_AtCoeff:
- if(ch >= '0' && ch <= '9')
- {
- numBuffer *= 10.0;
- numBuffer += (float)(int)(ch - '0');
- ch = fgetc(in->stream);
- ++denomPower; // Ничего не проверяем, всё равно будет сброс при точке
- }
- else if(ch == 'x')
- {
- state = State_AtX;
- ch = fgetc(in->stream);
- }
- else if(ch == '+' || ch == '-' || ch == EOF)
- {
- // Окончание коэффициента с нулевой степенью. Придерживаем символ
- currentPowCoefficient = 0;
- state = State_AtCoeffStart;
- }
- else if(ch == '.')
- {
- metDecimalDot = true;
- denomPower = 0;
- }
- else
- state = Result_UnexpectedSymbolInCoeff;
- break;
- case State_AtX:
- // Подготавливаем аккумулятор для коэффициента
- currentPowCoefficient = 0;
- if(ch == '^')
- {
- ch = fgetc(in->stream);
- state = State_AtPowerCoeffStart;
- }
- else
- {
- // Окончание коэффициента с первой степенью. Придерживаем символ
- currentPowCoefficient = 1;
- state = State_AtCoeffStart;
- }
- break;
- case State_AtPowerCoeffStart:
- state = (ch != EOF) ? State_AtPowerCoeff : Result_UnexpectedEndOfPower;
- break;
- case State_AtPowerCoeff:
- if(ch >= '0' && ch <= '9')
- {
- currentPowCoefficient *= 10.0;
- currentPowCoefficient += (size_t)(ch - '0');
- ch = fgetc(in->stream);
- }
- else
- state = State_AtCoeffStart;
- break;
- case State_AtRightSideStart:
- if(ch == '-')
- {
- numBuffer = 0.0;
- isPositiveCoeff = true; // Инверсия знака
- ch = fgetc(in->stream);
- state = State_AtRightSide;
- }
- else if(ch == EOF)
- {
- state = Result_UnexpectedEndOfRightSide;
- }
- else
- {
- numBuffer = 0.0;
- isPositiveCoeff = false; // Инверсия знака
- state = State_AtRightSide;
- }
- break;
- case State_AtRightSide:
- if(ch == EOF)
- {
- currentPowCoefficient = 0;
- numBuffer = -numBuffer;
- // Переходим, чтобы сохранить коэффициент и сразу же выйти
- state = State_AtCoeffStart;
- }
- else if(ch == '.')
- {
- metDecimalDot = true;
- denomPower = 0;
- }
- else
- {
- numBuffer *= 10.0;
- numBuffer += (double)(int)(ch - '0');
- ch = fgetc(in->stream);
- ++denomPower; // Ничего не проверяем, всё равно будет сброс при точке
- }
- break;
- }
- }
- return state;
- }
Add Comment
Please, Sign In to add comment