Консультация № 191339
12.09.2017, 16:31
0.00 руб.
0 46 0
Здравствуйте! У меня возникли сложности с таким вопросом:
Помогите пожалуйста решить одну из двух задач. Написать надо на языке Си.
1. Программа должна строить полную таблицу истинности введённой формулы.
2. Программа должна отыскивать все интерпретации на которых введённая формула принимает ложное значение.

Обсуждение

давно
Посетитель
7438
7205
13.09.2017, 10:08
общий
Адресаты:
Ну это уже Вам и Вашему преподавателю решать.
Мое решение, действительно, нетривиальное.
Если Вы только начали изучать Си, то решение вряд ли Вам подойдет.
Полагаю, преподаватель быстро раскусит, что это не Вы писали...
Посоветуйтесь с преподавателем, что, конкретно, должна делать программа.

Впрочем, для общего развития, программка даже очень полезна
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
давно
Посетитель
401316
23
13.09.2017, 11:35
общий
Си мы изучаем пол года
И преподаватель говорил что то про этот метод
Но для развития конечно очень полезно )
давно
Академик
20764
1861
13.09.2017, 11:47
общий
Цитата: Лысков Игорь Витальевич
Впрочем, для общего развития, программка даже очень полезна

Не очень полезна.
Общепринятая реализация грамматического разбора весьма компактна и изящна. Но теория там неочевидная. Тут лучше как раз теорию поверхостно почитать, а не разбираться в коде, тем более написаным "в один кирпич".
Только это интересно в основном специалистам по матлингвистике и писателям компиляторов. Для практиков есть генераторы кода прямо по формальному описанию грамматики с включёнными кусками кода, реализующими свёртки.
давно
Посетитель
7438
7205
13.09.2017, 12:02
общий
13.09.2017, 12:03
Адресаты:
Я с Вами не согласен. Можно пользоваться готовыми решениями, да. Но понимать, как это работает, никогда не вредно.
Тем более, в коде можно увидеть и научиться некоторым другим полезным "штучкам". Речь же идет об обучении программированию,
а не о выполнении конкретной работы.
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
давно
Посетитель
401316
23
16.09.2017, 02:05
общий
Адресаты:
Извините
А вы не могли бы подробнее рассказать как работает эта операция сдвига
Саму операцию я знаю
Но не понимаю какую матрицу она делает, а точнее как
давно
Посетитель
401316
23
16.09.2017, 12:37
общий
Адресаты:
И кстати она не правильно считает
давно
Посетитель
7438
7205
18.09.2017, 10:29
общий
Адресаты:
Не исключено. Программка, в общем-то, писалась на скорую руку.
Приведите пример, на котором неправильно считает. Было бы неплохо исправить.
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
давно
Посетитель
401316
23
18.09.2017, 10:51
общий
Адресаты:
Смотрите вот например если строк 2
То она выведет порвано сначала 0 потом 1
Допустим 8 строк она выведет сначала 4 нуля а потом 4 единицы
давно
Посетитель
401316
23
18.09.2017, 10:52
общий
Адресаты:
ОПЗ выводит правильно только не правильно сам ответ функции выводит
давно
Посетитель
7438
7205
18.09.2017, 11:02
общий
Адресаты:
если строк 2
То она выведет порвано сначала 0 потом 1
Допустим 8 строк она выведет сначала 4 нуля а потом 4 единицы

