C++ 当只有一些小事情需要更改时,如何避免复制粘贴代码块?
这对我来说很难用语言来表达,但是说我有一些功能:C++ 当只有一些小事情需要更改时,如何避免复制粘贴代码块?,c++,C++,这对我来说很难用语言来表达,但是说我有一些功能: a = a + b; printf("HI THERE"); b = a + c; (假设这是30行而不是3行)。现在,我想稍后再做同样的事情,除了不打印“HI THERE”,而是打印“HO THERE”。我现在做的是复制粘贴这个函数的所有行,只是将HI-THERE更改为HO-THERE。这对于大型代码块来说不是很优雅 我知道一个解决方案可能是: adder_function(1); adder_function(2); void adder
a = a + b;
printf("HI THERE");
b = a + c;
(假设这是30行而不是3行)。现在,我想稍后再做同样的事情,除了不打印“HI THERE”,而是打印“HO THERE”。我现在做的是复制粘贴这个函数的所有行,只是将HI-THERE更改为HO-THERE。这对于大型代码块来说不是很优雅
我知道一个解决方案可能是:
adder_function(1);
adder_function(2);
void adder_fuction(int input) {
a = a + b;
printer_function(input);
b = a + c;
}
void printer_function(int input) {
if (input == 1) printf("HI THERE");
if (input == 2) printf("HO THERE");
}
但对于更复杂的代码块来说,这似乎也是不雅观的。有没有更好的解决方案
编辑:为了说明我在做什么,下面是有问题的代码(您可以看到,除了.input和.output以及printf语句外,块之间几乎没有任何更改):
found=line.find(“输入”);
如果(找到==0){
inputfound=true;
find=line.find_first_of(“:”);
如果(找到==string::npos){
printf(“错误的网络列表输入声明\n\r”);
出口(1);
}
found=行。首先查找\u而不是(“\n\t”,found+1);
if(found==string::npos){
printf(“错误的网络列表输入声明\n\r”);
出口(1);
}
否则{
temp_node_name+=行[found];
对于(i=find+1;i
复制粘贴的单独代码块
found=line.find("OUTPUTS");
if (found == 0){
outputfound = true;
found = line.find_first_of(":");
if (found == string::npos) {
printf("BAD NETLIST OUTPUT DECLARATION\n\r");
exit(1);
}
found = line.find_first_not_of("\n\t ",found+1);
if (found == string::npos) {
printf("BAD NETLIST OUTPUT DECLARATION\n\r");
exit(1);
}
else {
temp_node_name += line[found];
for (i = found+1; i < line.size(); i++) {
if ( isalnum(line[i]) || isspace(line[i]) ) {
if ( isalnum(line[i]) )
temp_node_name += line[i];
if ( isspace(line[i]) || i == line.size() - 1 ) {
if (!temp_node_name.empty()) {
if (determine_uniqueness(temp_node_name)) {
nodes.push_back(dummy_node);
nodes.at(id_counter).name_in_netlist = temp_node_name;
**nodes.at(id_counter).output = true;**
temp_node_name.erase();
id_counter++;
}
}
}
}
else {
printf("BAD NETLIST OUTPUT DECLARATION\n\r");
exit(1);
}
}
}
printf("NETLIST OUTPUT DECLARATION OK\n\r");
continue;
}
found=line.find(“输出”);
如果(找到==0){
outputfound=true;
find=line.find_first_of(“:”);
if(found==string::npos){
printf(“错误的网络列表输出声明\n\r”);
出口(1);
}
found=行。首先查找\u而不是(“\n\t”,found+1);
if(found==string::npos){
printf(“错误的网络列表输出声明\n\r”);
出口(1);
}
否则{
temp_node_name+=行[found];
对于(i=find+1;i当然,生成函数是重用代码的好方法。如果相同的代码在多个位置重复,则可以从中生成函数。如果你发现有很多函数做类似的事情,也许你可以把它们组合成一个函数,再加上几个额外的参数。在您给出的示例中,您可以这样做:
void adder_function(const char * message) {
a = a + b;
printf("%s", message);
b = a + c;
}
int main() {
adder_function("HI THERE");
adder_function("HO THERE");
}
我建议您尽量避免在源代码中添加幻数(例如1和2)。最好使用#定义或完全避免这种情况,就像我在上面所做的那样。遵循单一责任原则,您应该将代码分解成更小的部分。在您的示例中,您将UI代码(printf)与计算逻辑混为一谈。避免这种情况
由于您使用的是纯C代码(没有C++),因此很难给出使用常见OOP模式的更灵活设计的示例。但对于您的问题,一个非常简单的第一个解决方案是将输出内容与计算分离:
void ShowMessage(const char* msg);
int Calculate(int a, int b);
int DoTheHiThereCalculation()
{
int c = Calculate(1, 2);
ShowMessage("Hi THERE");
return c;
}
根据话题发起者的评论
。如果我想做像node_struct.XXXXX=2这样的事情;如果XXXXXX可以是任意字符串,我将如何执行此操作
在使用c/c++时,可以使用宏。(看)
尝试将更改的内容(在两个函数中)作为参数传递给函数(这是唯一一个接受这些不同参数的函数)。通过这种方式,您可以在一个函数中同时完成这两项任务。既然这里介绍的各种简单解决方案似乎都没有用,我将提出一个大锤(警告:小心使用)
OO语言中有两种设计模式用于处理模式重复:
< LI>(不要被C++模板错误)
在您的情况下,我建议您以依赖注入的方式尝试策略
模式
struct Strategy {
virtual void setFoo(Foo& foo, int i) = 0;
virtual void setBar(Bar& bar, int i) = 0;
};
struct A: Strategy {
virtual void setFoo(Foo& foo, int i) { foo.a = i; }
virtual void setBar(Bar& bar, int i) { bar.a = i; }
};
struct B: Strategy {
virtual void setFoo(Foo& foo, int i) { foo.b = i; }
virtual void setBar(Bar& bar, int i) { bar.b = i; }
};
void doSomething(Foo& foo, Bar& bar, Strategy& strategy) {
for (size_t i = 0; i < 10; ++i) {
//
strategy.setFoo(foo, i);
//
for (size_t j = 0; j < 10; ++j) {
//
strategy.setBar(bar, j);
//
}
}
}
我来晚了,所以我只会处理你的更新代码
首先,我看到您将错误消息打印到stdout
(通过printf
),然后调用exit
。为什么?您应该将错误(可能还有调试)消息打印到stderr
(使用fprintf(stderr,…)
或perror
,但是如果库例程失败并设置errno
,则perror
更好)。还有,自从
const char* STR_TABLE[N] =
{
"HI THERE",
"HO THERE",
...
};
printf(STR_TABLE[n]);
#define NODE_MEMBER(x) node_struct.##x
......
NODE_MEMBER(a)
NODE_MEMBER(b)
struct Strategy {
virtual void setFoo(Foo& foo, int i) = 0;
virtual void setBar(Bar& bar, int i) = 0;
};
struct A: Strategy {
virtual void setFoo(Foo& foo, int i) { foo.a = i; }
virtual void setBar(Bar& bar, int i) { bar.a = i; }
};
struct B: Strategy {
virtual void setFoo(Foo& foo, int i) { foo.b = i; }
virtual void setBar(Bar& bar, int i) { bar.b = i; }
};
void doSomething(Foo& foo, Bar& bar, Strategy& strategy) {
for (size_t i = 0; i < 10; ++i) {
//
strategy.setFoo(foo, i);
//
for (size_t j = 0; j < 10; ++j) {
//
strategy.setBar(bar, j);
//
}
}
}
int main(int argc, char* argv[]) {
if (argc == 1) { std::cerr << "usage: %prog STRAT\n"; return 1; }
Foo foo;
Bar bar;
char const strat = argv[1][0];
switch(strat) {
case 'a': case 'A': {
A a;
doSomething(foo, bar, a);
return 0;
}
case 'b': case 'B': {
B b;
doSomething(foo, bar, b);
return 0;
}
default:
std::cerr << "Unknown Strategy: " << strat << ", pick A or B\n";
return 2;
}
}
fprintf(stderr, "BAD NETLIST %s DECLARATION\n", is_input ? "INPUT" : "OUTPUT");
fprintf(stderr, "NETLIST %s DECLARATION OK\n", is_input ? "INPUT" : "OUTPUT");
(is_input ? nodes[id_counter].input : nodes[id_counter]) = true
void adder_fuction(const char *text) {
a = a + b;
puts(text);
b = a + c;
}
int main() {
adder_function("HI THERE");
adder_function("HO THERE");
}
void adder_function(void (*callback)()) {
a = a + b;
callback();
b = a + c;
}
void callback1() {
puts("HI THERE");
}
void callback2() {
puts("HO THERE");
}
int main() {
adder_function(&callback1);
adder_function(&callback2);
}
void adder_function(int (*callback)(const char *)) {
a = a + b;
c = c + callback("HI THERE");
b = a + c;
}
int callback1(const char *) ...
#define define_adder_function(name, code) \
name() { \
a = a + b; \
code; \
b = a + c; \
}
define_adder_function(adder_function1, c = 22) // NO semicolon here. Using preprocessor does have it's quirks
int main() {
adder_function1();
}
struct Callback {
virtual void operator()(const char *) = 0;
};
void adder_function(Callback &cb) {
a = a + b;
cb("foo");
b = a + c;
}
int main() {
struct Cb : Callback {
void operator()(const char *arg) { printf("Foo %s\n", arg); }
} cb;
adder_function(cb);
}
#include <functional>
void adder_function(std::function<void (const char *)> cb) {
a = a + b;
cb("foo");
b = a + c;
}
void callback1(const char *arg) { puts(arg); }
int main() {
struct { // You can have local structures, even with methods, but not local functions
void operator()(const char *arg) { printf("Foo %s\n", arg); }
} callback2;
adder_function(&callback1); // std::function should accept either function or functor
adder_function(callback2);
}
template <typename Callback>
void adder_function(Callback cb) {
a = a + b;
cb("foo");
b = a + c;
}
void callback1(const char *arg) { puts(arg); }
int main() {
struct Callback2 { // Anonymous types can't be used in templates before C++11.
void operator()(const char *arg) { printf("Foo %s\n", arg); }
} callback2;
adder_function(&callback1); // template also accepts either function pointer or functor
adder_function(callback2);
}
int main() {
adder_function([](const char *arg) { puts(arg) });
}