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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Калькулятор 
:(
    Опции темы
ALEXEY13
Дата 30.5.2008, 18:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Пожалуйста, напишите объяснения к программе, а то скоро надо сдавать, а сам никак не разберусь.

Код

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

int tok;
double tokval;

int next() {
    for (;;) {
        int c = getchar();
        if (c == EOF || strchr("+-*/^()\n", c) != NULL) return tok = c;
        if (isspace(c)) continue;
        if (isdigit(c) || c == '.') {
            ungetc(c, stdin);
            scanf(" %lf", &tokval);
            return tok = 'n';
        }
        fprintf(stderr, "Bad character: %c\n", c); abort();
    }
}

void skip(int t) { assert(tok == t); next(); }

double expr();

double numpar() {
    if (tok == 'n') { double x = tokval; skip('n'); return x; }
    skip('('); double x = expr(); skip(')'); return x;
}

double factor() {
    double x = numpar();
    if (tok == '^') { skip('^'); x = pow(x, factor()); }
    return x;
}

double term() {
    double x = factor();
    for (;;) {
        if (tok == '*') { skip('*'); x *= factor(); }
        else if (tok == '/') { skip('/'); x /= factor(); }
        else return x;
    }
}

double expr() {
    double x = term();
    for (;;) {
        if (tok == '+') { skip('+'); x += term(); }
        else if (tok == '-') { skip('-'); x -= term(); }
        else return x;
    }
}

int main() {
    next();
    while (tok != EOF) {
        if (tok == '\n') { skip('\n'); continue; }
        printf("%.9g\n", expr());
    }
    return 0;
}

PM MAIL   Вверх
bronislav
Дата 30.5.2008, 19:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Это программа читает из потока математическое выражение и решает его (по крайней мере так задумывалось). Работоспособность программы не проверял - влом.

Но у меня большие сомнения в том, что она работает. В ней видимо не учитываются приоритеты операций. Потому, что все действия выполняются подряд.

А вы напишите что именно вам не понятно - объясню.

Добавлено через 1 минуту и 57 секунд
начнем с этой функции
Код

int next()
{
    for (;;)
    {
        // Получаем из стандартного потока символ
        int c = getchar();
        // Если символ указывает на конец или символ содержится в указанной строке,
        // то присваиваем код символа переменной toc и возвращаемся из функции
        if ( c == EOF || strchr( "+-*/^()\n" , c) != NULL)
            return tok = c;
        // Если символ пробел, то продолжаем
        if ( isspace(c) )
         continue;
        // Если символ цифра или точка, то
        if ( isdigit(c) || c == '.')
        {
            // Помещаем символ обратно в поток
         ungetc(c, stdin);
         // Читаем из потока число в переменную tokval
            scanf(" %lf", &tokval);
            // Присваиваем переменной tok код символа 'n' и возвращаемся из функции
            return tok = 'n';
        }
        // Если прочитанный символ недопустимый, то выводим сообщение об ошибке и  
        fprintf( stderr, "Bad character: %c\n", c);
        // завершаем работу программы
        abort();
    }
}


Хотя ИМХО теме самое место в "Центре помощи"


--------------------
user posted image
иногда проще и быстрей обойти лужу, даже если кажется что она мелкая и путь напрямик короче - ведь она может скрывать открытый люк (с) mes
PM MAIL   Вверх
ALEXEY13
Дата 30.5.2008, 21:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Программа работает правильно (проверял много раз), а не понимаю я на самом деле почти все.
Буду очень признателен, если напишите обьяснения к оставшейся части. Сам точно не смогу разобраться.
PM MAIL   Вверх
bronislav
Дата 30.5.2008, 21:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(ALEXEY13 @  30.5.2008,  20:24 Найти цитируемый пост)
а не понимаю я на самом деле почти все.


Ключевое слово тут почти. А что имено тебе понятно?

Цитата(ALEXEY13 @  30.5.2008,  20:24 Найти цитируемый пост)
Сам точно не смогу разобраться. 

Ты даже не попробуешь?

Запускай трассироваку и пошагово смотри, что делается в коде программы. Смотри значения переменных. Получиш массу впечатлений и опыт разбора чужого кода. Программа не настолько сложная, что бы в ней было сложно разобраться.




--------------------
user posted image
иногда проще и быстрей обойти лужу, даже если кажется что она мелкая и путь напрямик короче - ведь она может скрывать открытый люк (с) mes
PM MAIL   Вверх
ALEXEY13
Дата 31.5.2008, 12:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



А что значит scip и assert?

Это сообщение отредактировал(а) ALEXEY13 - 31.5.2008, 13:12
PM MAIL   Вверх
bronislav
Дата 31.5.2008, 13:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(ALEXEY13 @  31.5.2008,  11:38 Найти цитируемый пост)
А что значит scip? 

Может быть skip?


--------------------
user posted image
иногда проще и быстрей обойти лужу, даже если кажется что она мелкая и путь напрямик короче - ведь она может скрывать открытый люк (с) mes
PM MAIL   Вверх
ALEXEY13
Дата 31.5.2008, 13:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Да, никак не пойму,  что делает skip. А с assert разобрался.
PM MAIL   Вверх
xvr
Дата 2.6.2008, 13:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

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



Цитата(ALEXEY13 @ 30.5.2008,  18:46)
Пожалуйста, напишите объяснения к программе, а то скоро надо сдавать, а сам никак не разберусь.

Код

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

int tok;
double tokval;

int next() {
    for (;;) {
        int c = getchar();
        if (c == EOF || strchr("+-*/^()\n", c) != NULL) return tok = c;
        if (isspace(c)) continue;
        if (isdigit(c) || c == '.') {
            ungetc(c, stdin);
            scanf(" %lf", &tokval);
            return tok = 'n';
        }
        fprintf(stderr, "Bad character: %c\n", c); abort();
    }
}

void skip(int t) { assert(tok == t); next(); }

double expr();

double numpar() {
    if (tok == 'n') { double x = tokval; skip('n'); return x; }
    skip('('); double x = expr(); skip(')'); return x;
}

double factor() {
    double x = numpar();
    if (tok == '^') { skip('^'); x = pow(x, factor()); }
    return x;
}

double term() {
    double x = factor();
    for (;;) {
        if (tok == '*') { skip('*'); x *= factor(); }
        else if (tok == '/') { skip('/'); x /= factor(); }
        else return x;
    }
}

double expr() {
    double x = term();
    for (;;) {
        if (tok == '+') { skip('+'); x += term(); }
        else if (tok == '-') { skip('-'); x -= term(); }
        else return x;
    }
}

int main() {
    next();
    while (tok != EOF) {
        if (tok == '\n') { skip('\n'); continue; }
        printf("%.9g\n", expr());
    }
    return 0;
}

Программа представляет собой парсер, реализованный методом рекурсивного спуска. Каждая из функций expr, numpar, factor, term представляет собой одно из правил в грамматике:
Код

expr : term | term '+' term | term '-' term ;
term : factor | factor '*' factor | factor '/' factor ;
factor : numpar | numpar '^' numpar ;
numpar : NUMBER | '(' expr ')' ;
Функция next извлекает следующую лексему из входного потока, тип лексемы записывается в переменную tok, значение (для числа) в переменную tokval
Функция skip проверяет, что текущая лексема равна заданной в параметре и извлекает следующую лексему


Это сообщение отредактировал(а) xvr - 2.6.2008, 13:55
PM MAIL   Вверх
ALEXEY13
Дата 5.6.2008, 18:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Большое спасибо.
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

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


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

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


 




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


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

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