Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
TSPP.doc
Скачиваний:
11
Добавлен:
19.09.2019
Размер:
146.43 Кб
Скачать

Код программы Программа 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);

}

////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]