Guest User

Untitled

a guest
Dec 14th, 2017
89
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.32 KB | None | 0 0
  1. scanf("%s",string[80]);
  2.  
  3. scanf("%fx^2+%fx+%f=0", &a, &b, &c);
  4.  
  5. #include <stdio.h>
  6.  
  7. enum States
  8. {
  9. // Конечные состояния
  10. Result_Success, // Успешное завершение
  11. Result_CoefficientCantBeStored, // Ошибка: массив outCoeffs слишком мал
  12. Result_UnexpectedSymbolInCoeff, // Ошибка: неожиданный символ в коэффициенте
  13. Result_UnexpectedEndOfPower, // Ошибка: После знака степени нет самой степени
  14. Result_UnexpectedEndOfRightSide,// Ошибка: не указана правая часть уравнения
  15.  
  16. // Промежуточные состояния
  17. State_AtCoeffStart, // Первый символ коэффициента (+/-/цифра)
  18. State_AtCoeff, // Дальнейшие цифры коэффициента
  19. State_AtX, // Буква "икс"
  20. State_AtPowerCoeffStart, // Первый символ показателя степени члена
  21. State_AtPowerCoeff, // Показатель степени члена
  22. State_AtRightSideStart, // Первый символ справа от знака равенства
  23. State_AtRightSide, // Дальнейшие цифры справа от знака равенства
  24.  
  25. // Первое неконечное состояние (используется при проверке на необходимость выхода)
  26. FirstInternalState = State_AtCoeffStart
  27. };
  28.  
  29. /**
  30. * Функция разбора строки с линейным уравнением и вычленения из неё коэффициентов.
  31. *
  32. * Переметры:
  33. *
  34. * in
  35. * дескриптов входного символьного потока.
  36. *
  37. * outCoeffs
  38. * указатель на массив, который будет принимать коэффициенты, считанные
  39. * из уравнения. Коэффициент для N-й степени идёт в outCoeffs[N].
  40. * Если определённый коэффициент не указан в уравнении, то в соответствующий
  41. * элемент массива будет записан положительный ноль.
  42. *
  43. * coeffsCount
  44. * Количество элементов в массиве outCoeffs. Если очередная степень приводит
  45. * к записи за пределами outCoeffs, функция возвращает
  46. * Result_CoefficientCantBeStored.
  47. *
  48. * Возвращаемое значение:
  49. *
  50. * Константа из семейства States::Result_*. При возникновении ошибки происходит
  51. * возврат кода, отличного от Result_Success; массив outCoeffs при этом содержит
  52. * те коэффициенты, которые были успешно считаны целиком до возникновения ошибки.
  53. */
  54. enum States parse(FILE* in, double* outCoeffs, size_t coeffsCount)
  55. {
  56. // Зануляем все указанные коэффициенты, вдруг не все из них будут указаны в уравнении
  57. for(size_t i = 0; i < coeffsCount; ++i)
  58. outCoeffs[i] = 0.0;
  59.  
  60. enum States state = State_AtCoeffStart;
  61. size_t currentPowCoefficient = 0;
  62. bool isPositiveCoeff;
  63. double numBuffer = 0.0;
  64. bool metDecimalDot = false;
  65. size_t denomPower = 0;
  66. // Так как нам может потребоваться попридержать текущий символ до следующего
  67. // состояния, введём для него промежуточный буфер
  68. char ch = fgetc(in->stream);
  69. while(state >= FirstInternalState)
  70. {
  71. // Считываем очередной символ и решаем, что с ним делать (решение принимаем
  72. // с помощью простенького конечного автомата).
  73. //
  74. // Да простят меня нелюбители switch-bases FSM, но пробрасывать
  75. // во вспомогательные функции все параметры и переменные — для учебного
  76. // примера это, пожалуй, перебор.
  77. switch(state)
  78. {
  79. case State_AtCoeffStart:
  80. // Сюда мы можем выйти при завершении предыдущего члена.
  81. // Поэтому именно здесь мы выдаём готовый коэффициент.
  82. if(coeffsCount > currentPowCoefficient)
  83. {
  84. // Чтобы сместить десятичную точку на denomPower позиций
  85. // вправо, мы могли бы воспользоваться pow(). Однако,
  86. // для этого потребуется зпрещённая math.h, а потому мы
  87. //вынуждены крутить цикл
  88. double decimalPointOffseter = 1.0;
  89. for(size_t i = 0; i < denomPower; ++i)
  90. decimalPointOffseter /= 10.0;
  91.  
  92. outCoeffs[currentPowCoefficient] = numBuffer
  93. * (isPositiveCoeff ? 1.0 : -1:0)
  94. / decimalPointOffseter;
  95. }
  96. else
  97. state = Result_CoefficientCantBeStored;
  98.  
  99. // Переходим непосредственно к чтению нового члена
  100. metDecimalDot = false;
  101. if(ch == '-')
  102. {
  103. numBuffer = 0.0;
  104. isPositiveCoeff = false;
  105. ch = fgetc(in->stream);
  106. state = State_AtCoeff;
  107. }
  108. else if(ch == '=')
  109. {
  110. ch = fgetc(in->stream);
  111. state = State_AtRightSideStart;
  112. }
  113. else if(ch == EOF)
  114. {
  115. state = Result_Success;
  116. }
  117. else
  118. {
  119. numBuffer = 0.0;
  120. isPositiveCoeff = true;
  121. state = State_AtCoeff;
  122. }
  123. break;
  124.  
  125. case State_AtCoeff:
  126. if(ch >= '0' && ch <= '9')
  127. {
  128. numBuffer *= 10.0;
  129. numBuffer += (float)(int)(ch - '0');
  130. ch = fgetc(in->stream);
  131. ++denomPower; // Ничего не проверяем, всё равно будет сброс при точке
  132. }
  133. else if(ch == 'x')
  134. {
  135. state = State_AtX;
  136. ch = fgetc(in->stream);
  137. }
  138. else if(ch == '+' || ch == '-' || ch == EOF)
  139. {
  140. // Окончание коэффициента с нулевой степенью. Придерживаем символ
  141. currentPowCoefficient = 0;
  142. state = State_AtCoeffStart;
  143. }
  144. else if(ch == '.')
  145. {
  146. metDecimalDot = true;
  147. denomPower = 0;
  148. }
  149. else
  150. state = Result_UnexpectedSymbolInCoeff;
  151. break;
  152.  
  153. case State_AtX:
  154. // Подготавливаем аккумулятор для коэффициента
  155. currentPowCoefficient = 0;
  156. if(ch == '^')
  157. {
  158. ch = fgetc(in->stream);
  159. state = State_AtPowerCoeffStart;
  160. }
  161. else
  162. {
  163. // Окончание коэффициента с первой степенью. Придерживаем символ
  164. currentPowCoefficient = 1;
  165. state = State_AtCoeffStart;
  166. }
  167. break;
  168.  
  169. case State_AtPowerCoeffStart:
  170. state = (ch != EOF) ? State_AtPowerCoeff : Result_UnexpectedEndOfPower;
  171. break;
  172.  
  173. case State_AtPowerCoeff:
  174. if(ch >= '0' && ch <= '9')
  175. {
  176. currentPowCoefficient *= 10.0;
  177. currentPowCoefficient += (size_t)(ch - '0');
  178. ch = fgetc(in->stream);
  179. }
  180. else
  181. state = State_AtCoeffStart;
  182.  
  183. break;
  184.  
  185. case State_AtRightSideStart:
  186. if(ch == '-')
  187. {
  188. numBuffer = 0.0;
  189. isPositiveCoeff = true; // Инверсия знака
  190. ch = fgetc(in->stream);
  191. state = State_AtRightSide;
  192. }
  193. else if(ch == EOF)
  194. {
  195. state = Result_UnexpectedEndOfRightSide;
  196. }
  197. else
  198. {
  199. numBuffer = 0.0;
  200. isPositiveCoeff = false; // Инверсия знака
  201. state = State_AtRightSide;
  202. }
  203. break;
  204.  
  205. case State_AtRightSide:
  206. if(ch == EOF)
  207. {
  208. currentPowCoefficient = 0;
  209. numBuffer = -numBuffer;
  210.  
  211. // Переходим, чтобы сохранить коэффициент и сразу же выйти
  212. state = State_AtCoeffStart;
  213. }
  214. else if(ch == '.')
  215. {
  216. metDecimalDot = true;
  217. denomPower = 0;
  218. }
  219. else
  220. {
  221. numBuffer *= 10.0;
  222. numBuffer += (double)(int)(ch - '0');
  223. ch = fgetc(in->stream);
  224. ++denomPower; // Ничего не проверяем, всё равно будет сброс при точке
  225. }
  226. break;
  227. }
  228. }
  229. return state;
  230. }
Add Comment
Please, Sign In to add comment