Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Центр помощи > [C++] Проверка арифметического выражения


Автор: СтудентИзРоссии 17.2.2007, 04:31
Доброй день.

Необходима помощь в написании алгоритма
по проверке арифметического выражения.

Если у кого-то есть опыт в написании подобного алгоритма на C, подскажите как?
Может быть есть готовое решение?

p.s. Схема (пример) арифметического выражения в прикреплённом файле.

Автор: ip127001 17.2.2007, 09:16
перегрузка опереторов

Автор: Daevaorn 17.2.2007, 10:55
Цитата(СтудентИзРоссии @  17.2.2007,  05:31 Найти цитируемый пост)
написании подобного алгоритма на C

Цитата(ip127001 @  17.2.2007,  10:16 Найти цитируемый пост)
перегрузка опереторов 

очень сочитается

Автор: MAKCim 17.2.2007, 11:09
СтудентИзРоссии
у тебя ж готовая схема есть, бери и пиши прямо в лоб

Автор: СтудентИзРоссии 17.2.2007, 13:36
Цитата(ip127001 @ 17.2.2007,  09:16)
перегрузка опереторов

Не могли бы привести пример?

Цитата(MAKCim @ 17.2.2007,  11:09)
СтудентИзРоссии
у тебя ж готовая схема есть, бери и пиши прямо в лоб

Вы правы, схема есть, она понятна, но с реализацией проблема,
не могли бы Вы помочь? Будем признательны.

Автор: Earnest 17.2.2007, 15:29
Для домашних заданий, курсовых, существует "Центр Помощи".

Тема перенесена! 

Автор: СтудентИзРоссии 17.2.2007, 18:48
Цитата(Earnest @ 17.2.2007,  15:29)
Для домашних заданий, курсовых, существует "Центр Помощи".

Тема перенесена!

Спасибо, может и правда кто-то сможет помочь.

Автор: Бонифаций 17.2.2007, 18:53
тебе надо
1) лексический анализатор - который из строки (или файла) будет делать поток лексем. Согласно синтаксической диаграмме Вирта (которую ты привел) у тебя могут быть лексемы:

 * / + - целое буква , [ ]

для реализации подойдет например strtok. 

2) синтаксический анализатор.

разбирает поток лексем в соответствии с теми диаграммами которые ты привел. Вирт давал инфо  какой тип диаграммы должен соответствовать какой конструкции языка (на паскале правда).

то есть у тебя должно быть что - то типа 
Код


int ae1() {
  int res;
  int tmp;

  res = operand();

  while( 1 ) {   
     if (следующая лексема == '*') {
        считать_следующую_лексему();
        tmp = operand();
        res  *=  tmp;
        continue;       
    } ;

     if (следующая лексема == '/') {
        считать_следующую_лексему();
        tmp = operand();
        res  =  res / tmp;
        continue;       
    } ;

     if (следующая лексема == '+') {
        считать_следующую_лексему();
        tmp = operand();
        res  =  res + tmp;
        continue;       
    } ;

     if (следующая лексема == '-') {
        считать_следующую_лексему();
        tmp = operand();
        res  =  res - tmp;
        continue;       
    } ;

   /* если мы тут то следующий символ не из *-+/  */
    return res; 
  }

  return res;
}



Остаток допишу позже

Автор: Xenon 17.2.2007, 19:25
Если нужен просто обрезаный парсер, то чего-нибудь типа :
Код

//////////////////////////////////////
#include <iostream>
const int MAX=20;
class stack
{
private:
    char data[MAX];
    int size;
public:
    stack():size(0) {}
    void push (char var)
    {
        data[++size]=var;
    }
    char pop()
    {
        return data[size--];
    }
    int get_size()
    {
        return size;
    }
};
class expresser
{
private:
    stack st;
public:
    void parse(char* expression)
    {
        char ch; //Symbol from string
        char lastop; //Last operator
        char lastval; //Last number
        for (int i=0;i<strlen(expression);++i)
        {
            ch=expression[i];
            if (ch>='0' && ch<='9')
            {
                st.push(ch-'0');
            }
            else
            {
                if (ch=='*' || ch=='+' || ch=='-' || ch=='/')
                {
                    if (st.get_size()==1)
                    {
                        st.push(ch);
                    }
                    else
                    {
                        lastval=st.pop();
                        lastop=st.pop();
                        if ((ch=='*' || ch=='/') && (lastop=='+' || lastop=='-'))
                        {
                            st.push(lastop);
                            st.push(lastval);
                        }
                        else
                        {
                            switch(lastop)
                            {
                            case '+':st.push(st.pop()+lastval);
                                break;
                            case '-':st.push(st.pop()-lastval);
                                break;
                            case '/':st.push(st.pop()/lastval);
                                break;
                            case '*':st.push(st.pop()*lastval);
                            default: std::cout << "Error - unknown operator"; exit(1); break;
                            }
                        }
                        st.push(ch);
                    }
                }
                else
                {
                    cout << "Error";
                    exit(1);
                }
            }
        }
    }
    int solve()
    {
        char lastval;
        while (st.get_size()>1)
        {
            lastval=st.pop();
            switch(st.pop())
            {
            case '+': st.push(st.pop()+lastval);
                break;
            case '-': st.push(st.pop()-lastval);
                break;
            case '/': st.push(st.pop()/lastval);
                break;
            case '*': st.push(st.pop()*lastval);
                break;
            default: std::cout << "Error - unknown operator"; exit(1);break;
            }
        }
        return int(st.pop());
    }
};
int main(int argc, char* argv[])
{
    expresser parser;
    char* expression="2+4/2+1";
    parser.parse(expression);
    std::cout << parser.solve();
    std::cin.get();
    return 0;
}
     

