Модераторы: Poseidon
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> [C++] Проверка арифметического выражения, 1 + a - b * c 
V
    Опции темы
СтудентИзРоссии
  Дата 17.2.2007, 04:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 49
Регистрация: 13.11.2006

Репутация: нет
Всего: нет



Доброй день.

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

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

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

Присоединённый файл ( Кол-во скачиваний: 42 )
Присоединённый файл  ae1.jpg 40,52 Kb
PM MAIL   Вверх
ip127001
Дата 17.2.2007, 09:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 164
Регистрация: 24.11.2006
Где: Omsk

Репутация: нет
Всего: -1



перегрузка опереторов
--------------------
aqua currit et debere currere ut currere solebat
PM MAIL   Вверх
Daevaorn
Дата 17.2.2007, 10:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2155
Регистрация: 29.11.2004
Где: Москва

Репутация: нет
Всего: 70



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

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

очень сочитается
PM MAIL WWW   Вверх
MAKCim
Дата 17.2.2007, 11:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Воін дZэна
****


Профиль
Группа: Экс. модератор
Сообщений: 5644
Регистрация: 10.12.2005
Где: Менск, РБ

Репутация: 6
Всего: 207



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


--------------------
Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі ©

PM MAIL   Вверх
СтудентИзРоссии
  Дата 17.2.2007, 13:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 49
Регистрация: 13.11.2006

Репутация: нет
Всего: нет



Цитата(ip127001 @ 17.2.2007,  09:16)
перегрузка опереторов

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

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

Вы правы, схема есть, она понятна, но с реализацией проблема,
не могли бы Вы помочь? Будем признательны.
PM MAIL   Вверх
Earnest
Дата 17.2.2007, 15:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 2
Всего: 183



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

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


--------------------
...
PM   Вверх
СтудентИзРоссии
Дата 17.2.2007, 18:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 49
Регистрация: 13.11.2006

Репутация: нет
Всего: нет



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

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

Спасибо, может и правда кто-то сможет помочь.
PM MAIL   Вверх
Бонифаций
Дата 17.2.2007, 18:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 827
Регистрация: 15.9.2005
Где: Brisbane

Репутация: 1
Всего: 40



тебе надо
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;
}



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



--------------------
 Бонифаций.
 
PM MAIL ICQ Skype GTalk Jabber YIM   Вверх
Xenon
Дата 17.2.2007, 19:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1529
Регистрация: 12.4.2006

Репутация: 19
Всего: 50



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

//////////////////////////////////////
#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;
}
     



--------------------
user posted image  
PM MAIL   Вверх
СтудентИзРоссии
Дата 17.2.2007, 20:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 49
Регистрация: 13.11.2006

Репутация: нет
Всего: нет



Цитата(Бонифаций @ 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", а программа
говорит о неправильном операторе в записе.

Это сообщение отредактировал(а) СтудентИзРоссии - 17.2.2007, 21:06
PM MAIL   Вверх
Бонифаций
Дата 18.2.2007, 00:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 827
Регистрация: 15.9.2005
Где: Brisbane

Репутация: 1
Всего: 40



тебе прям готовую надо? ну вот на тех принципах что я писал:
Код

#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  и будет нормально


--------------------
 Бонифаций.
 
PM MAIL ICQ Skype GTalk Jabber YIM   Вверх
СтудентИзРоссии
Дата 18.2.2007, 00:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 49
Регистрация: 13.11.2006

Репутация: нет
Всего: нет



Цитата(Бонифаций @ 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  и будет нормально

Огромное Вам СПАСИБО! Работает!!!
PM MAIL   Вверх
bigmaik
Дата 31.1.2012, 05:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 5
Регистрация: 31.1.2012

Репутация: нет
Всего: нет



Здравствуйте! А можете эту же программу в Pascal написать???

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

Добавлено через 1 минуту и 50 секунд
Здравствуйте! А можете эту же программу в Pascal написать???
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Центр помощи"

ВНИМАНИЕ! Прежде чем создавать темы, или писать сообщения в данный раздел, ознакомьтесь, пожалуйста, с Правилами форума и конкретно этого раздела.
Несоблюдение правил может повлечь за собой самые строгие меры от закрытия/удаления темы до бана пользователя!


  • Название темы должно отражать её суть! (Не следует добавлять туда слова "помогите", "срочно" и т.п.)
  • При создании темы, первым делом в квадратных скобках укажите область, из которой исходит вопрос (язык, дисциплина, диплом). Пример: [C++].
  • В названии темы не нужно указывать происхождение задачи (например "школьная задача", "задача из учебника" и т.п.), не нужно указывать ее сложность ("простая задача", "легкий вопрос" и т.п.). Все это можно писать в тексте самой задачи.
  • Если Вы ошиблись при вводе названия темы, отправьте письмо любому из модераторов раздела (через личные сообщения или report).
  • Для подсветки кода пользуйтесь тегами [code][/code] (выделяйте код и нажимаете на кнопку "Код"). Не забывайте выбирать при этом соответствующий язык.
  • Помните: один топик - один вопрос!
  • В данном разделе запрещено поднимать темы, т.е. при отсутствии ответов на Ваш вопрос добавлять новые ответы к теме, тем самым поднимая тему на верх списка.
  • Если вы хотите, чтобы вашу проблему решили при помощи определенного алгоритма, то не забудьте описать его!
  • Если вопрос решён, то воспользуйтесь ссылкой "Пометить как решённый", которая находится под кнопками создания темы или специальным флажком при ответе.

Более подробно с правилами данного раздела Вы можете ознакомится в этой теме.

Если Вам помогли и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, Poseidon, Rodman

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Центр помощи | Следующая тема »


 




[ Время генерации скрипта: 0.1437 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.