这来自other question。如果我们有:
const std::string& S = ...;
int freq[CHAR_MAX-CHAR_MIN+1]={0};
以下四个循环是否相同?你更喜欢什么?
for (int c: S) ++freq[c-CHAR_MIN]; // (1)
for (char c: S) ++freq[c-CHAR_MIN]; // (2)
for (unsigned c: S) ++freq[c]; // (3) <-- BAD!
for (unsigned char c: S) ++freq[c]; // (4)
答案 0 :(得分:3)
2是最佳选择,因为它清楚地展示了您打算使用每个角色的内容(非常简单:作为角色)。这意味着在1,3和4中丢失。正如Rapptz所提到的,如果你有一个支持它的编译器(C ++ 11标准),你也可以使用for (auto c : S)
。
此外,没有必要在int(1),unsigned int(3)或unsigned char(4)中存储char,因为它们可以存储大于char的值。
答案 1 :(得分:1)
使其适当通用:
#include <limits>
#include <vector>
template <typename C, typename T = typename C::value_type>
std::vector<unsigned> histogram(C const& container)
{
std::vector<unsigned> result(std::numeric_limits<T>::max() - std::numeric_limits<T>::min());
for(auto& el : container)
result[el - std::numeric_limits<T>::min()]++;
return result;
}
现在,这将导致大型元素类型T
的无用大型结果向量(无论输入长度如何)。考虑使用地图:
// for very large char types, consider
#include <map>
template <typename C, typename T = typename C::value_type>
std::map<T, unsigned> histogram_ex(C const& container)
{
std::map<T, unsigned> result;
for(auto& el : container)
result[el]++;
return result;
}
一些使用示范:
#include <algorithm>
#include <string>
#include <iostream>
int main()
{
auto v = histogram (std::string ("hello world"));
auto m = histogram_ex(std::wstring(L"hello world"));
std::wcout << L"Sum of frequencies: " << std::accumulate(v.begin(), v.end(), 0) << "\n";
for (auto p : m)
std::wcout << L"'" << p.first << L"': " << p.second << L'\n';
}
打印:
Sum of frequencies: 11
' ': 1
'd': 1
'e': 1
'h': 1
'l': 3
'o': 2
'r': 1
'w': 1
全部查看 Live on Coliru
答案 2 :(得分:0)
我自己找到了答案,到目前为止没有其他答案,所以我回答了我自己的问题。
循环不等同。在(3)中,如果char
已签名且值为-1
,则会将其转换为unsigned
,其符号扩展名为4294967295
。
至于个人偏好哪个循环更好,我更喜欢(4),因为它不依赖于<limits.h>
。
修改强>
(3)可能无法在非二补码系统上正常工作。所以(1)和(2)更好。将char
转换为int
(或size_t
)时,不应听不到任何表现。