Автор: СтудентИзРоссии 17.2.2007, 20:20
Цитата(Бонифаций @ 17.2.2007,  18:53)
тебе надо
1) лексический анализатор - который из строки (или файла) будет делать поток лексем. Согласно синтаксической диаграмме Вирта (которую ты привел) у тебя могут быть лексемы:

 * / + - целое буква , [ ]

для реализации подойдет например strtok. 

2) синтаксический анализатор.

разбирает поток лексем в соответствии с теми диаграммами которые ты привел. Вирт давал инфо  какой тип диаграммы должен соответствовать какой конструкции языка (на паскале правда).

то есть у тебя должно быть что - то типа 
Код


int ae1() {
  int res;
  int tmp;

  res = operand();

  while( 1 ) {   
     if (следующая лексема == '*') {
        считать_следующую_лексему();
        tmp = operand();
        res  *=  tmp;
        continue;       
    } ;

     if (следующая лексема == '/') {
        считать_следующую_лексему();
        tmp = operand();
        res  =  res / tmp;
        continue;       
    } ;

     if (следующая лексема == '+') {
        считать_следующую_лексему();
        tmp = operand();
        res  =  res + tmp;
        continue;       
    } ;

     if (следующая лексема == '-') {
        считать_следующую_лексему();
        tmp = operand();
        res  =  res - tmp;
        continue;       
    } ;

   /* если мы тут то следующий символ не из *-+/  */
    return res; 
  }

  return res;
}



Остаток допишу позже

Необходим простой анализатор, который проверяет запись на её правильность.
Например: 1+2*3/3+ABC[123]-ASD+100 (верная запись)
Например: 3434+ewrwer...,.,%$ (неверная запись).
Будем очень благодарные, если сможете помочь.

Xenon, спасибо за код, но к сожалению, на некоторых
правильных записях программа выдаёт неверный результат,
например есть запись "2+4/2+1+1+3+2+3*1/3", а программа
говорит о неправильном операторе в записе.

Автор: Бонифаций 18.2.2007, 00:15
тебе прям готовую надо? ну вот на тех принципах что я писал:
Код

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

#define CH (*current_char)
#define GCH current_char++

static char *current_char, *start;

void ae1();

void variable()
{

    while (isalpha(CH))
        GCH;
    if (CH == '[') {
        do {
            GCH;
            ae1();
        } while (CH == ',');

        if (CH == ']')
            GCH;
        else {
            printf("Ошибка около %d буквы",
                   current_char - start);
            exit(1);

        }
    }
}

void integer()
{
    while (isdigit(CH))
        GCH;
}

void operand()
{
    if (isdigit(CH)) {
        integer();
        return;
    };

    if (isalpha(CH)) {
        variable();
        return;
    };

    printf("Ошибка около %d буквы", current_char - start);
    exit(1);
}
void ae1()
{
    do {
        operand();
        if (CH == '*' || CH == '/' || CH == '-' || CH == '+') {
            GCH;
            continue;
        } else
            break;
    } while (1);
    return;
}

void validate(char *expression)
{
    current_char = expression;
    start = expression;
    ae1();
    if (CH != '\0')
        printf("Ошибка около %d буквы",
               current_char - start);
}


int main()
{
    validate("2+4/2+1+1+3+2+3*1/3");
    return 0;
}



Добавлено @ 00:17 
я писал навскидку, не проверяя, так что сами тестируйте

Добавлено @ 00:22 
ps/ Я писал на С, ориентируясь на исходное сообщение, где был вопрос именно по С. Если надо именно на C++ - сами уж доведите. Там собственно добавьте обрабтку ошибок не с помощью exit а через exception  и будет нормально

Автор: СтудентИзРоссии 18.2.2007, 00:51
Цитата(Бонифаций @ 18.2.2007,  00:15)
тебе прям готовую надо? ну вот на тех принципах что я писал:
Код

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

#define CH (*current_char)
#define GCH current_char++

static char *current_char, *start;

void ae1();

void variable()
{

    while (isalpha(CH))
        GCH;
    if (CH == '[') {
        do {
            GCH;
            ae1();
        } while (CH == ',');

        if (CH == ']')
            GCH;
        else {
            printf("Ошибка около %d буквы",
                   current_char - start);
            exit(1);

        }
    }
}

void integer()
{
    while (isdigit(CH))
        GCH;
}

void operand()
{
    if (isdigit(CH)) {
        integer();
        return;
    };

    if (isalpha(CH)) {
        variable();
        return;
    };

    printf("Ошибка около %d буквы", current_char - start);
    exit(1);
}
void ae1()
{
    do {
        operand();
        if (CH == '*' || CH == '/' || CH == '-' || CH == '+') {
            GCH;
            continue;
        } else
            break;
    } while (1);
    return;
}

void validate(char *expression)
{
    current_char = expression;
    start = expression;
    ae1();
    if (CH != '\0')
        printf("Ошибка около %d буквы",
               current_char - start);
}


int main()
{
    validate("2+4/2+1+1+3+2+3*1/3");
    return 0;
}



Добавлено @ 00:17 
я писал навскидку, не проверяя, так что сами тестируйте

Добавлено @ 00:22 
ps/ Я писал на С, ориентируясь на исходное сообщение, где был вопрос именно по С. Если надо именно на C++ - сами уж доведите. Там собственно добавьте обрабтку ошибок не с помощью exit а через exception  и будет нормально

Огромное Вам СПАСИБО! Работает!!!

Автор: bigmaik 31.1.2012, 05:17
Здравствуйте! А можете эту же программу в Pascal написать???

Добавлено через 20 секунд
Здравствуйте! А можете эту же программу в Pascal написать???

Добавлено через 1 минуту и 50 секунд
Здравствуйте! А можете эту же программу в Pascal написать???

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)