Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 04.09.2014, 19:22   #1
flax
Новичок
Джуниор
 
Регистрация: 27.11.2008
Сообщений: 1
По умолчанию парсер мат строк

Добрый день
возник следующий вопрос, в программировании не сильно большой гуру
пошел на собеседование , дали тестовое задание парсер мат выражений, написал все работает , в фидбеке написали что код ужасный
могли бы подсказать где ужастность?

main.cpp
Код:
#include <iostream>
#include <string>
#include <conio.h>
#include "parser.h"

using namespace std;



void main()
{
	char str[64];
	Parser pr;

	while(1)
	{
		system("CLS");
		cout<<"Input math expr:\t";
		cin>>str;
		
		try
		{
			cout<<str<< " = "<<pr.calculateExp(str)<<endl;
		}
		catch (char* e)
		{
			cout<<e<<endl;
		}

		cout<<"Would you like to continue? (y/n)\t";
		if (getch()==(int)'Y')
			continue;
		else break;
	}

	cout<<endl;
}

Parser.h
Код:
#include <iostream>
using namespace std;

const int iSize = 20;


template <class T> 
class MyStack
{
	
	T m_stackData[iSize];
	int m_iStackSize;
	friend class Parser;

	
	//friend class Parser;

	void push(T x)
	{
		if (m_iStackSize<iSize)
			m_stackData[m_iStackSize++] = x;
	}

	T pop ()
	{
		if (m_iStackSize>0)
			return m_stackData[--m_iStackSize];
		else return -1;
	}

	T top ()const
	{
		if (m_iStackSize>0)
			return m_stackData[m_iStackSize-1];
		else return -1;
	}

public:
	MyStack():m_iStackSize(0){}
};


class Parser
{
	int priorityOperation(char c);
	void make_poland(char * str_expr, char * Output);
	double calculateResult(const char *strPoland);

public:

	double calculateExp( char *strMathExpr);
	
		

};
Parser.cpp
Код:
#include "parser.h"


int Parser::priorityOperation(char c)
{      
	switch(c) 
	{
		case '(': return 1;
		case '+': case '-': return 2;
		case '*': case '/': return 3;
		default: return 0;
	}
}

void Parser::make_poland(char * strInputExpr, char * strOutput )
{
	int iOperation = 0;
	MyStack <char> stChar;
	int iCountSkobki = 0;
	char curc;

	if (strlen(strInputExpr)!=0)
	{
		while (isspace(*strInputExpr))
			*strInputExpr++;

		if (!isdigit(*strInputExpr) && *strInputExpr!='(')
			throw (char*)"Incorect input string";
		else
		{
			while(*strInputExpr!='\0')
			{
				if (isdigit(*strInputExpr) || *strInputExpr=='.')
				{
					*strOutput++=*strInputExpr;
					iOperation=0;
				}
				else
				{
					*strOutput++=' ';

					switch(*strInputExpr)
					{
					case '(':
						stChar.push(*strInputExpr);
						iCountSkobki++;
						iOperation = 0;
						break;
					
					case '+': case '-': case '*': case '/':
						{
							if (strlen(strInputExpr) == 0)
								throw (char *)"syntaxes error";

							if (!iOperation)
							{
								iOperation = 1;

								while(priorityOperation(*strInputExpr)<=priorityOperation(stChar.top()))
									*strOutput++ = stChar.pop();

								if (priorityOperation(*strInputExpr)>priorityOperation(stChar.top()))
									stChar.push(*strInputExpr);
							}
						}
						break;

					case ')':
						while ((curc=stChar.pop())!='(' && iCountSkobki>0)
							*strOutput++ = curc;
						iCountSkobki--;

						break;
					}
				}
				*strInputExpr++;
			}
		}
	}
	else throw(char*)"input string is empty";

	while(stChar.top() != -1)
		*strOutput++=stChar.pop();
	
	if(iCountSkobki) 
		throw (char*)"incorrect count brackets"; 

	*strOutput = '\0';

}