Честно говоря, не понял, как это. Как это 2 строки, и как порвано выведет
Предполагалось, что строка будет одна.
Нарисуйте буковками, что было понятно, о чем речь
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
давно
Посетитель
401316
23
18.09.2017, 11:07
общий
Адресаты:
A&B
A B F
0 0 0
0 1 0
1 0 1
1 1 1
Или
(A&B)|(C>B)
A B C F
0 0 0 0
0 0 1 0
0 1 0 0
0 1 1 0
1 0 0 1
1 0 1 1
1 1 0 1
1 1 1 1
давно
Посетитель
7438
7205
18.09.2017, 11:32
общий
Адресаты:
Вот мои результаты:

Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
давно
Посетитель
401316
23
18.09.2017, 11:34
общий
Адресаты:
Очень странно) ладно дома ещё раз проверю
давно
Посетитель
7438
7205
18.09.2017, 11:40
общий
18.09.2017, 11:41
Адресаты:
Кстати, я понял, что имелось в виду, когда говорилось "выведет сначала 4 нуля а потом 4 единицы"
Выводило первый аргумент. Но почему, совершенно непонятно...
Если будет то же самое, киньте мне полученный exe-файл (загрузите в "мои файлы" на главной странице и дайте ссылку). Я посмотрю изнутри
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
давно
Посетитель
7438
7205
18.09.2017, 11:47
общий
Адресаты:
А вы не могли бы подробнее рассказать как работает эта операция сдвига
Саму операцию я знаю
Но не понимаю какую матрицу она делает, а точнее как
Это до сих пор непонятно?
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
давно
Посетитель
7438
7205
18.09.2017, 12:00
общий
18.09.2017, 12:05
Адресаты:
В двух словах, была использована двойная природа бит:
1) биты, как самостоятельная единица информации;
2) биты в совокупности являются неким числом.
Другими словами, разные наборы значений переменных являются последовательными числами от 0 до 2N - 1, где N - количество переменных.
Перебирая числа от 0 до 2N - 1, мы получим все наборы.
А взяв соответствующие биты из числа, получим значения логических переменных для конкретного набора.
А вот чтобы получить значение бита и используем маску, как сдвиг единицы на соответствующее место.
Проверив на 0 конъюнкцию маски и числа, получим значение соответствующей переменной.

Там есть небольшой момент: первая переменная задается старшим используемым битом,
поэтому в программе производится небольшое преобразование.
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
давно
Посетитель
401316
23
18.09.2017, 22:25
общий
Адресаты:
https://rfpro.ru/upload/10594
Прикрепленные файлы:
c8b8d57545a95bca5c2440bfa7394725.png
давно
Посетитель
401316
23
20.09.2017, 12:12
общий
Адресаты:
Вы посмотрели файл ?
давно
Посетитель
7438
7205
20.09.2017, 12:21
общий
Адресаты:
Программа не запускается...
Ее размер точно равен 71680 байт?
Если судить по заголовку, ее размер должен быть порядка 163840
Киньте на почту lyskov@gmail.com
Только переименуйте, например, в *.eee
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
давно
Посетитель
401316
23
20.09.2017, 14:00
общий
Адресаты:
Отправила
давно
Посетитель
401316
23
20.09.2017, 14:49
общий
Адресаты:
Теперь загрузилось?
давно
Посетитель
7438
7205
20.09.2017, 16:27
общий
Адресаты:
Все равно, не работает... Надо было собрать в один exe...

Вроде нашел в Инете все требуемые dll, но все равно VCRUNTIME140D.dll не та, не находится некая функция, не факт, что одна
Так что, киньте, наверное, мне еще VCRUNTIME140D.dll (найдите ее на своем диске)
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
давно
Посетитель
7438
7205
20.09.2017, 16:34
общий
Адресаты:
Лучше давайте упакуйте проект в архив и киньте мне.
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
давно
Посетитель
401316
23
20.09.2017, 16:43
общий
Адресаты:
Хорошо вечером кину
давно
Мастер-Эксперт
425
4118
21.09.2017, 07:36
общий
Адресаты:
Цитата: Лысков Игорь Витальевич
Вроде нашел в Инете все требуемые dll, но все равно VCRUNTIME140D.dll не та, не находится некая функция, не факт, что одна
Так что, киньте, наверное, мне еще VCRUNTIME140D.dll (найдите ее на своем диске)

А не может быть такого, что у Вас разрядности программы и DLL разные?
Об авторе:
Я только в одном глубоко убеждён - не надо иметь убеждений! :)
давно
Посетитель
401316
23
21.09.2017, 08:30
общий
Адресаты:
Я думала об этом
Но что в этом случае делать?:с
Как исправить что бы правильно работала
давно
Мастер-Эксперт
425
4118
21.09.2017, 09:02
общий
Адресаты:
Цитата: mir97_00
Но что в этом случае делать?:с
Как исправить что бы правильно работала

