×
Samples Blogs Make Payment About Us Reviews 4.9/5 Order Now

Program to Generate Truth Tables From Logic Expressions In C++ Assignment Solution

July 01, 2024
Prof. Liam Wilson
Prof. Liam
🇦🇺 Australia
C++
Prof. Liam Wilson is a seasoned programmer and educator with a master's degree in computer science from the University of Melbourne. His expertise in C++ is unmatched, having completed over 700 assignments with meticulous attention to detail and a commitment to delivering top-quality solutions.
Key Topics
  • Instructions
    • Objective
  • Requirements and Specifications
Tip of the day
Use modular coding in Verilog assignments by breaking the design into smaller modules. This improves readability, simplifies debugging, and allows for easier testing and reuse of code components in larger designs.
News
In 2024, Visual Studio Code now offers enhanced GitHub Copilot integration for faster, while PyCharm has improved debugging and testing tools, making it ideal for Python students​

Instructions

Objective

Write a program that allows users to generate truth tables from logic expressions in C++.

Requirements and Specifications

You will write a program truthtable that reads a file containing a description of a circuit, andprints that circuit’s truth table. The files specify (1) the number and names of each input to thecircuit, (2) the number and names of each output from the circuit, and (3) the logic gates and components that make up the circuit. In order to indicate the connections between gates, each connection is also given a name.

For example, this is a description for a circuit that implements a 3-argument AND gate:

INPUT 3 a b c

OUTPUT 1 d

AND a b x

AND c x d

Note that it contains three inputs (a, b, and c), a single output (d), and two AND gates, each of which has two inputs and one output. The variable x indicates an internal connection between the first AND gate and the second. See section 3 for details on the specification language.

truthtable takes a single argument, which is the name of a file containing a circuit description. The behavior of truthtable is unspecified if it receives no arguments or more than one argument, but you should still check that the number of arguments is correct. (One possibility is to have truthtable read from standard input if no file argument is given.)

Screenshots of output

program-to-generate-truth-tables-from-logic-expressions-C++
program-to-generate-truth-tables-from-logic-expressions-C++ 1

Source Code

