为了使讨论具体化,假设一个简单的示例问题:用户输入几个没有空格的一位数字,按Enter
并得到这些数字的总和。因此,用户会话可能如下所示:
> 1231
7
> 12
3
> 0123
6
> ^D
我正在通过 C ++ Primer (第5版)学习C ++。在学习关于泛型算法的第10章之前,我将以下面的天真方式解决上述问题:
int main() {
std::cout << "> ";
std::string word;
while (std::cin >> word) {
auto sum = 0;
for (auto c : word) sum += c - '0';
std::cout << sum << std::endl << "> ";
}
return 0;
}
以下是我使用通用算法解决同样问题的方法:
int main() {
std::cout << "> ";
std::istream_iterator<std::string> in(std::cin), eof;
std::for_each(in, eof,
[](const std::string &word) {
std::cout << std::accumulate
(word.cbegin(), word.cend(), 0,
[](int cur, char ch) {
return cur + (ch - '0');
}) << std::endl << "> ";
});
return 0;
}
说实话,我更喜欢第一种解决方案。它简短易读。第二种解决方案牺牲了C ++ 11标准库的祭坛的简洁性和清晰度。
我的问题有三个:
我对两种解决方案的比较是否正确?
使用标准库的功能是否有更好的方法来解决示例问题?
如果在这种情况下天真的解决方案实际上是最好的解决方案,那么我在示例中使用的C ++ 11标准库的功能的实际用例是什么?
int main() {
std::cout << "> ";
std::istream_iterator<std::string> in(std::cin), eof;
std::ostream_iterator<int> out(std::cout, "\n> ");
using CStrR = const std::string &;
auto myAdd = [](int acc, char ch) {return acc + (ch - '0');};
auto mySum = [&](CStrR word) {
out = std::accumulate(word.cbegin(), word.cend(), 0, myAdd);
};
std::for_each(in, eof, mySum);
return 0;
}
答案 0 :(得分:2)
你可以写得更简单。例如
auto sum = std::accumulate( std::istream_iterator<char>( std::cin ),
std::istream_iterator<char>(),
0, []( auto acc, auto c ) { return acc += c -'0'; } );
std::cout << sum << std::endl;
或者
#include <iostream>
#include <numeric>
#include <string>
int main()
{
std::cout << "> ";
std::string word;
while ( std::cin >> word )
{
auto sum = std::accumulate( word.begin(), word.end(), 0,
[]( int acc, char c ) { return acc += c - '0'; } );
std::cout << sum << std::endl << "> ";
}
}
虽然有时使用普通循环而不是复合算法记录确实更好。:)
答案 1 :(得分:0)
请记住,这只是一个玩具示例,可以让您更容易理解一些复杂的概念。在实践中,您可能不会看到这么简单的代码。
你永远不应该*牺牲代码的清晰度。当计算机变得更快,新标准出现时,建议使用新的编码样式,您编写的代码不易于阅读,理解或调试。
因此对于这个特殊问题,较短的版本很可能是你想要的。 例如,如果您想支持cin但也支持字符向量,那么第二个版本更合适,因为您必须进行少量更改,但您也可以修改第一个版本。
始终了解适用于手头问题的内容,保持简单,不要害怕修改项目代码。
答案 2 :(得分:0)
问题不在于一般方法是错误的,而且通常众所周知C ++ stdlib过于冗长。委员会正在研究实际范围,这将使这个问题变得更简单,但它们还没有完成。
一个好的块也是完全不必要的换行符和相关的缩进罪。
int main() {
std::cout << "> ";
std::istream_iterator<std::string> in(std::cin), eof;
std::ostream_iterator<int> out(std::cout, "\n> ");
std::for_each(in, eof, [&out](std::string word) {
*out = std::accumulate(word.begin(), word.end(), 0, [](int cur, char ch) {
return cur + (ch - '0');
});
});
return 0;
}
如果您以合理的方式对其进行格式化,则会更具竞争力。
此外,最终,算法库不是为解决琐碎问题而构建的,它是为解决难题而构建的。