Даже не знаю, понравится ли Вам мой ответ...
Не использовать программное обеспечение тех фирм, которые озабочены только своими прибылями.
Для Windows можно использовать C/C++ либо проекта MinGW, либо проетка Cygwin. И тот и другой - попытка переложить на рельсы Windows кучу полезных программ из Linux, в том числе и набор компиляторов GCC (это Си, Си++, Ада, Ди, Фортран, Го, может ещё кого забыл ). Их отличия - MinGW для русского языка использует ту же кодировку, что и Windows, а в Cygwin'е - всё как в Линукс, кодировка UTF8 (на англицкий язык UTF8 никак не влияет, только на другие языки).
Самая главная проблема для тех, кто программировал только в Windows - для этого набора компиляторов разработчиками не предусмотрено никакого графического IDE, приходится пользоваться командной строкой, многих это приводит в панический ужас... Правда в интернете можно найти для них IDE'шки, но это никакие не Visual - только под тексты программ, с цветовыделением ключевых слов и кнопками компиляции\запуска. Зато если в конторе, где Вы работаете\собираетесь работать выйдет в пятницу срочный приказ "До понедельника всем перейти на открытую операционную систему Linux" (как это, к примеру было в службе судебных приставов и ещё кое-каких госконторах), Вас это ни капли не смутит - Вы будете единственным человеком, который умеет там программировать. А это сразу, как минимум, должность замдиректора по новым информационным технологиям и возможность финансово не напрягаясь четыре раза в год ездить отдыхать на Майорку или в Малагу.
Об авторе:
Я только в одном глубоко убеждён - не надо иметь убеждений! :)
давно
Посетитель
401316
23
22.09.2017, 13:50
общий
Адресаты:
Я решила переделать операции, они заработали но только когда я считаю две буквы типа (A&B) когда я начинаю считать большие формулы типа ( (A&B)|(C>B) ) то он не так начинает считать:c
помогите исправить
что там не так?
Код:
#include "stdafx.h"
#include "stdio.h"
#include <string>
#include <iostream>
#include <stdlib.h>
#include <conio.h>
#include <cstringt.h>
#define nn 10

