我做了一个简单的程序,对给定数组的所有元素执行基本算术操作。但是问题是,代码是非常重复的,编写重复的代码并不是一个好的实践,我无法想出解决这个问题的方法。我们如何尽量减少这个程序中的代码重复?
int add(int numcount, int numarr[]){
int total = numarr[0];
// add all the numbers in a array
for (int i = 1; i < numcount; i++){
total += numarr[i];
}
return total;
}
int sub(int numcount, int numarr[]) {
int total = numarr[0];
// subtract all the numbers in array
for (int i = 1; i < numcount; i++){
total -= numarr[i];
}
return total;
}
int mul(int numcount, int numarr[]) {
int total = numarr[0];
// multiply all the numbers in array
for (int i = 1; i < numcount; i++){
total *= numarr[i];
}
return total;
}
int main(int argc, char* argv[]){
const int n = 5;
int arr[n] = {1, 2, 3, 4, 5};
cout << "Addition: " << add(n, arr) << endl;
cout << "Subtraction: " << sub(n, arr) << endl;
cout << "Multiplication: " << mul(n, arr) << endl;
}发布于 2022-09-07 15:53:10
我们如何尽量减少这个程序中的代码重复?
一般说来,通过识别重复的结构,看看我们是否可以把它抽象出来,或者为它找到一个现有的名称。
std::accumulate可以做我们需要的事情,不需要为add添加任何额外的参数,只需要为其他的运算符函数对象提供适当的运算符函数对象。所以,你可以随便写
int add(int numcount, int numarr[]){
return std::accumulate(numarr, numarr+numcount, 0);
}
// OK, your sub isn't actually trivial
int sub(int numcount, int numarr[]){
return std::accumulate(numarr+1, numarr+numcount, numarr[0],
std::minus<int>{});
}
// could also be this - honestly it's a little hairy
// and making it behave well with an empty array
// requires an extra check. Yuck.
int sub2(int numcount, int numarr[]){
return numarr[0] - add(numcount-1, numarr+1);
}等。
如果允许使用std::array (在所有容器上抽象迭代器对),则切换到使用C++20或使用范围会稍微好一些。
如果必须使用C数组(而且它们在通过另一个函数的过程中不会衰减到指针),则可以编写
template <std::size_t N>
int add(int (&numarr)[N]){
return std::accumulate(numarr, numarr+N, 0);
}为了节省一些样板(到处传递numcount只是一个错误的机会)。
注意:正如链接的文档中所提到的,std::accumulate是我们从原始代码中抽象出来的事物“(特殊的”高阶函数“)的实现,您可以使用相同的std::plus、std::minus等操作符函数编写自己的foldl模板函数。
发布于 2022-09-07 15:52:57
您可以使用std::accumulate
auto adder = [](auto accu,auto elem) { return accu + elem; };
auto multiplier = [](auto accu, auto elem) { return accu * elem; };
auto sum = std::accumulate(std::begin(arr),std::end(arr),0,adder);
auto prod = std::accumulate(std::begin(arr),std::end(arr),0,multiplier);sub的结果就是2*arr[0] - sum。
请注意std::accumulate的初始值。它决定了返回类型,并乘以很多int很容易溢出,可能使用0LL而不是0。
在std::accumulate或任何其他标准算法都适合的情况下,您发现自己编写的函数非常类似,只有通过一个特定的操作才不同,您可以重构将函子传递给一个函数,该函数允许调用方专门指定要应用的操作:
template <typename F>
void foo(F f) {
std::cout << f(42);
}
int identity(int x) { return x;}
int main() {
foo([](int x) { return x;});
foo(identity);
}在这里,foo将调用参数42调用的结果打印到控制台。main用lambda表达式调用它一次,用空闲函数调用一次。
发布于 2022-09-07 16:07:55
我们如何尽量减少这个程序中的代码重复?
这样做的一种方法是有一个char类型的参数,表示需要执行的操作,如下所示:
//second parameter denotes the operator which can be +, - or *
int calc(int numcount, char oper, int numarr[])
{
//do check here that we don't go out of bounds
assert(numcount > 0);
int total = numarr[0];
// do the operatations for all the numbers in the array
for (int i = 1; i < numcount; i++){
total = (oper == '-') * (total - numarr[i]) +
(oper == '+') * (total + numarr[i]) +
(oper == '*') * (total * numarr[i]);
}
return total;
}
int main()
{
int arr[] = {1,2,3,4,5,6};
std::cout << calc(6, '+', arr) << std::endl; //prints 21
std::cout << calc(6, '-', arr) << std::endl; //prints -19
std::cout << calc(6, '*', arr) << std::endl; //prints 720
}https://stackoverflow.com/questions/73638098
复制相似问题