提问人:BraVeHurt 提问时间:5/31/2023 更新时间:5/31/2023 访问量:68
实现逻辑门电路的 C 编程解决方案
Implementing a C programm for logic gates circuit solution
问:
逻辑门电路解决方案
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 10
int myand(int a, int b);
int myor(int a, int b);
int mynand(int a, int b);
int mynor(int a, int b);
int myxor(int a, int b);
typedef int (*CallBack)(int a, int b);
int getinput();
typedef struct function {
CallBack f;
char ch[10];
} MyFunction;
typedef struct gate {
CallBack f;
struct gate * in1 ;
struct gate * in2 ;
} Gate;
Gate * creategate(CallBack f);
int eval(Gate *x);
int main() {
Gate *a_ptr, *a1_ptr, *a2_ptr, *b_ptr, *b1_ptr, *b2_ptr, *c_ptr, *c1_ptr, *c2_ptr, *d_ptr, *e_ptr, *f_ptr;
a_ptr = creategate(mynor);
a1_ptr = creategate(getinput);
a2_ptr = creategate(getinput);
a_ptr->in1 = a1_ptr;
a_ptr->in2 = a2_ptr;
printf("First gate's output: %d\n", eval(a_ptr));
b_ptr = creategate(myand);
b1_ptr = creategate(getinput);
b2_ptr = creategate(getinput);
b_ptr->in1 = b1_ptr;
b_ptr->in2 = b2_ptr;
printf("Second gate's output: %d\n", eval(b_ptr));
c_ptr = creategate(myor);
c1_ptr = creategate(getinput);
c2_ptr = creategate(getinput);
c_ptr->in1 = c1_ptr;
c_ptr->in2 = c2_ptr;
printf("Third gate's output: %d\n", eval(c_ptr));
d_ptr = creategate(mynand);
d_ptr->in1 = a_ptr;
d_ptr->in2 = b_ptr;
printf("Fourth gate's output: %d\n", eval(d_ptr));
e_ptr = creategate(myxor);
e_ptr->in1 = b_ptr;
e_ptr->in2 = c_ptr;
printf("Fifth gate's output: %d\n", eval(e_ptr));
f_ptr = creategate(myor);
f_ptr->in1 = d_ptr;
f_ptr->in2 = e_ptr;
printf("Circuit's output: %d\n", eval(f_ptr));
free(a_ptr);
free(a1_ptr);
free(a2_ptr);
free(b_ptr);
free(b1_ptr);
free(b2_ptr);
free(c_ptr);
free(c1_ptr);
free(c2_ptr);
free(d_ptr);
free(e_ptr);
free(f_ptr);
return 0;
}
int myand (int a, int b) {
return a * b;
}
int myor (int a, int b) {
return a + b>0;
}
int mynand (int a, int b) {
int result = a * b;
if (result == 0) {
result = 1;
}
else {
result = 0;
}
return result;
}
int mynor(int a, int b) {
int result = a + b>0;
if (result == 0) {
result = 1;
}
else {
result = 0;
}
return result;
}
int myxor(int a, int b) {
int a1=0, b1=0;
if (a==0) {
a1=1;
}
else if (a==1) {
a1=0;
}
if (b==0) {
b1=1;
}
else if (b==1) {
b1=0;
}
return ((a*b1) + (a1*b))>0;
}
int getinput() {
int x;
printf("Enter input(0 or 1): ");
scanf("%d", &x);
return x;
}
Gate * creategate(CallBack f) {
Gate * temp ;
temp = malloc(sizeof (Gate));
temp->f = f;
temp->in1 = NULL;
temp->in2 = NULL;
return temp;
}
int eval(Gate *x) {
int a, b;
if (x->in1 != NULL) {
a = eval(x->in1);
}
if (x->in2 != NULL) {
b = eval(x->in2);
}
if (x->in1==NULL && x->in2 == NULL) {
return (x->f)(0,0);
}
else {
return (x->f)(a,b);
}
}
我首先让用户使用 getinput 函数输入每个门输入。 在前三个门中输入前六个输入后, 我希望程序自动获取前一个门的输出 用户无需输入内容。我尝试了很多方法,但我找不到 一个解决方案。我需要保留动态内存分配以及所有结构 如有必要,我可以添加另一个功能。
答:
1赞
Craig Estey
5/31/2023
#1
一些问题......
- 门结构中没有当前的 [output] “状态”。
- “运算符”函数(例如 、 等)返回一个值,而不是将输出值设置到结构体中。
myand
myor
- 因此,如果一个门连接到多个输出,则门状态将被多次评估(而不是每轮一次)。
- 门电平的排序被硬连线到代码中(在函数中)。
eval
- 使用 C 逻辑运算符可以大大简化运算符功能。
- 我们可以通过将相同深度的所有门分配给不同的列表(即每个逻辑深度的单独列表)来动态确定门的评估顺序
- 为了清楚起见,我在门结构中添加了门和函数的名称。
下面是重构后的代码。它被注释。不幸的是,我不得不重写其中的大部分内容。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <termios.h>
#define SIZE 10
struct gate;
typedef void (*CallBack)(struct gate *);
typedef struct function {
CallBack f;
char ch[10];
} MyFunction;
typedef struct gate {
const char *sym; // gate name
CallBack f; // operation function
const char *fsym; // name of operation
int depth; // gate's logic depth
struct gate *next; // peer gate at same logic level
int out; // output state/value
struct gate *in1; // input gate
struct gate *in2; // input gate
} Gate;
// list of gates
typedef struct {
Gate *head;
} List;
#define CREATE(_sym,_fnc) \
Gate *_sym = creategate(#_sym,_fnc,#_fnc)
#define MAXDEPTH 100
int bottom_depth; // last/maximum depth
List levels[MAXDEPTH]; // list of gates at a given depth
// leveladd -- add gate to given gate list
void
leveladd(List *list,Gate *add)
{
Gate *prev = NULL;
for (Gate *tmp = list->head; tmp != NULL; tmp = tmp->next)
prev = tmp;
if (prev != NULL)
prev->next = add;
else
list->head = add;
add->next = NULL;
}
// leveldel -- remove gate from given list
void
leveldel(List *list,Gate *del)
{
Gate *prev = NULL;
Gate *cur = list->head;
for (; cur != NULL; cur = cur->next) {
if (cur == del)
break;
prev = cur;
}
if (cur == NULL) {
printf("leveldel: no match -- %s\n",del->sym);
exit(1);
}
if (prev != NULL)
prev->next = del->next;
else
list->head = del->next;
del->next = NULL;
}
// gatevalue -- current output value of gate
int
gatevalue(Gate *gate)
{
return gate->out;
}
void
myand(Gate *gate)
{
int in1 = gatevalue(gate->in1);
int in2 = gatevalue(gate->in2);
gate->out = (in1 & in2) != 0;
}
void
myor(Gate *gate)
{
int in1 = gatevalue(gate->in1);
int in2 = gatevalue(gate->in2);
gate->out = (in1 | in2) != 0;
}
void
mynand(Gate *gate)
{
int in1 = gatevalue(gate->in1);
int in2 = gatevalue(gate->in2);
gate->out = (in1 & in2) != 0;
gate->out = ! gate->out;
}
void
mynor(Gate *gate)
{
int in1 = gatevalue(gate->in1);
int in2 = gatevalue(gate->in2);
gate->out = (in1 | in2) != 0;
gate->out = ! gate->out;
}
void
myxor(Gate *gate)
{
int in1 = gatevalue(gate->in1);
int in2 = gatevalue(gate->in2);
gate->out = (in1 ^ in2) != 0;
}
void
getinput(Gate *cur)
{
int x;
printf("Enter input(0 or 1) for gate '%s': ",cur->sym);
fflush(stdout);
char buf[10];
fgets(buf,sizeof(buf),stdin);
// echo input if coming from redirected file (e.g.) ./myprogram < inp
struct termios tio;
if (tcgetattr(fileno(stdin),&tio) < 0)
fputs(buf,stdout);
x = atoi(buf);
cur->out = x & 1;
}
// creategate -- create a new gate
Gate *
creategate(const char *sym,CallBack f,const char *fsym)
{
Gate *cur;
cur = calloc(1,sizeof(Gate));
// name of this gate
cur->sym = sym;
// save the operator function
cur->f = f;
cur->fsym = fsym;
// assume initial depth
leveladd(&levels[0],cur);
return cur;
}
// redepth -- [recursively] assign new depth to logic gate
void
redepth(Gate *cur,int newdepth)
{
if (cur == NULL)
return;
if (newdepth > cur->depth)
cur->depth = newdepth;
++newdepth;
redepth(cur->in1,newdepth);
redepth(cur->in2,newdepth);
}
// attach -- attach input gates to given gate
void
attach(Gate *a,Gate *b,Gate *c)
{
a->in1 = b;
redepth(b,a->depth + 1);
a->in2 = c;
redepth(c,a->depth + 1);
}
// gatename -- get name of gate
const char *
gatename(Gate *cur)
{
if (cur != NULL)
return cur->sym;
return NULL;
}
// showgate -- show gate and children
void
showgate(Gate *cur)
{
printf(" %s -- %s %s %s (DEPTH: %d)",
cur->sym,gatename(cur->in1),cur->fsym,gatename(cur->in2),cur->depth);
}
// showlevel -- show all gates at given logic level
void
showlevel(List *list)
{
printf("showlevel: %zu\n",list - levels);
for (Gate *cur = list->head; cur != NULL; cur = cur->next) {
showgate(cur);
printf("\n");
}
}
// showall -- show all logic levels
void
showall(const char *who)
{
List *list;
printf("showall: %s\n",who);
for (list = &levels[0]; list < &levels[MAXDEPTH]; ++list) {
if (list->head != NULL)
showlevel(list);
}
}
// moveall -- move gates to their correct logic level lists
void
moveall(void)
{
List *old = &levels[0];
Gate *next;
for (Gate *cur = old->head; cur != NULL; cur = next) {
next = cur->next;
if (cur->depth != 0) {
leveldel(old,cur);
leveladd(&levels[cur->depth],cur);
}
// remember maximum depth
if (cur->depth > bottom_depth)
bottom_depth = cur->depth;
}
}
// eval -- evaluate gate's new value
void
eval(Gate *cur)
{
printf("\n");
printf("eval:");
showgate(cur);
printf("\n");
cur->f(cur);
printf("eval: out=%d\n",cur->out);
}
// doround -- compute values for all gates for single time period
void
doround(void)
{
for (int curdepth = bottom_depth; curdepth >= 0; --curdepth) {
List *list = &levels[curdepth];
for (Gate *cur = list->head; cur != NULL; cur = cur->next)
eval(cur);
}
}
// showround -- compute values for all gates for single time period
void
showround(void)
{
for (int curdepth = bottom_depth; curdepth >= 0; --curdepth) {
List *list = &levels[curdepth];
for (Gate *cur = list->head; cur != NULL; cur = cur->next)
printf("showround: %s --> %d\n",gatename(cur),gatevalue(cur));
}
}
int
main(void)
{
CREATE(a_ptr,mynor);
CREATE(a1_ptr,getinput);
CREATE(a2_ptr,getinput);
attach(a_ptr,a1_ptr,a2_ptr);
CREATE(b_ptr,myand);
CREATE(b1_ptr,getinput);
CREATE(b2_ptr,getinput);
attach(b_ptr,b1_ptr,b2_ptr);
CREATE(c_ptr,myor);
CREATE(c1_ptr,getinput);
CREATE(c2_ptr,getinput);
attach(c_ptr,c1_ptr,c2_ptr);
CREATE(d_ptr,mynand);
attach(d_ptr,a_ptr,b_ptr);
CREATE(e_ptr,myxor);
attach(e_ptr,b_ptr,c_ptr);
CREATE(f_ptr,myor);
attach(f_ptr,d_ptr,e_ptr);
showall("postadd");
showall("premove");
moveall();
showall("postmove");
// we can loop here if we wish
doround();
showround();
return 0;
}
以下是我使用的示例输入:
1
1
1
1
1
0
输出如下:
showall: postadd
showlevel: 0
a_ptr -- a1_ptr mynor a2_ptr (DEPTH: 2)
a1_ptr -- (null) getinput (null) (DEPTH: 3)
a2_ptr -- (null) getinput (null) (DEPTH: 3)
b_ptr -- b1_ptr myand b2_ptr (DEPTH: 2)
b1_ptr -- (null) getinput (null) (DEPTH: 3)
b2_ptr -- (null) getinput (null) (DEPTH: 3)
c_ptr -- c1_ptr myor c2_ptr (DEPTH: 2)
c1_ptr -- (null) getinput (null) (DEPTH: 3)
c2_ptr -- (null) getinput (null) (DEPTH: 3)
d_ptr -- a_ptr mynand b_ptr (DEPTH: 1)
e_ptr -- b_ptr myxor c_ptr (DEPTH: 1)
f_ptr -- d_ptr myor e_ptr (DEPTH: 0)
showall: premove
showlevel: 0
a_ptr -- a1_ptr mynor a2_ptr (DEPTH: 2)
a1_ptr -- (null) getinput (null) (DEPTH: 3)
a2_ptr -- (null) getinput (null) (DEPTH: 3)
b_ptr -- b1_ptr myand b2_ptr (DEPTH: 2)
b1_ptr -- (null) getinput (null) (DEPTH: 3)
b2_ptr -- (null) getinput (null) (DEPTH: 3)
c_ptr -- c1_ptr myor c2_ptr (DEPTH: 2)
c1_ptr -- (null) getinput (null) (DEPTH: 3)
c2_ptr -- (null) getinput (null) (DEPTH: 3)
d_ptr -- a_ptr mynand b_ptr (DEPTH: 1)
e_ptr -- b_ptr myxor c_ptr (DEPTH: 1)
f_ptr -- d_ptr myor e_ptr (DEPTH: 0)
showall: postmove
showlevel: 0
f_ptr -- d_ptr myor e_ptr (DEPTH: 0)
showlevel: 1
d_ptr -- a_ptr mynand b_ptr (DEPTH: 1)
e_ptr -- b_ptr myxor c_ptr (DEPTH: 1)
showlevel: 2
a_ptr -- a1_ptr mynor a2_ptr (DEPTH: 2)
b_ptr -- b1_ptr myand b2_ptr (DEPTH: 2)
c_ptr -- c1_ptr myor c2_ptr (DEPTH: 2)
showlevel: 3
a1_ptr -- (null) getinput (null) (DEPTH: 3)
a2_ptr -- (null) getinput (null) (DEPTH: 3)
b1_ptr -- (null) getinput (null) (DEPTH: 3)
b2_ptr -- (null) getinput (null) (DEPTH: 3)
c1_ptr -- (null) getinput (null) (DEPTH: 3)
c2_ptr -- (null) getinput (null) (DEPTH: 3)
eval: a1_ptr -- (null) getinput (null) (DEPTH: 3)
Enter input(0 or 1) for gate 'a1_ptr': 1
eval: out=1
eval: a2_ptr -- (null) getinput (null) (DEPTH: 3)
Enter input(0 or 1) for gate 'a2_ptr': 1
eval: out=1
eval: b1_ptr -- (null) getinput (null) (DEPTH: 3)
Enter input(0 or 1) for gate 'b1_ptr': 1
eval: out=1
eval: b2_ptr -- (null) getinput (null) (DEPTH: 3)
Enter input(0 or 1) for gate 'b2_ptr': 1
eval: out=1
eval: c1_ptr -- (null) getinput (null) (DEPTH: 3)
Enter input(0 or 1) for gate 'c1_ptr': 1
eval: out=1
eval: c2_ptr -- (null) getinput (null) (DEPTH: 3)
Enter input(0 or 1) for gate 'c2_ptr': 0
eval: out=0
eval: a_ptr -- a1_ptr mynor a2_ptr (DEPTH: 2)
eval: out=0
eval: b_ptr -- b1_ptr myand b2_ptr (DEPTH: 2)
eval: out=1
eval: c_ptr -- c1_ptr myor c2_ptr (DEPTH: 2)
eval: out=1
eval: d_ptr -- a_ptr mynand b_ptr (DEPTH: 1)
eval: out=1
eval: e_ptr -- b_ptr myxor c_ptr (DEPTH: 1)
eval: out=0
eval: f_ptr -- d_ptr myor e_ptr (DEPTH: 0)
eval: out=1
showround: a1_ptr --> 1
showround: a2_ptr --> 1
showround: b1_ptr --> 1
showround: b2_ptr --> 1
showround: c1_ptr --> 1
showround: c2_ptr --> 0
showround: a_ptr --> 0
showround: b_ptr --> 1
showround: c_ptr --> 1
showround: d_ptr --> 1
showround: e_ptr --> 0
showround: f_ptr --> 1
评论
eval
a
b
a = ...
b = ...
eval
a
b
int a=0,b=0;
x->in1
x->in2
a
b
result = !result
a + b == 0
xor
a != b
(a == 0) != (b == 0)
createGate
getinput