double Parser::calculateResult(const char *strPoland)
{
	string str;
	MyStack<double> val_stack;
	char* err;
	double n1, n, res = 0;


	for (size_t i=0;i<strlen(strPoland);i++)
	{
		if(strPoland[i] == ' ')continue;
		
		while(i<strlen(strPoland) && (isdigit(strPoland[i]) || strPoland[i]=='.'))
		{
			str += strPoland[i++];
		}

		if(str.length()!=0) 
		{
			val_stack.push(strtod(str.c_str(), &err));
			str.clear();
			if(i >= strlen(strPoland))
				break;                 //end of the input string

			if(strPoland[i] == ' ') continue;

		}

		n = val_stack.pop();         //the first current number
		n1 = val_stack.pop();        //the second current number

		switch(strPoland[i])
		{
		case '+': res = n + n1; break;
		case '-': res = n1 - n; break;
		case '*': res = n * n1; break;
		case '/': res = n1 / n; break;
		default: throw (char*)"error";
		}
		val_stack.push(res);

	}

	return val_stack.pop();
}

double Parser::calculateExp( char *strMathExpr)
{
	char strPoland[64];
	make_poland(strMathExpr,strPoland);

	return calculateResult(strPoland);
}
flax вне форума Ответить с цитированием
Старый 04.09.2014, 21:33   #2
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

Цитата:
в фидбеке написали что код ужасный
могли бы подсказать где ужастность?
Да расслабься, они просто уже взяли другого кодера, и не знали как тебе об этом сообщить

А вообще лично мне не понравилась бы make_poland(). Но только потому что выглядит сложно - т.е. если ты начнешь проект, потом вдруг уволишься, а твои коды придется кому-то дорабатывать, бедный доработчик может моск сломать в условиях кратчайших сроков, поставленных заказчиком.
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 04.09.2014, 21:37   #3
challengerr
Участник клуба
 
Аватар для challengerr
 
Регистрация: 30.07.2008
Сообщений: 1,603
По умолчанию

Абстракция и реализация слабая Где-то на форуме я видел крутую реализацию парсера: то ли тут, то ли на киберфоруме. Проблемы кода:
1. размер стека 20. Фиксированный размер это неудачное архитектурное решение. Должен быть построен конечный автомат. А если там буде 5+5+.. + 5 миллион раз с миллионом пар скобок, ваш стек сразу сломается?
2.фиксированная длина строки ввода это неправильно.

При разборе выражения, нужно строить дерево синтаксического разбора и использовать восходящий или нисходящий разбор - в вашей программе не построено дерево разбора..
"SPACE.THE FINAL FRONTIER.This's a voyage of starship Enterprise. It's 5-year mission to explore strange new worlds,to seek out new life and civilizations,to boldly go where no man has gone before"

Последний раз редактировалось challengerr; 04.09.2014 в 21:48.
challengerr вне форума Ответить с цитированием
Старый 04.09.2014, 22:08   #4
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

Цитата:
А если там буде 5+5+.. + 5 миллион раз с миллионом пар скобок, ваш стек сразу сломается?
Цитирую автора:
Цитата:
дали тестовое задание парсер мат выражений
Соответственно автор написал демо версию.
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 04.09.2014, 22:22   #5
challengerr
Участник клуба
 
Аватар для challengerr
 
Регистрация: 30.07.2008
Сообщений: 1,603
По умолчанию

Как это делается правильно , код в теме http://www.cyberforum.ru/cpp-beginne...ead671878.html , сообщение от 16.10.2012 21:40


