Проверить корректность арифметического выражения, заданного строкой - C (СИ)
Формулировка задачи:
Решение задачи: «Проверить корректность арифметического выражения, заданного строкой»
- #include <stdio.h>
- #include <stdlib.h>
- #include <ctype.h>
- #include <string.h>
- //коды ошибок
- enum err_expr {
- ERR_SUCCESS, //нет ошибки
- ERR_NONE_STR, //строка пуста
- ERR_DIV_BYZERO, //деление на нуль!
- ERR_PARSE_NUMBER, //ошибка при парсирование числа
- ERR_EXPR //другие ошибки: скобки, иные символы...
- //...
- };
- int is_expr(const char* s);
- double _calc(const char* s, const char** p, enum err_expr* e);
- //вычисление мат-выражений из строки
- double calculate(char* s, enum err_expr* err){
- char* a, *b;
- enum err_expr e = ERR_SUCCESS;
- const char* p = NULL;
- double n = 0.0;
- if(*s && is_expr(s)){
- a = s;
- while(*a && !isspace(*a))
- ++a;
- for(b = a; *a; *a = *(++b)){
- if(! isspace(*b))
- ++a;
- }
- if(*s)
- n = _calc(s, &p, &e);
- else
- e = ERR_NONE_STR;
- } else
- e = (*s) ? ERR_EXPR : ERR_NONE_STR;
- if(err != NULL)
- *err = e;
- return n;
- }
- int main(void){
- enum err_expr e;
- char s[256];
- double t, res;
- //1-ый пример
- strcpy(s, "-(-(-(-(-(-(-(-(-(-0.5))))))) + 0.7))*5.123-(-(0.4*3.3/0.0001))/2.5");
- t = -(-(-(-(-(-(-(-(-(-0.5))))))) + 0.7))*5.123-(-(0.4*3.3/0.0001))/2.5;
- res = calculate(s, NULL);
- printf("result: %lg\n", res);
- printf("test : %lg\n\n", t);
- //2-ой пример
- strcpy(s, "-1.4e+5 + (-2) * (-(-5.5 + 0.1234)*(-5.2 / 0.1234 + 9.9) + 0.333) / 0.5");
- t = -1.4e+5 + (-2) * (-(-5.5 + 0.1234)*(-5.2 / 0.1234 + 9.9) + 0.333) / 0.5;
- res = calculate(s, NULL);
- printf("result: %lg\n", res);
- printf("test : %lg\n\n", t);
- //3-ий пример
- strcpy(s, "1. / 1000.0 * (-(-999.2-(-9.0e+3))+(-(0.5 + 5.5*200)/(-3.3) + 0.7) * 2.8)");
- t = 1. / 1000.0 * (-(-999.2-(-9.0e+3))+(-(0.5 + 5.5*200)/(-3.3) + 0.7) * 2.8);
- res = calculate(s, NULL);
- printf("result: %lg\n", res);
- printf("test : %lg\n\n", t);
- //4-ый пример с обработкой ошибок
- strcpy(s, "10 * 2 / 0");
- res = calculate(s, &e);
- switch(e){
- case ERR_SUCCESS:
- printf("%lg\n\n", res);
- break;
- case ERR_NONE_STR:
- puts("строка пуста");
- break;
- case ERR_DIV_BYZERO:
- puts("деление на нуль!");
- break;
- case ERR_PARSE_NUMBER:
- puts("ошибка при парсирование числа.");
- break;
- case ERR_EXPR:
- puts("другая ошибка.");
- break;
- }
- getchar();
- return 0;
- }
- //проверка скобок на правильность расстоновки
- int is_expr(const char* s){
- int n = 0;
- for(; *s; ++s){
- if(*s == '(')
- ++n;
- else if(*s == ')'){
- if(--n < 0)
- break;
- }
- }
- return (n == 0);
- }
- // рекурсивное вычисление мат-выражений из строки
- double _calc(const char* s, const char** p, enum err_expr* e){
- int neg;
- char c, c1;
- char* i;
- const char* o;
- double k, v, n = 0.0;
- if((*s == '(') || (*s == '-' && *(s + 1) == '(')){
- neg = (*s == '-');
- n = _calc(s + (1 + neg), &o, e);
- if(*e != ERR_SUCCESS)
- return 0.0;
- s = o;
- if(neg)
- n = 0.0 - n;
- } else {
- n = strtod(s, &i);
- if(s == i){
- *e = ERR_PARSE_NUMBER;
- return 0.0;
- }
- s = i;
- }
- while(*s && (*s != ')')){
- c = *s++;
- if(! *s){
- *e = ERR_EXPR;
- return 0.0;
- }
- if(*s == '('){
- k = _calc(s + 1, &o, e);
- if(*e != ERR_SUCCESS)
- return 0.0;
- s = o;
- } else {
- k = strtod(s, &i);
- if(s == i){
- *e = ERR_PARSE_NUMBER;
- return 0.0;
- }
- s = i;
- }
- switch(c){
- case '*':
- n *= k;
- break;
- case '/':
- if(k == 0.0){
- *e = ERR_DIV_BYZERO;
- return 0.0;
- }
- n /= k;
- break;
- case '+':
- case '-':
- if((*s == '*') || (*s == '/')) {
- v = k;
- while(*s && (*s != ')')) {
- c1 = *s;
- if((c1 == '+') || (c1 == '-'))
- break;
- ++s;
- if(*s == '('){
- k = _calc(s + 1, &o, e);
- if(*e != ERR_SUCCESS)
- return 0.0;
- s = o;
- } else {
- k = strtod(s, &i);
- if(s == i){
- *e = ERR_PARSE_NUMBER;
- return 0.0;
- }
- s = i;
- }
- if(c1 == '/') {
- if(k == 0.0){
- *e = ERR_DIV_BYZERO;
- return 0.0;
- }
- v /= k;
- } else if(c1 == '*')
- v *= k;
- }
- k = v;
- }
- if(c == '+')
- n += k;
- else if(c == '-')
- n -= k;
- if(*s == ')'){
- *p = s + 1;
- return n;
- }
- break;
- }
- }
- if(*s == ')')
- *p = s + 1;
- return n;
- }
Объяснение кода листинга программы
Этот код - это математический калькулятор, который проверяет и вычисляет выражения, заданные в виде строк. Он поддерживает основные арифметические операции, а также скобки для группировки выражений. Код также проверяет ошибки, такие как деление на ноль и неправильное использование скобок. Синтаксис кода:
-
include
- подключает стандартную библиотеку для ввода и вывода данных. -
include
- подключает стандартную библиотеку для работы с числами. -
include
- подключает стандартную библиотеку для работы со строками и символами. -
include
- подключает стандартную библиотеку для работы со строками. Основная функция - это функция calculate, которая принимает строку с математическим выражением, указатель на переменную, в которую будет сохранено результат, и указатель на ошибку. Функция parse_number - это функция, которая преобразует строку в число. Код использует стек для обработки выражений. Когда функция is_expr проверяет, что выражение корректно, она создает стек для хранения операндов и операций. Когда она встречает операцию, она помещает ее на вершину стека, а затем продолжает работу с предыдущими операндами. Когда функция _calc встречает число, она вызывает функцию parse_number для преобразования строки в число, а затем добавляет это число в стек. Когда функция _calc встречает операцию, она проверяет, что стек не пуст, и затем выполняет операцию. Если происходит ошибка, она возвращает значение ошибки. Функция main - это точка входа в программу. Она демонстрирует использование калькулятора, вызывая функцию calculate для трех примеров. В первом примере она вычисляет выражение
-(-(-5.5 + 0.1234)*(-5.2 / 0.1234 + 9.9) + 0.333) / 0.5
. Во втором примере она вычисляет выражение-1.4e+5 + (-2) * (-(-5.5 + 0.1234)*(-5.2 / 0.1234 + 9.9) + 0.333) / 0.5
. В третьем примере она вычисляет выражение1. / 1000.0 * (-(-999.2-(-9.0e+3))+(-(0.5 + 5.5*200)/(-3.3) + 0.7) * 2.8)
. В третьем примере программа выдает ошибку, потому что деление на ноль невозможно. В четвертом примере программа выдает ошибку, потому что выражение10 * 2 / 0
некорректно синтаксически.
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д