struct code_op //структура для хранения допустимых символов операций
{
char symbol; //символ
char priority; //приоритет операции
};
//коды операций, как индекс в массиве codes
#define SPACE_CODE 0
#define OR_CODE 1
#define AND_CODE 2
#define NOT_CODE 3
#define XOR_CODE 4
#define IMP_CODE 5
#define EQU_CODE 6
#define OPEN_CODE 7
#define CLOSE_CODE 8
#define MAX_CODE 9
code_op codes[MAX_CODE] =
{
{ ' ', 0 }, //разделитель (игнорируется)
{ '|', 2 }, //или
{ '&', 3 }, //и
{ '~', 7 }, //отрицание
{ '+', 4 }, //исключающее или
{ '>', 5 }, //импликация
{ '=', 6 }, //эквиваленция
{ '(', 1 }, //открывающая скобка
{ ')', 1 } //закрывающая скобка
};
int CmpOp(char op) //поиск кода в массиве codes
{
int i;
for (i = 0; i<MAX_CODE; i++)
{
if (codes[i].symbol == op)
return i; //возвращаем индекс
}
return -1; //или -1, если не найдено
}
//построение обратной польской нотации с проверкой на корректность.
//параметры:
//str - входная строка с обычной нотацией
//opn - выходная строка с обратной польской нотацией
//возвращается количество переменных или -1, если любая ошибка
int OPN(char *str, char *opn)
{
char *temp = opn; //сохраним адрес выхожной строки для окончательной проверки
char stack[nn]; //стек, растет снизу вверх
int top = 0; //вершина стека
int cnt = 0; //количество аргументов
int check; //переменная для последней проверки корректности
char code; //текущий символ
for (code = *(str++); code; code = *(str++)) //по всем символам строки
{
if ((code >= 'A') && (code <= 'Z')) //заглавные буковки переменных
code += 0x20; //превратим в малые!
if ((code >= 'a') && (code <= 'z')) //переменные ?
{
*(opn++) = code; //пишем в выходную строку
if (cnt < (code - 'a' + 1)) //одновременно ищем количество переменных,
cnt = code - 'a' + 1; // как максимальный используемый код
while (top && (stack[top - 1] == NOT_CODE)) //если перед этим было отрицание
*(opn++) = stack[--top]; //извлечем из стека в выходную строку
}
/*else if ((code == '1')||(code == '0')) //явные константы
{
*(opn++) = code; //пишем в строку, как переменные
while (top && (stack[top-1] == NOT_CODE)) //если перед этим было отрицание
*(opn++) = stack[--top]; //извлечем из стека в выходную строку
}*/
else
{
code = CmpOp(code); //проверим на допустимый код операции, возвращается индекс в массиве
if (code == SPACE_CODE)
continue; //пробелы игнорируем
else
{
if (code == OPEN_CODE) //открывающая скобка?
stack[top++] = code; //пишем в стек
else if (code == CLOSE_CODE)//закрывающая скобка?
{
if (top) //есть что-то в стеке?
{
for (code = stack[--top]; code != OPEN_CODE; code = stack[--top])
{ //пока не дойдем до открывающей скобки
*(opn++) = code;//извлекаем код операции в выходную строку
if (top == 0) //проверим на парность скобок
return -1; //если дошли до 0, значит открывающей скобки не было, ошибка!
}
while (top && (stack[top - 1] == NOT_CODE)) //извлечем из стека отрицания,
*(opn++) = stack[--top]; // которые перед открывающей скобкой
}
else
return -1; //в стеке ничего нет - ошибка!
}
else //код операции
{ //проверим приоритет операций
if (top != 0) //в случае, если что-то есть в стеке
{
if (stack[top - 1] != NOT_CODE) //кроме отрицания!
//если приоритет новой операции меньше или равен
//приоритета операции в стеке
if (codes[code].priority <= codes[stack[top - 1]].priority)
*(opn++) = stack[--top]; //то извлечем код операции из стека
}
stack[top++] = code; //запишем новый код в стек
}
}
}
}
//извлечем из стека операции
while (top) //пока что-то там есть
{
if (stack[top - 1] != OPEN_CODE) //но никак не открывающая скобка!
*(opn++) = stack[--top];
else
return -1; //( - ошибка!
}
*opn = 0; //закроем строку нулем
//проверим строку на соответствие операций и переменных!
//чтобы у операций (кроме отрицания) было два аргумента!
check = 0; //счетчик аргументов
for (code = *(temp++); code; code = *(temp++))//по всем символам opn
{
if (code < MAX_CODE) //операция?
{
if (code != NOT_CODE) //не отрицание, для него надо один аргумент
{
check--; //операции из двух аргументов получают один, т.е. уменьшаем на 1
}
}
else
check++; //для аргументов увеличиваем на 1
}
if (check != 1) //в итоге должны получить 1! Последний аргумент и будет результатом
return -1; //иначе - ошибка!
return cnt; //возвращаем количество переменных
}
void print_opn(char *opn) //вывод строки ОПН
{
char ch;
printf("OPN = ");
for (ch = *(opn++); ch; ch = *(opn++)) //по всем символам строки
{
if (ch >= 'a') //переменную
printf("%c", ch); //выводим, как ее саму
else
printf("%c", codes[ch].symbol); //операцию, как символ из массива (в строке ОПН лежит индекс)
}
printf("\n");
}
void print_header(int cnt) //заголовок таблицы истинности, параметр - число переменных
{
int i;

for (i = 0; i<cnt; i++) //для всех
printf("%c ", i + 'a'); //выводим буковки, разделяя пробелом
printf("f\n"); //f, как идентификатор значения функции
}
//расчет функции для конкретного набора значений переменных
//значения задаются битами в параметре row, которые можно рассматривать, как номер строки
//параметры:
// opn - строка обратной польской нотации
// row - порядковый номер строки
// cnt - количество переменных
//возвращает значение функции на конкретном наборе переменных
int F(char* opn, int row, int cnt)
{
char res(0);
bool first(false), chet(false);
char stack[nn]; //стек для отработки ОПН
int top = 0; //вершина стека, растет вверх
char ch;
for (ch = *(opn++); ch; ch = *(opn++)) //по всем символам ОПН
{
if (ch >= 'a') //переменная?
//пишем в стек значение соответствующего бита в row
//номер переменной (0,1,...) получаем, как ch-'a'
//из-за того, что младший бит справа,
//перевернем номер относительно количества переменных
//т.е. получим cnt-ch+'a'-1
//тогда маска бита получается 1<<(cnt-ch+'a'-1)
//в стек получим или 1, или 0, как результат сравнения не 0
stack[top++] = (char)(((1 << (cnt - ch + 'a' - 1)) & row) != 0);
else
switch (ch) //для операций
{ //берем два значения (или одно для отрицания) из стека,
// делаем операцию и отправляем обратно в стек
case OR_CODE:
for (int i(top - 1); i >= 0; --i)
if ((stack[i] == 1) || (stack[i] == 0))
if (!first) {
res = stack[i];
first = true;
}
else
res |= stack[i];
//stack[top++] = stack[--top] | stack[--top]; //или
break;
case AND_CODE:
for (int i(top - 1); i >= 0; --i)
if ((stack[i] == 1) || (stack[i] == 0))
if (!first) {
res = stack[i];
first = true;
}
else
res &= stack[i];
//stack[top] = stack[top-1] & stack[top-2]; //и
break;
case NOT_CODE:
for (int i(top - 1); i >= 0; --i)
if ((stack[i] == 1) || (stack[i] == 0))
if (!first) {
res = 1 ^ stack[i];
first = true;
}
else
res = 1 ^ stack[i];
//stack[top++] = 1 ^ stack[--top]; //отрицание, как исключающее или с 1
break;
case XOR_CODE:
for (int i(top - 1); i >= 0; --i)
if ((stack[i] == 1) || (stack[i] == 0))
if (!first) {
res = stack[i];
first = true;
}
else
res ^= stack[i];
//stack[top++] = stack[--top] ^ stack[--top]; //исключающее или
break;
case IMP_CODE:
for (int i(top - 1); i >= 0; --i)
if ((stack[i] == 1) || (stack[i] == 0))
if (!first) {
res = stack[i];
first = true;
}
else
if (chet) {
res |= stack[i];
chet = false;
}
else {
res |= (1 ^ stack[i]);
chet = true;
}
//stack[top++] = stack[--top] | (1 ^ stack[--top]); //импликация по формуле a->b=~a|b
break; //сначала достаем второй аргумент!
case EQU_CODE:
stack[top++] = 1 ^ (stack[--top] ^ stack[--top]); //эквиваленция, как отрицание xor
break;
}
}
return res;//stack[top]; //после всех расчетов в вершине стека - результат
}
//расчет и вывод строки таблицы истинности
//параметры:
//ОПН, номер строки, количество переменных
void print_table(char* opn, int row, int cnt)
{
int i;
for (i = 0; i<cnt; i++)
{
printf("%d ", (((1 << (cnt - i - 1)) & row) != 0)); //вывод значений переменных (о маске бита смотри выше)
}
printf("%d\n", F(opn, row, cnt)); //расчет и вывод значения функции
}
int main()
{
char str[256]; //входная строка
char opn[256]; //строка ОПН
int i;
int cnt; //количество переменных
int max; //число строк таблицы истинности
printf("Enter function: ");
std::cin >> str; //вводим строку
if ((cnt = OPN(str, opn))>0) //пребразовываем в ОПН (с проверкой на синтаксис).
{ //одновременно получаем количество переменных
print_opn(opn); //выведем строку ОПН
print_header(cnt); //заголовок таблицы истинности (по кол элементов)
max = 1 << cnt; //количество строк таблицы истинности
for (i = 0; i<max; i++)
print_table(opn, i, cnt); //расчет и вывод очередной строки ТИ
}
else
printf("Syntax error...\n"); //ошибка! Получили cnt=-1
_getch();
return 0;
}


давно
Посетитель
7438
7205
22.09.2017, 14:07
общий
Адресаты:
Хорошо, посмотрю, но чуть позже. Увы, занят...
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
давно
Посетитель
401316
23
07.10.2017, 12:26
общий
Адресаты:
Вы ещё не смотрели ?
Форма ответа