
- •Список требований заказчика
- •Программа-генератор
- •Программа-вычислитель
- •Функциональная спецификация Программа-генератор polgen.Exe
- •Программа-вычислитель polsolve.Exe
- •Проектная спецификация Программа-генератор polgen.Exe
- •Программа-вычислитель polsolve.Exe
- •Эксплуатационная документация к программе-генератору polgen.Exe
- •К программе-вычислителю polsolve.Exe
- •Код программы Программа polgen.Exe Файл maincode.Cpp
- •Программа polsolve.Exe Файл maincode.Cpp
Код программы Программа polgen.Exe Файл maincode.Cpp
#include <iostream>
#include <string>
#include <deque>
#include <sstream>
#include <assert.h>
#include <bitset>
#include <iterator>
using namespace std;
//ограничение на максимальное количество переменных.
//сделано исключительно для bitset, который не может быть динамическим
const int maxVariableCount = 8;
struct dcell
{
string value;
bool isOperand;
};
string parseargs (char *args[], int argcount);
bool checkparams (string argarr, int argcount);
bool checkfunct (string str, int argcount);
deque<string> buildSDNF (string funct, string argarr);
void toNORbase (deque<string> &mydeq);
void main (int argc, char* argv[])
{
if (argc == 1)
{
cerr << "You must specify variable names in parameters!\n";
assert ( argc > 1 );
}
string inputfunct;
::getline (cin, inputfunct);
string argarr = parseargs (argv, argc);
if (checkparams(argarr, argc) && checkfunct (inputfunct, argc))
{
deque<string> mydeq = buildSDNF (inputfunct, argarr);
//copy (mydeq.begin(), mydeq.end(), ::ostream_iterator<string>(cout, " "));
//cout << endl;
toNORbase (mydeq);
copy (mydeq.begin(), mydeq.end(), ::ostream_iterator<string>(cout, " "));
//cout << endl;
}
else
{
assert(0);
}
system("pause");
}
string parseargs (char *args[], int argcount)
{
//vars - строка с именами переменых
string vars;
//записываем аргументы (кроме нулевого) в string-переменную для последующего анализа
for (int i = 1; i <= argcount - 1; ++i)
{
for (size_t j = 0; j + 1 <= ::strlen(args[i]); ++j)
vars.push_back(args[i][j]);
vars.push_back(' ');
}
vars.pop_back();
return vars;
}
bool checkparams (string argarr, int argcount)
{
bool checkresult = true;
string tempstr;
::stringstream mystr (argarr);
int count = 0;
while (mystr >> tempstr && checkresult)
{
count++;
if (tempstr.find_first_of("`~!@#$%^&*()-_=+\\") != string::npos)
{
cerr << "Inappropriate variable name. Should consist of a letter with or without a number\n";
checkresult = false;
}
assert (count <= ::maxVariableCount);
}
return checkresult;
}
bool checkfunct (string funcstr, int argcount)
{
bool checkresult = true;
//сколько должно быть значений функции во входном векторе
//двойка в степени количества переменных
int valuecount = 2 << (argcount - 2);
if (funcstr.length() != valuecount)
{
cerr << "Function doesn't match variable count!\n";
checkresult = false;
}
if (funcstr.find_first_not_of("10") != string::npos)
{
cerr << "Function should be bool, i.e. consisting of 1 and 0\n";
checkresult = false;
}
assert (checkresult);
return checkresult;
}
deque<string> buildSDNF (string funct, string argarr)
{
deque<string> mydeq;
deque<string> vararr;
string temp;
::stringstream mysstr (argarr);
while (mysstr >> temp)
vararr.push_front(temp);
//bitset в данном случае показался удобным, однако в STL он не может быть динамическим
bitset<::maxVariableCount> valuesNow;
int i;
bool notFirstDiz = false;
for (i = 0; i + 1 <= funct.length(); i++)
{
//в процессе пробега натыкаемся на строку, в которой функция равна 1
//эта строка будет участвовать в СДНФ в качестве дизъюнкта
if (funct[i] == '1')
{
valuesNow = i;
//пробегаемся по битам, чтобы добавить в дэк дизъюнкт, состоящий из конъюнкций переменных или их отрицаний
for (int k = 0; k + 1 <= vararr.size(); k++)
{
//запихиваем рассматриваемую переменную в дэк
mydeq.push_back(vararr[k]);
//смотрим, нужно ли брать её с отрицанием
if (valuesNow[k] == 0)
mydeq.push_back("~");
//если рассматриваемая переменная не первая, то надо поставить конъюнкцию с предыдущими
if (k != 0)
mydeq.push_back("&");
}
//после построения дизъюнкта надо добавить дизъюнкцию с остальными, но если он не самый первый
if (notFirstDiz)
mydeq.push_back("|");
notFirstDiz = true;
}
}
return mydeq;
}
void toNORbase (deque<string> &mydeq)
{
deque<dcell> retdeq;
//в качестве элемента нового дэка будет структура, в которой кроме string есть булевая переменная
//булевая переменная будет очень полезна при конвертации польской нотации
//Поэтому скопируем элементы старого дэка в новый
dcell tempel;
tempel.isOperand = false;
::stringstream myss;
copy (mydeq.begin(), mydeq.end(), ::ostream_iterator<string>(myss, " "));
while (myss >> tempel.value)
{
tempel.isOperand = false;
//если это операнд/переменная, то ставим ему флаг
if (tempel.value.find_first_of("&|~") == string::npos)
tempel.isOperand = true;
retdeq.push_back(tempel);
}
// //конвертируем
bool flag = true;
int i;
string resultstr;
while (retdeq.size() >= 3 && flag)
{
flag = false;
i = 0;
while (i + 3 <= retdeq.size() && retdeq.size() >= 3)
{
resultstr.erase();
//если мы нашли отрицание операнда
if (retdeq[i].isOperand && retdeq[i + 1].value == "~")
{
resultstr = retdeq[i].value + " 0 _";
retdeq[i + 1].value = resultstr;
retdeq[i + 1].isOperand = true;
retdeq.erase(retdeq.begin() + i);
if (i != 0)
i--;
flag = true;
}
else if (retdeq[i].isOperand && retdeq[i + 1].isOperand && retdeq[i + 2].value.find_first_not_of("&|") == string::npos)
{
switch (retdeq[i + 2].value[0])
{
case '&':
resultstr = retdeq[i].value + " 0 _ " + retdeq[i + 1].value + " 0 _ _";
break;
case '|':
resultstr = retdeq[i].value + " " + retdeq[i + 1].value + " _ 0 _";
break;
default:
//Что-то пошло не так, других элементов быть не должно
assert(0);
}
retdeq[i + 2].value = resultstr;
retdeq[i + 2].isOperand = true;
retdeq.erase(retdeq.begin() + i, retdeq.begin() + i + 2);
flag = true;
}
else
i++;
}
}
assert (retdeq.size() == 1);
resultstr = retdeq[0].value;
mydeq.clear();
string tempstring;
::stringstream mysstr (resultstr);
while (mysstr >> tempstring)
mydeq.push_back(tempstring);
}
////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////