In this case, scanf() with one large format string, as suggested by @Sergey, will not work. Once the members of the equation can follow in any order, then the line must be read in parts.
Let the input have a string of the form S1+...+SN=0 or S1+...+SN=<нецелое_число> (where Si = <нецелое_число>x , or Si = <нецелое_число>x^<целое_число> ), and output - an array of coefficients, where the array index corresponds to the desired degree when the coefficient.
Important note: since the number can be arbitrarily large, then in order to avoid overflowing the string buffer, we will read it in a small number. Well, since the string is complex, we use the state machine.
#include <stdio.h> #define bool unsigned char #define true 1 #define false 0 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); 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); state = State_AtCoeff; } else if(ch == '=') { ch = fgetc(in); 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); ++denomPower; // Ничего не проверяем, всё равно будет сброс при точке } else if(ch == 'x') { state = State_AtX; ch = fgetc(in); } 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); 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); } else state = State_AtCoeffStart; break; case State_AtRightSideStart: if(ch == '-') { numBuffer = 0.0; isPositiveCoeff = true; // Инверсия знака ch = fgetc(in); 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); ++denomPower; // Ничего не проверяем, всё равно будет сброс при точке } break; } } return state; }
5+3x+21x^2=0, and21x^2+3x=-5, and (surely)21x^2+5=0, and21x^2+3x=0... And this is without taking into account the more exotic options such as21x^2+2x+x+5=0. - Yaant5x^2-3x-10=0? - AnT