Учеба и наука

Язык Си - вопрос №274743

Помогите с задачей на языке Си.Дано целочисленное арифметическое выражение, записанное как строка, в десятичной системе счисления. Проверить правильность записи и вычислить значение этого выражения. Выражение записывается без скобок, операции выполняются в порядке их следования.Буду благодарен

май 21, 2012 г.

  • Всего ответов: 1

  • Валентина - аватарка

    Валентина

    3-й в

    /* Это модуль содержит простой синтаксический анализатор,
    который не распознает переменные.
    */

    #include <stdlib.h>
    #include <ctype.h>
    #include <stdio.h>
    #include <string.h>

    #define DELIMITER 1
    #define VARIABLE 2
    #define NUMBER 3

    extern char *prog; /* содержит анализируемое выражение */
    char token[80];
    char tok_type;

    void eval_exp(double *answer), eval_exp2(double *answer);
    void eval_exp3(double *answer), eval_exp4(double *answer);
    void eval_exp5(double *answer), eval_exp6(double *answer);
    void atom(double *answer);
    void get_token(void), putback(void);
    void serror(int error);
    int isdelim(char c);

    /* Точка входа анализатора. */
    void eval_exp(double *answer)
    {
    get_token();
    if(!*token) {
    serror(2);
    return;
    }
    eval_exp2(answer);

    if(*token) serror(0); /* последней лексемой должен быть нуль */
    }

    /* Сложение или вычитание двух слагаемых. */
    void eval_exp2(double *answer)
    {
    register char op;
    double temp;

    eval_exp3(answer);
    while((op = *token) == '+' || op == '-') {
    get_token();
    eval_exp3(&temp);
    switch(op) {
    case '-':
    *answer = *answer — temp;
    break;
    case '+':
    *answer = *answer + temp;
    break;
    }
    }
    }

    /* Умножение или деление двух множителей. */
    void eval_exp3(double *answer)
    {
    register char op;
    double temp;

    eval_exp4(answer);
    while((op = *token) == '*' || op == '/' || op == '%') {
    get_token();
    eval_exp4(&temp);
    switch(op) {
    case '*':
    *answer = *answer * temp;
    break;
    case '/':
    if(temp == 0.0) {
    serror(3); /* деление на нуль */
    *answer = 0.0;
    } else *answer = *answer / temp;
    break;
    case '%':
    *answer = (int) *answer % (int) temp;
    break;
    }
    }
    }

    /* Возведение в степень */
    void eval_exp4(double *answer)
    {
    double temp, ex;
    register int t;

    eval_exp5(answer);

    if(*token == '^') {
    get_token();
    eval_exp4(&temp);
    ex = *answer;
    if(temp==0.0) {
    *answer = 1.0;
    return;
    }
    for(t=temp-1; t>0; --t) *answer = (*answer) * (double)ex;
    }
    }

    /* Умножение унарных операторов + и -. */
    void eval_exp5(double *answer)
    {
    register char op;

    op = 0;
    if((tok_type == DELIMITER) && *token=='+' || *token == '-') {
    op = *token;
    get_token();
    }
    eval_exp6(answer);
    if(op == '-') *answer = -(*answer);
    }

    /* Вычисление выражения в скобках. */
    void eval_exp6(double *answer)
    {
    if((*token == '(')) {
    get_token();
    eval_exp2(answer);
    if(*token != ')')
    serror(1);
    get_token();
    }
    else
    atom(answer);
    }

    /* Получение значения в скобках. */
    void atom(double *answer)
    {
    if(tok_type == NUMBER) {
    *answer = atof(token);
    get_token();
    return;
    }
    serror(0); /* иначе синтаксическая ошибка в выражении */
    }

    /* Выражение лексемы во входной поток. */
    void putback(void)
    {
    char *t;

    t = token;
    for(; *t; t++) prog--;
    }

    /* Отображение сообщения об ошибке. */
    void serror(int error)
    {
    static char *e[]= {
    «Синтаксическая ошибка»,
    «Несбалансированные скобки»,
    «Нет выражения»,
    «Деление на нуль»
    };
    printf("%s\n", e[error]);
    }

    /* Возврат очередной лексемы. */
    void get_token(void)
    {
    register char *temp;

    tok_type = 0;
    temp = token;
    *temp = '\0';

    if(!*prog) return; /* конец выражения */
    while(isspace(*prog)) ++prog; /* пропустить пробелы,
    символы табуляции и пустой строки */

    if(strchr("+-*/%^=()", *prog)){
    tok_type = DELIMITER;
    /* перейтик следующему символу */
    *temp++ = *prog++;
    }
    else if(isalpha(*prog)) {
    while(!isdelim(*prog)) *temp++ = *prog++;
    tok_type = VARIABLE;
    }
    else if(isdigit(*prog)) {
    while(!isdelim(*prog)) *temp++ = *prog++;
    tok_type = NUMBER;
    }

    *temp = '\0';
    }

    /* Возвращение значения ИСТИНА, если с является разделителем. */
    int isdelim(char c)
    {

    if(strchr(" +-/*%^=()", c) || c==9 || c=='\r' || c==0)
    return 1;
    return 0;
    }

    char *prog;
    void eval_exp(double *answer);

    int main(void)
    {
    double answer;
    char *p;

    p = (char *) malloc(100);
    if(!p) {
    printf(«Ошибка при выделении памяти.\n»);
    exit(1);
    }

    /* Обработка выражений до ввода пустой строки. */
    do {
    prog = p;
    printf(«Введите выражение: „);
    gets(prog);
    if(!*prog) break;
    eval_exp(&answer);
    printf(“Результат: %.2f\n», answer);
    } while(*p);

    return 0;
    }

     

    Проверила, работает

    Источник и описание 

    lord-n.narod.ru/download/books/walla/programming/Spr_po_C/24/2404.htm

    Еще один источник

     www.bhv.ru/books/get_pdf_data.php?id=183103

    Буду благодарна, если отметите 

    май 22, 2012 г.

Похожие вопросы