TASKS:
1) The class interfaces do not follow good object-oriented design principles,
which makes them bug-prone and hard to extend/subclass properly.
Improve the object-oriented design of the classes.
2) There seems to be a bug somewhere, as the test program seems to end with a
SEGV.
Find the bug, explain what is wrong, and make a working fix.
3) The class LogicFunction only supports functions defined by a table.
For some logical functions, especially with many inputs, the truth tables may
be inconveniently large. As an example, a 10-input XOR would need 1024 rows,
whereas you could implement it by a couple of lines of C++ code.
Make modifications that enable client code to define their own LogicFunction
objects, whose behaviour is determined by their own C++ code, that can be used
with the standard LogicFunction and LogicProcessor classes.
4) Using your modified classes, define LogicProcessor objects that are able to
inspect an 8x8 monochrome pixel grid, represented by 64 inputs, and report
whether this grid has horizontal, vertical or rotational symmetry.
The grids given in testcases.h cover some easy possibilities; use them to
1) The class interfaces do not follow good object-oriented design principles,
which makes them bug-prone and hard to extend/subclass properly.
Improve the object-oriented design of the classes.
2) There seems to be a bug somewhere, as the test program seems to end with a
SEGV.
Find the bug, explain what is wrong, and make a working fix.
3) The class LogicFunction only supports functions defined by a table.
For some logical functions, especially with many inputs, the truth tables may
be inconveniently large. As an example, a 10-input XOR would need 1024 rows,
whereas you could implement it by a couple of lines of C++ code.
Make modifications that enable client code to define their own LogicFunction
objects, whose behaviour is determined by their own C++ code, that can be used
with the standard LogicFunction and LogicProcessor classes.
4) Using your modified classes, define LogicProcessor objects that are able to
inspect an 8x8 monochrome pixel grid, represented by 64 inputs, and report
whether this grid has horizontal, vertical or rotational symmetry.
The grids given in testcases.h cover some easy possibilities; use them to
extend the test program to test your symmetry processors.
主要是第4题:
思路如下:
判断8x8矩阵是否对称
1,判断垂直对称
第1行与第8行对比,例如
11110011,
11111100
--------------------
11110000
两两做同或(先异或,再去反),再对11110000依次求与, 1&1&1&1&0&0&0&0
若为1,则这两行对称,否则不对称。
同样,第2行与第7行,第3行与第6行,第4行与第5行
最后把上面求的四组结果依次求与,得出结果。若为1,则对称,若为0则不对称。
2对于水平对称,矩阵转置,然后调用垂直对称的算法
3,完全对称:同时满足垂直对称和水平对称。
详细过程见:点击下载代码
*****************LogicFunction.h*****************//
class LogicFunction {
public:
// inputs/output are char: 't','f','x'
// table entries are strings of numinputs inputs + resulting output
LogicFunction(const char *name, int numinputs, const char **table);
~LogicFunction();
static LogicFunction *findFunction(const char *name);
char calculate(char *inputs);
int m_numinputs;
char *m_name;
const char **m_table;
};
class LogicProcessor {
public:
LogicProcessor( LogicFunction *function );
~LogicProcessor();
void setInput(int input, LogicProcessor *lf);
void setInput(int input, char * source);
char process();
char **m_inputsources;
LogicProcessor **m_inputfunctions;
LogicFunction *m_logicfunction;
};
#endif // LOGICFUNCTION_H
/******************LogicFunction.cpp****************//
/* Logical function */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include "logicfunction.h" class LogicFunctionList { private: struct LogicFunctionElm { LogicFunction *m_function; struct LogicFunctionElm *m_next; }; static struct LogicFunctionElm *head; public: static void insert(LogicFunction *f); static void remove(LogicFunction *f); static LogicFunction *find(const char *name); }; LogicFunctionList::LogicFunctionElm *LogicFunctionList::head; void LogicFunctionList::insert(LogicFunction *f) { struct LogicFunctionElm *oldhead=head; head = new struct LogicFunctionElm; head->m_function = f; head->m_next = oldhead; } void LogicFunctionList::remove(LogicFunction *f) { for (LogicFunctionElm **elm=&head; *elm; elm=&((*elm)->m_next)) { if ( (*elm)->m_function == f) { LogicFunctionElm *next = (*elm)->m_next; delete (*elm); (*elm) = next; } } } LogicFunction *LogicFunctionList::find(const char *name) { for (LogicFunctionElm *elm=head; elm; elm=elm->m_next) { if (0 == strcmp(name, elm->m_function->m_name) ) { return elm->m_function; } } return 0; } LogicFunction::LogicFunction(const char *name, int numinputs, const char **table) : m_numinputs(numinputs), m_table(table) { if (LogicFunction *lf = LogicFunctionList::find(name)) { fprintf(stderr, "Warning: Duplicate definition of LogicFunction \"%s\"\n", name); delete lf; } m_name = strdup(name); LogicFunctionList::insert(this); } LogicFunction::~LogicFunction() { LogicFunctionList::remove(this); free(m_name); } LogicFunction *LogicFunction::findFunction(const char *name) { return LogicFunctionList::find(name); } char LogicFunction::calculate(char *inputs) { for (const char **t=m_table; *t ; t++) { int i; for (i=0; (*t)[i] == 'x' || inputs[i] == (*t)[i] ; ) { if (++i == m_numinputs ) return (*t)[i]; } } return 'x'; } LogicProcessor::LogicProcessor( LogicFunction *function ) : m_logicfunction ( function ) { m_inputsources = new char * [ function->m_numinputs ]; m_inputfunctions = new LogicProcessor * [ function->m_numinputs ]; for (int i=0; i<function->m_numinputs; i++) { m_inputsources[i] = 0; m_inputfunctions[i] = 0; } } LogicProcessor::~LogicProcessor() { delete [] m_inputsources; delete [] m_inputfunctions; } void LogicProcessor::setInput(int input, LogicProcessor *lf) { m_inputfunctions[input] = lf; } void LogicProcessor::setInput(int input, char * source) { m_inputsources[input] = source; } char LogicProcessor::process() { char *inputs = new char [ m_logicfunction->m_numinputs ]; for (int i=0;i<m_logicfunction->m_numinputs;i++) { inputs[i] = m_inputsources[i] ? *m_inputsources[i] : m_inputfunctions[i] ? m_inputfunctions[i]->process() : 'x'; } char output=m_logicfunction->calculate(inputs); delete [] inputs; return output; }
******************************/
/* * Test software */ #include <stdio.h> #include "logicfunction.h" const char *or2_table [] = { "txt", "xtt", "fff", 0 }; const char *or3_table [] = { "txxt", "xtxt", "xxtt", "ffff", 0 }; const char *and2_table [] = { "ttt", "fxf", "xff", 0 }; const char *and3_table [] = { "tttt", "fxxf", "xfxf", "xxff", 0 }; const char *xor2_table [] = { "tft", "ftt", "fff", "ttf", 0 }; const char *xor3_table [] = { "fftt", "ftft", "tfft", "tttt", "ffff", "fttf", "ttff", "tftf", 0 }; const char *impl_table [] = { "xtt", "fxt", "tff", 0 }; const char *not_table [] = { "tf", "ft", 0 }; const char *incl_table [] = { "txxt", 0 }; void processor_test(LogicProcessor *proc, int n, char *inp) { int i; for (i=0;i<n;i++) { inp[i] = 'f'; } bool done=false; do { for (i=0 ; i<n; i++) printf("%c ", inp[i]); printf(" -> %c\n", proc->process()); for (i=0 ; i<n; i++) { if (inp[i] == 'f') { inp[i] = 't'; break; } else { inp[i] = 'f'; } } done = i==n; } while (!done); } void function_test ( LogicFunction *func ) { char *inp; char n=func->m_numinputs; LogicProcessor proc(func); printf("Testing function: %s\n", func->m_name); inp = new char [n]; for (int i=0; i<n; i++) { proc.setInput(i, inp+i); } processor_test(&proc, n, inp); delete [] inp; } int main() { LogicFunction f_not("not",1,not_table), f_and2("and2",2,and2_table), f_and3("and3",3,and3_table), f_or2("or2",2,or2_table), f_or3("or3",3,or3_table), f_xor2("xor2",2,xor2_table), f_xor3("xor3",3,xor3_table), f_implies("implies", 2, impl_table); LogicFunction f_incomplete("incomplete",3, incl_table); // Basic table tests function_test(&f_not); function_test(&f_and2); function_test(&f_and3); function_test(&f_or2); function_test(&f_or3); function_test(&f_xor2); function_test(&f_xor3); function_test(&f_implies); function_test(&f_incomplete); // Combinatorial tests { printf("Testing combinatorial not (P and Q)\n"); char inputs[2]; LogicProcessor p_not(&f_not), p_and(&f_and2); p_and.setInput(0,inputs); p_and.setInput(1,inputs + 1); p_not.setInput(0,&p_and); processor_test(&p_not, 2, inputs); } { printf("Testing combinatorial P and not (Q or not R)\n"); // A && !(B || !C) char inputs[3]; LogicProcessor p_not0(&f_not), p_not1(&f_not), p_or(&f_or2), p_and(&f_and2); p_not0.setInput(0,inputs+2); p_or.setInput(0,inputs+1); p_or.setInput(1,&p_not0); p_not1.setInput(0,&p_or); p_and.setInput(0,inputs); p_and.setInput(1, &p_not1); processor_test(&p_and, 3, inputs); } }
//********************testcases.h****************//// Testcases for task 5 // Sample inputs that show different types of symmetry // Supplied as an array in an includable file for simplicity static const char * testcases[] = { // All symmetries "ffffffff" "ffffffff" "ffffffff" "ffffffff" "ffffffff" "ffffffff" "ffffffff" "ffffffff" , "tttttttt" "tttttttt" "tttttttt" "tttttttt" "tttttttt" "tttttttt" "tttttttt" "tttttttt" , "tttttttt" "ffffffff" "tttttttt" "ffffffff" "ffffffff" "tttttttt" "ffffffff" "tttttttt" , "tttttttt" "tfffffft" "tfffffft" "tfffffft" "tfffffft" "tfffffft" "tfffffft" "tttttttt" , "tfffffft" "ftfffftf" "fftfftff" "fffttfff" "fffttfff" "fftfftff" "ftfffftf" "tfffffft" , "fffttfff" "fftfftff" "ftfffftf" "tfffffft" "tfffffft" "ftfffftf" "fftfftff" "fffttfff" , "fffttfff" "fffttfff" "fffttfff" "tttttttt" "tttttttt" "fffttfff" "fffttfff" "fffttfff" , "ttfffftt" "ttfffftt" "ttfffftt" "tttttttt" "tttttttt" "ttfffftt" "ttfffftt" "ttfffftt" , // Horizontal symmetry only "ffffffff" "ffffffff" "ffffffff" "ffffffff" "tttttttt" "tttttttt" "tttttttt" "tttttttt" , "ttfffftt" "ttfffftt" "ffttttff" "ffttttff" "ttfffftt" "ttfffftt" "ffttttff" "ffttttff" , "tttttttt" "fttttttf" "ffttttff" "fffttfff" "tfffffft" "ttfffftt" "tttffttt" "tttttttt" , "tfffffft" "ftfffftf" "fftfftff" "fffttfff" "tfffffft" "ftfffftf" "fftfftff" "fffttfff" , "ttfffftt" "ttfffftt" "fttffttf" "fttffttf" "ffttttff" "ffttttff" "fffttfff" "fffttfff" , "tfffffft" "ttfffftt" "fttffttf" "ffttttff" "fffttfff" "fffttfff" "fffttfff" "fffttfff" , "ffttttff" "fttffttf" "fttffttf" "ffttttff" "fttttttf" "ttfffftt" "ttfffftt" "ffttttff" , "fffttfff" "ffttttff" "fttffttf" "ttfffftt" "tttttttt" "tttttttt" "ttfffftt" "ttfffftt" , // Vertical symmetry only "ttttffff" "ttttffff" "ttttffff" "ttttffff" "ttttffff" "ttttffff" "ttttffff" "ttttffff" , "ttffttff" "ttffttff" "ffttfftt" "ffttfftt" "ffttfftt" "ffttfftt" "ttffttff" "ttffttff" , "fffffftt" "ffffttff" "ffttffff" "ttffffff" "ttffffff" "ffttffff" "ffffttff" "fffffftt" , "tttttttt" "tttttttf" "ttttttff" "ffffffff" "ffffffff" "ttttttff" "tttttttf" "tttttttt" , "ffttttff" "fttttttf" "ttfffftt" "ttffffff" "ttffffff" "ttfffftt" "fttttttf" "ffttttff" , "ttttffff" "ttttttff" "ttfffttf" "ttfffftt" "ttfffftt" "ttfffttf" "ttttttff" "ttttffff" , "tttttttt" "tttttttt" "ttffffff" "tttttttt" "tttttttt" "ttffffff" "tttttttt" "tttttttt" , "ttttttff" "ttfffftt" "ttfffftt" "ttttttff" "ttttttff" "ttfffftt" "ttfffftt" "ttttttff" , // No symmetry "ttttffff" "ttttffff" "ttttffff" "ttttffff" "ffffffff" "ffffffff" "ffffffff" "ffffffff" , "ftffffff" "ffffffff" "ffffffff" "ffffffff" "ffffffff" "ffffffff" "ffffffff" "ffffffff" , "ftffffff" "tffffttf" "ftfffttf" "tfffffff" "ftttffff" "fffttttf" "fffffttf" "tffftttf" , "ttfffttf" "ffttffft" "tfffttff" "fttffftt" "fffttfff" "ttfffttf" "ffttffft" "tfffttff" , "tttttttt" "tttttttt" "fffffttf" "ffffttff" "fffttfff" "ffttffff" "fttfffff" "ttffffff" , "tttttttt" "tttttttt" "ttffffff" "tttttttt" "tttttttt" "ttffffff" "ttffffff" "ttffffff" , "ffttttff" "fttttttf" "ttfffftt" "ttffffff" "ttfftttt" "ttffffft" "tttttttf" "ffttttff" , "fffffftt" "fffffftt" "fffffftt" "fffffftt" "fffffftt" "ttfffftt" "fttffttf" "ffttttff" };