实现逻辑门电路的 C 编程解决方案

Implementing a C programm for logic gates circuit solution

提问人:BraVeHurt 提问时间:5/31/2023 更新时间:5/31/2023 访问量:68

问:

逻辑门电路解决方案

#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 函数输入每个门输入。 在前三个门中输入前六个输入后, 我希望程序自动获取前一个门的输出 用户无需输入内容。我尝试了很多方法,但我找不到 一个解决方案。我需要保留动态内存分配以及所有结构 如有必要,我可以添加另一个功能。

c 逻辑

评论

1赞 WhozCraig 5/31/2023
我认为你需要考虑在每种情况下都做了什么。请记住:除非分别由 those 和 lines 分配,否则 和 都是不确定的。这很重要,尤其是在只分配了其中一个的情况下。我认为如果初始化并接近零(即 然后做了你的两个测试,因为你有它们来覆盖和/或,完全扔掉第三个if-test+block,只是硬返回你的elsebody,但没有else。evalaba = ...b = ...evalabint a=0,b=0;x->in1x->in2ab
0赞 Aconcagua 5/31/2023
请注意:您只需拥有 ,就可以更轻松地交换 0 和 1,但如果您已经调整了比较,您实际上可以直接获得所需的值: – 您可以通过 更轻松地通过 .当然,如果其中一个不是 0 或 1,则中断,如果您想对 AGAINST 进行鲁棒,则可以改为,假设您想将任何不等于零的值视为“true”......result = !resulta + b == 0xora != b(a == 0) != (b == 0)
0赞 Aconcagua 5/31/2023
前几个门的“输出”?你不是说“输入”吗?我假设您想对操作和相应的否定操作使用相同的输入——这是正确的吗?那么你的代码的主要问题是你所拥有的只是操作,但这些操作是完全无状态的。您必须扩展整个设计,以便也可以存储状态。完成此操作后,您将不会调用否定操作,而是为它们提供您提供给非否定操作的相同状态门。createGate
0赞 Aconcagua 5/31/2023
顺便说一句,由于您不需要创建多个门,因此您可以为所有计算门(两次)提供唯一真正必要的实例(无论如何都是无状态的,还记得吗?) - 当然,一旦您添加状态;)getinput
0赞 BraVeHurt 5/31/2023
@Aconcagua我希望门的输出作为下一个门的输入......我不知道你是否明白我......例如,我有三个门,每个门需要两个输入。第一个是“和门”,我给它 0 和 1。它返回 0。第二个是“或门”,我给它 0 和 0。它返回 0。现在我想使用两个输出,我的意思是 0 和 0,作为最后一个门的输入

答:

1赞 Craig Estey 5/31/2023 #1

一些问题......

  1. 门结构中没有当前的 [output] “状态”。
  2. “运算符”函数(例如 、 等)返回一个值,而不是将输出值设置到结构体中。myandmyor
  3. 因此,如果一个门连接到多个输出,则门状态将被多次评估(而不是每轮一次)。
  4. 门电平的排序被硬连线到代码中(在函数中)。eval
  5. 使用 C 逻辑运算符可以大大简化运算符功能。
  6. 我们可以通过将相同深度的所有门分配给不同的列表(即每个逻辑深度的单独列表)来动态确定门的评估顺序
  7. 为了清楚起见,我在门结构中添加了门和函数的名称。

下面是重构后的代码。它被注释。不幸的是,我不得不重写其中的大部分内容。

#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