Код:
 /* 
 * Grammar
 * 
 * <expr> ::=
 *      <expr> '+' <term>
 * |    <expr> '-' <term>
 * |    <term>
....
"SPACE.THE FINAL FRONTIER.This's a voyage of starship Enterprise. It's 5-year mission to explore strange new worlds,to seek out new life and civilizations,to boldly go where no man has gone before"
challengerr вне форума Ответить с цитированием
Старый 05.09.2014, 00:04   #6
_Bers
Старожил
 
Регистрация: 16.12.2011
Сообщений: 2,329
По умолчанию

Цитата:
Сообщение от challengerr Посмотреть сообщение
Как это делается правильно , код в теме http://www.cyberforum.ru/cpp-beginne...ead671878.html , сообщение от 16.10.2012 21:40


Код:
 /* 
 * Grammar
 * 
 * <expr> ::=
 *      <expr> '+' <term>
 * |    <expr> '-' <term>
 * |    <term>
....
Версия ТС мне нравится больше.
_Bers вне форума Ответить с цитированием
Старый 05.09.2014, 05:45   #7
rrrFer
Санитар
Старожил
 
Аватар для rrrFer
 
Регистрация: 04.10.2008
Сообщений: 2,577
По умолчанию

challengerr
Ты бы на сайбер не ссылался. ИМХО это не только мне глаз режет. Ну можешь попробовать на сайбере ссылку на программерзфорум оставить. Пару раз попробуешь, потом бан получишь (я получил).
Тем более код там тоже не очень приятный.

ТС, лично мне не нравится твой стек. Не понятно зачем это велосипед, когда стек есть в стандартной библиотеке. Тем более твой велосипед снаружи выглядит как велосипед, а внутри у него самокат (стек не должен ломаться при добавлении 21 элемента, поэтому он обычно как динамический список строится, а у тебя внутри массив из 20 элементов).

Если уж ты сделал свой стек, да он у тебя шаблонный, то он должен работать нормально и с любыми типами. Я беру вот этот кусок только:
Код:
T top ()const
	{
		if (m_iStackSize>0)
			return m_stackData[m_iStackSize-1];
		else return -1;
	}
Что если тип элементов стека не кастуется в int? - return -1 вызывает конструктор T(int).

Я особо не вчитывался, но вцелом вроде бы сам парсер выглядит симпатично.
rrrFer вне форума Ответить с цитированием
Старый 05.09.2014, 06:05   #8
challengerr
Участник клуба
 
Аватар для challengerr
 
Регистрация: 30.07.2008
Сообщений: 1,603
По умолчанию

Цитата:
Сообщение от rrrFer Посмотреть сообщение
challengerr
Ты бы на сайбер не ссылался. ИМХО это не только мне глаз режет. Ну можешь попробовать на сайбере ссылку на программерзфорум оставить. Пару раз попробуешь, потом бан получишь (я получил).
Тем более код там тоже не очень приятный.
В 2013 я там потерял эккаунт, и после регистрации нового эккаунта получил бан. Ссылки на другие форумы они вырезали.
"SPACE.THE FINAL FRONTIER.This's a voyage of starship Enterprise. It's 5-year mission to explore strange new worlds,to seek out new life and civilizations,to boldly go where no man has gone before"
challengerr вне форума Ответить с цитированием
Старый 05.09.2014, 10:18   #9
rrrFer
Санитар
Старожил
 
Аватар для rrrFer
 
Регистрация: 04.10.2008
Сообщений: 2,577
По умолчанию

Цитата:
Ссылки на другие форумы они вырезали.
Они вообще внешние ссылки вырезали, даже неактивные ссылки. На мой блог тоже обещали вырезать (хотя не я их там оставил, но ко мне претензии были).
А тут все ссылки активные и без nofollow/noindex. Жирно сильно сайберу, я считаю.
rrrFer вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Мат плата aman777 Компьютерное железо 0 06.05.2014 14:18
Для матрицы из 3 столбцов и 7 строк отпечатать номера тех строк, в которых третий элемент больше суммы двух других элементов строк abramov Помощь студентам 2 03.12.2013 10:15
МАТ. ЛИНГВИСТИКА!!! ...Ou... Фриланс 0 24.04.2012 19:44
МАТ. ЛИНГВИСТИКА!!! ...Ou... Помощь студентам 1 18.04.2012 09:57
Мат програмка с росдела мат логики. Sheva777 Помощь студентам 4 23.03.2012 23:48