Разработка утилиты командной строки

Автор работы: Пользователь скрыл имя, 25 Марта 2012 в 21:52, курсовая работа

Описание

Разработать калькулятор для командной строки – expr_stud, выполняющий вычисление арифметического выражения, переданного в качестве входных данных. Арифметическое выражение записывается следующим образом: (ApB), где А – левый операнд, В – правый операнд, p – арифметическая операция. А и В – вещественные числа, р=+|-|*|/.

Работа состоит из  1 файл

курсач.doc

— 60.50 Кб (Скачать документ)


Федеральное агентство связи

Государственное образовательное учреждение высшего профессионального образования

«Сибирский государственный университет телекоммуникаций и информатики»

 

 

 

 

 

 

 

Факультет ИВТ

 

 

 

 

Кафедра вычислительных систем

 

 

 

 

 

 

Курсовой проект

По теме «Разработка утилиты командной строки»

 

 

 

 

 

 

 

Выполнил:

 

студент гр. ВМ-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=='+'||*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=='*'||*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;}

 



Информация о работе Разработка утилиты командной строки