#include #include #include typedef enum { AND, OR, NAND, NOR, XOR, NOT, PASS, DECODER, MULTIPLEXER } kind_t; char *gate_name[9] = {"AND", "OR", "NAND", "NOR", "XOR", "NOT", "PASS", "DECODER", "MULTIPLEXER"}; typedef struct gate { kind_t kind; int size; // indicates size of DECODER and MULTIPLEXER int *params; // length determined by kind and size; // includes inputs and outputs, indicated by variable numbers }Gate; typedef struct variable { char *name; // variable name int value; // current value int out; // flag to indicate if it's an output for a gate or the circuit }Variable; typedef struct circuit { int ninputs; // number of inputs int *inputs; // input variable positions int noutputs; // number of outputs int *outputs; // output variable positions int ngates; // number of gates Gate **gates; // list of gates int nvars; // number of variables Variable **vars; // variables }Circuit; /* Free all the memory allocated by a variable */ void free_variable(Variable *var) { if (var != NULL) { if (var->name != NULL) free(var->name); free(var); } } /* Free all the memory allocated by a gate */ void free_gate(Gate *gate) { if (gate != NULL) { if (gate->params != NULL) free(gate->params); free(gate); } } /* Free all the memory allocated by the circuit */ void free_circuit(Circuit *circ) { int i; if (circ != NULL) { if (circ->ninputs && circ->inputs != NULL) free(circ->inputs); if (circ->noutputs && circ->outputs != NULL) free(circ->outputs); if (circ->vars != NULL) { for (i = 0; i < circ->nvars; i++) free_variable(circ->vars[i]); free(circ->vars); } if (circ->gates != NULL) { for (i = 0; i < circ->ngates; i++) free_gate(circ->gates[i]); free(circ->gates); } free(circ); } } /* Searches a variable in the variable list for the circuit, returns its position or -1 if not found */ int search_variable(char *var, Circuit *circ) { int i, index = -1; for (i = 0; i < circ->nvars && index == -1; i++) { if (!strcmp(var, circ->vars[i]->name)) index = i; } return index; } /* Create a new variable */ Variable *new_variable(char *name, Circuit *circ) { Variable *var = (Variable *) malloc(sizeof(Variable)); if (var == NULL) { printf("ERROR: Out of memory while creating variable\n"); free_circuit(circ); exit(EXIT_FAILURE); } var->name = (char *) malloc(strlen(name) + 1); if (var->name == NULL) { printf("ERROR: Out of memory while creating variable\n"); free(var); free_circuit(circ); exit(EXIT_FAILURE); } strcpy(var->name, name); // save variable name var->value = -1; // undefined var->out = 0; // not out return var; } /* Adds a variable to the variable list in the circuit, returns its position. It avoids adding repeated variable names */ int add_variable(char *var_name, Circuit *circ) { int n; Variable **vars; n = search_variable(var_name, circ); if (n == -1) // if new variable { n = circ->nvars; if (n == 0) vars = (Variable **) malloc(sizeof(Variable *)); else vars = (Variable **) realloc(circ->vars, (n + 1) * sizeof(Variable *)); if (vars == NULL) { printf("ERROR: Out of memory while creating variable\n"); free_circuit(circ); exit(EXIT_FAILURE); } circ->vars = vars; circ->vars[n] = new_variable(var_name, circ); circ->nvars++; // increment number of variables } return n; // return position of variable } /* Create a new circuit */ Circuit *new_circuit() { int i; Circuit *circ = (Circuit *) malloc(sizeof(Circuit)); if (circ == NULL) { printf("ERROR: Out of memory while creating circuit\n"); exit(EXIT_FAILURE); } /* set all entries to zero */ memset(circ, 0, sizeof(Circuit)); i = add_variable("0", circ); // add the zero constant circ->vars[i]->value = 0; // always zero i = add_variable("1", circ); // add the one constant circ->vars[i]->value = 1; // always one add_variable("_", circ); // add the dummy var return circ; } /* Create a new gate of n parameters and given kind */ Gate *new_gate(kind_t kind, int n, int size, Circuit *circ) { Gate *gate = (Gate *) malloc(sizeof(Gate)); if (gate == NULL) { printf("ERROR: Out of memory while creating gate\n"); free_circuit(circ); exit(EXIT_FAILURE); } gate->kind = kind; gate->params = (int *) malloc(n *sizeof(int *)); if (gate->params == NULL) { printf("ERROR: Out of memory while creating gate\n"); free(gate); free_circuit(circ); exit(EXIT_FAILURE); } gate->size = size; return gate; } /* Adds a gate to the gate list in the circuit. */ void add_gate(Gate *gate, Circuit *circ) { int n; n = circ->ngates; Gate **gates; if (n == 0) gates = (Gate **) malloc(sizeof(Gate *)); else gates = (Gate **) realloc(circ->gates, (n + 1) * sizeof(Gate *)); if (gates == NULL) { printf("ERROR: Out of memory while creating gate\n"); free_circuit(circ); exit(EXIT_FAILURE); } circ->gates = gates; circ->gates[n] = gate; // save gate circ->ngates++; // increment number of gates } /* Loads a circuit from the given file and returns it */ Circuit *load_circuit(char *filename) { FILE *f; char buffer[20]; int i, j, n, size; kind_t kind; Circuit *circ; Gate *gate; int outi, nouts; f = fopen(filename, "rt"); // open file as read only text if (f == NULL) // if file was not open { printf("ERROR: Unable to open file: \"%s\"\n", filename); exit(EXIT_FAILURE); // terminate program } // create new circuit circ = new_circuit(); // read input variables, it must be at start fscanf(f, "%16s %d", buffer, &circ->ninputs); // read if (strcmp(buffer, "INPUT")) { printf("ERROR: INPUT was not the first directive in the file\n"); exit(EXIT_FAILURE); } circ->inputs = (int *) malloc(circ->ninputs*sizeof(int)); // allocate space for inputs if (circ->inputs == NULL) { printf("ERROR: Out of memory while creating circuit inputs\n"); free_circuit(circ); exit(EXIT_FAILURE); } // read inputs for (i = 0; i < circ->ninputs; i++) { if (fscanf(f, "%16s", buffer) != 1) // read variable { printf("ERROR: INPUT expected a variable name\n"); free_circuit(circ); exit(EXIT_FAILURE); } n = add_variable(buffer, circ); circ->inputs[i] = n; // save variable position } // read output variables, it must be after input fscanf(f, "%16s %d", buffer, &circ->noutputs); // read if (strcmp(buffer, "OUTPUT")) { printf("ERROR: OUTPUT was not the second directive in the file\n"); free_circuit(circ); exit(EXIT_FAILURE); } circ->outputs = (int *) malloc(circ->noutputs*sizeof(int)); // allocate space for outputs if (circ->outputs == NULL) { printf("ERROR: Out of memory while creating circuit outputs\n"); free_circuit(circ); exit(EXIT_FAILURE); } // read outputs for (i = 0; i < circ->noutputs; i++) { if (fscanf(f, "%16s", buffer) != 1) // read variable { printf("ERROR: OUTPUT expected a variable name\n"); free_circuit(circ); exit(EXIT_FAILURE); } n = add_variable(buffer, circ); circ->outputs[i] = n; // save variable position circ->vars[circ->outputs[i]]->out = 1; } while (!feof(f)) // read all lines in file { if(fscanf(f, "%16s", buffer) == 1) // read directive { outi = 2; nouts = 1; if (!strcmp(buffer, "NOT")) { kind = NOT; size = 0; n = 2; outi = 1; nouts = 1; } if (!strcmp(buffer, "PASS")) { kind = PASS; size = 0; n = 2; outi = 1; nouts = 1; } else if (!strcmp(buffer, "AND")) { kind = AND; size = 0; n = 3; } else if (!strcmp(buffer, "OR")) { kind = OR; size = 0; n = 3; } else if (!strcmp(buffer, "NAND")) { kind = NAND; size = 0; n = 3; } else if (!strcmp(buffer, "NOR")) { kind = NOR; size = 0; n = 3; } else if (!strcmp(buffer, "XOR")) { kind = XOR; size = 0; n = 3; } else if (!strcmp(buffer, "DECODER")) { kind = DECODER; fscanf(f, "%d", &size); // read the size n = size + (1 << size); // n + 2^n parameters outi = size; // start of outputs nouts = 1 << size; // size of outputs } else if (!strcmp(buffer, "MULTIPLEXER")) { kind = MULTIPLEXER; fscanf(f, "%d", &size); // read the size n = size + (1 << size) + 1; // n + 2^n + 1 parameters outi = size + (1 << size); // start of outputs nouts = 1; // size of outputs } // create the gate gate = new_gate(kind, n, size, circ); // read parameters for (i = 0; i < n; i++) { if (fscanf(f, "%16s", buffer) != 1) // read variable { printf("ERROR: %s expected a variable name\n", gate_name[kind]); free_gate(gate); free_circuit(circ); exit(EXIT_FAILURE); } j = add_variable(buffer, circ); gate->params[i] = j; // save variable position if (i >= outi && i <= outi + nouts - 1) circ->vars[j]->out = 1; } add_gate(gate, circ); // add gate to circuit } } fclose(f); return circ; } /* get decimal value from a series of consecutive variables in a gate */ int get_dec_value(int start, int end, Gate *gate, Circuit *circ) { int i, pow2 = 0; int val = 0; for (i = end, pow2 = 0; i >= start && val != -1; i--, pow2++) { if (circ->vars[gate->params[i]]->value == -1) val = -1; else val += circ->vars[gate->params[i]]->value << pow2; } return val; } /* evaluate gate output */ int eval_gate(Gate *gate, Circuit *circ) { int a, b; int i, pos; int output = -1; // cache values for 2 input gates a = circ->vars[gate->params[0]]->value; b = circ->vars[gate->params[1]]->value; switch (gate->kind) { case AND: if (a != -1 && b != -1) output = a & b; circ->vars[gate->params[2]]->value = output; break; case OR: if (a != -1 && b != -1) output = a | b; circ->vars[gate->params[2]]->value = output; break; case NAND: if (a != -1 && b != -1) output = (~(a & b)) & 1; circ->vars[gate->params[2]]->value = output; break; case NOR: if (a != -1 && b != -1) output = (~(a | b)) & 1; circ->vars[gate->params[2]]->value = output; break; case XOR: if (a != -1 && b != -1) output = a ^ b; circ->vars[gate->params[2]]->value = output; break; case NOT: if (a != -1) output = (~a) & 1; circ->vars[gate->params[1]]->value = output; break; case PASS: output = a; circ->vars[gate->params[1]]->value = output; break; case DECODER: pos = get_dec_value(0, gate->size - 1, gate, circ); if (pos == -1) { for (i = 0; i < (1 << gate->size); i++) circ->vars[gate->params[gate->size + i]]->value = -1; } else { for (i = 0; i < (1 << gate->size); i++) circ->vars[gate->params[gate->size + i]]->value = 0; circ->vars[gate->params[gate->size + pos]]->value = 1; output = 1; } break; case MULTIPLEXER: pos = get_dec_value(1 << gate->size, (1 << gate->size) + gate->size - 1, gate, circ); if (pos == -1) circ->vars[gate->params[(1 << gate->size) + gate->size]]->value = -1; else { output = circ->vars[gate->params[pos]]->value; circ->vars[gate->params[(1 << gate->size) + gate->size]]->value = output; } break; } return output; } /* increment input to next value, returns 0 if no error, 1 if all inputs were 1 */ int next_input(Circuit *circ) { int i; int cy = 1; for (i = circ->ninputs - 1; i >= 0 && cy == 1; i--) { if (circ->vars[circ->inputs[i]]->value == 0) { circ->vars[circ->inputs[i]]->value = 1; cy = 0; // don't propagate } else { circ->vars[circ->inputs[i]]->value = 0; cy = 1; // propagate to next } } return cy; } /* print input values */ void print_inputs(Circuit *circ) { int i; for (i = 0; i < circ->ninputs; i++) printf("%d ", circ->vars[circ->inputs[i]]->value); } /* print output values */ void print_outputs(Circuit *circ) { int i; for (i = 0; i < circ->noutputs; i++) printf(" %d", circ->vars[circ->outputs[i]]->value); } /* returns 1 if all outputs are valid */ int valid_outputs(Circuit *circ) { int i; for (i = 0; i < circ->noutputs; i++) if (circ->vars[circ->outputs[i]]->value == -1) return 0; return 1; } /* float all outputs to undefined */ void float_outputs(Circuit *circ) { int i; // float all outputs, ignore the 0, 1 and _ wires for (i = 3; i < circ->nvars; i++) if (circ->vars[i]->out) circ->vars[i]->value = -1; } /* evaluate circuit outputs */ void eval_circuit(Circuit *circ) { int i; int cy = 0; /* set all inputs to zero */ for (i = 0; i < circ->ninputs; i++) circ->vars[circ->inputs[i]]->value = 0; while (!cy) // repeat until there's a carry after incrementing input { print_inputs(circ); /* set all outputs to -1 */ float_outputs(circ); while (!valid_outputs(circ)) // evaluate until all outputs are valid { for (i = 0; i < circ->ngates; i++) // evaluate all gates eval_gate(circ->gates[i], circ); // evaluate gate } printf("|"); print_outputs(circ); printf("\n"); cy = next_input(circ); // get next input state } } int main(int argc, char **argv) { Circuit *circ; if (argc == 1) /* if no input arguments */ { printf("Usage:\n"); printf(" %s \n", argv[0]); return EXIT_SUCCESS; } else if (argc > 2) { printf("Too many arguments\n"); return EXIT_FAILURE; } circ = load_circuit(argv[1]); /* load circuit from argument */ eval_circuit(circ); free_circuit(circ); return EXIT_SUCCESS; }

Similar Samples

Discover our expertise at ProgrammingHomeworkHelp.com through our diverse collection of sample assignments. These examples showcase our proficiency in solving programming challenges across various languages and topics. Explore our samples to see how we can assist you in achieving academic success with your programming projects.