Автор работы: Пользователь скрыл имя, 25 Марта 2012 в 21:52, курсовая работа
Разработать калькулятор для командной строки – expr_stud, выполняющий вычисление арифметического выражения, переданного в качестве входных данных. Арифметическое выражение записывается следующим образом: (ApB), где А – левый операнд, В – правый операнд, p – арифметическая операция. А и В – вещественные числа, р=+|-|*|/.
Федеральное агентство связи
Государственное образовательное учреждение высшего профессионального образования
«Сибирский государственный университет телекоммуникаций и информатики»
Факультет ИВТ
Кафедра вычислительных систем
Курсовой проект
По теме «Разработка утилиты командной строки»
Выполнил:
студент гр. ВМ-05
Машкевич С.С
Проверил:
старший преподаватель
Поляков А.Ю.
Новосибирск, 2011
Задание:
Разработать калькулятор для командной строки – expr_stud, выполняющий вычисление арифметического выражения, переданного в качестве входных данных. Арифметическое выражение записывается следующим образом: (ApB), где А – левый операнд, В – правый операнд, p – арифметическая операция. А и В – вещественные числа, р=+|-|*|/.
Анализ задачи:
Синтаксический анализ — это процесс сопоставления линейной последовательности лексем (слов, токенов) языка с его формальной грамматикой. Результатом обычно является дерево разбора (синтаксическое дерево). Обычно применяется совместно с лексическим анализом. Синтаксический анализатор — это программа или часть программы, выполняющая синтаксический анализ.
Как правило, результатом синтаксического анализа является синтаксическая структура предложения, представленная либо в виде дерева зависимостей, либо в виде дерева составляющих, либо в виде некоторой комбинации первого и второго способов представления.
Задание было выполнено с использованием рекурсий. На вход подавалось выражение, которое обрабатывалось в функции input, являющейся синтаксическим анализатором. При вызове функции input() из входной строки выбирается лексема. Если она является пустой строкой, то функция печатает сообщение «Otsutstvuet vwragenie» и завершается. Если это не пустая строка, вызывается функция slagaemwe(), которая обрабатывает операции «+» и «-». В результате, функция slagaemwe() вызывает mnogiteli(), обрабатывающую «*» и «/», a mnogiteli() вызывает edznaki(). Затем функция edznaki() проверяет, не является ли лексема унарным плюсом или минусом. Если это не так, то вызывается skobki(). В этот момент skobki() может рекурсивно вызвать либо slagaemwe(), в случае выражения, заключенного в скобки, либо obr(), чтобы определить значение числа. Затем происходит выборка следующей лексемы и возврат из цепочки вызовов функций.
Тестовые данные:
В качестве тестовых данных возьмём следующее выражение и дадим описание алгоритма его вычисления:
100/5+4*2
В данном случае первой лексемой является число 100. Поскольку это не пустая строка, вызывается функция slagaemwe(). Происходит проход по цепочке вызовов функций. Поскольку лексема не является открывающей скобкой, выполняется функция obr() и переменной *otvet присваивается значение 100 и выбирается следующая лексема. Ей становится оператор «/», а управление передаётся функции mnogiteli(). Поскольку текущей лексемой является символ «/», он сохраняется в переменной zn. Затем анализатор выбирает следующую лексему и спуск по цепочке начинается снова. Как и раньше, вызывается функция obr(). Полученное значение 5 возвращается в переменной *otvet, и считывается лексема «+». Это вызывает возврат по цепочке до mnogiteli(), где происходит первая арифметическая операция — деление 100 на 5. Полученный результат возвращается функции slagaemwe(), где выбирается следующая лексема и выполняется очередной проход по цепочке вызовов функций. После этого в *otvet записывается значение 4 и совершается переход к следущей лексеме «*». После возврата в функцию mnogiteli(), считывается следующая лексема и вновь происходит вызов функции obr(), *otvet присваивается значение 2. Присвоенное значение возвращается в mnogiteli(), где 4 умножается на 2. Полученный результат переходит в slagaemwe(), где выполняется последняя операция: к 20 прибавляем 8.
Листинг программы:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#define NOMER 1
#define RAZDELITEL 2
void input(double *otvet);
void slagaemwe(double *otvet);
void mnogiteli(double *otvet);
void edznaki(double *otvet);
void skobki(double *otvet);
void obr(double *otvet);
char leks_type;
char leks[80];
char *vwr;
void next_leks();
int razd(char c);
void oshibka(int er);
void input(double *otvet)
{
next_leks();
if(!*leks) {
oshibka(2);
return;
}
slagaemwe(otvet);
if(*leks) oshibka(0);
}
void slagaemwe(double *otvet)
{
char zn;
double vr;
mnogiteli(otvet);
zn = *leks;
while(zn == '+' || zn == '-') {
next_leks();
if(*leks=='\0'||*leks=='+'||*
oshibka(0);
else{
mnogiteli(&vr);
switch(zn) {
case '-':
*otvet = *otvet - vr;
break;
case '+':
*otvet = *otvet + vr;
break;
}}
}
}
void mnogiteli(double *otvet)
{
char zn;
double vr;
edznaki(otvet);
zn = *leks;
while(zn == '*' || zn == '/') {
next_leks();
if(*leks=='\0'||*leks=='*'||*
oshibka(0);
else{
edznaki(&vr);
switch(zn) {
case '*':
*otvet = *otvet * vr;
break;
case '/':
if(vr == 0.0) {
oshibka(3);
*otvet = 0.0;
} else *otvet = *otvet/ vr;
break;
}}
}
}
void edznaki(double *otvet)
{
char zn;
zn = 0;
if((leks_type == RAZDELITEL) && (*leks=='+' || *leks == '-')) {
zn = *leks;
next_leks();
}
skobki(otvet);
if(zn == '-') *otvet = -(*otvet);
}
void skobki(double *otvet)
{
if((*leks == '(')) {
next_leks();
slagaemwe(otvet);
if(*leks != ')')
oshibka(1);
next_leks();
}
else
obr(otvet);
}
void obr(double *otvet)
{
if(leks_type == NOMER) {
*otvet = atof(leks);
next_leks();
return;
}
oshibka(0);
}
void next_leks()
{
char *vr;
leks_type = 0;
vr = leks;
*vr = '\0';
if(!*vwr) return;
while(isspace(*vwr)) vwr++;
if(strchr("+-*/=()", *vwr)){
leks_type = RAZDELITEL;
*vr++ = *vwr++;
}
else if(isdigit(*vwr)) {
while(!razd(*vwr)) *vr++ = *vwr++;
leks_type = NOMER;
}
oshibka(0);
*vr = '\0';
}
int razd(char c)
{
if(strchr(" +-/*=()", c) )
return 1;
return 0;
}
void oshibka(int er)
{
static char *k[]= {
"Oshibka sintaksisa",
"Disbalans skobok",
"Otsutstvuet vwragenie",
"Na nul delit nelzj"
};
printf("%s\n", k[er]);
}
int main(int argc, char argv[])
{
double otvet;
vwr = argv[1];
input(&otvet);
printf("Otvet: %.2f\n", otvet);
return 0;}