5. Tips¶
5.1. オーバーフローに注意¶
次のコードはyukicoder No.51の解答例である。
#include <iostream>
int main()
{
int W; std::cin >> W;
int D; std::cin >> D;
for(int i=0; i<D-1; i++)
{
W -= W/((D-i)*(D-i));
}
std::cout << W << std::endl;
return 0;
}
このコードはオーバーフローすることがある。
((D-i)*(D-i))
は全てint型から成るので、この一時的な結果はint型として保存される。しかし、この計算結果は最悪の場合int型の範囲を越えるためオーバーフローする場合がある。
オーバーフローさせないためにはDまたはiをlong long型にすればよい。
もう面倒くさいときは次のマクロ使っちゃえ(笑)
#define int long long
5.3. std::string¶
5.3.1. 文字列検索¶
findメソッドは頭から一致する文字列を検索する。戻り値はstd::string::size_typeで、整数型へのキャストも可能だが、std::string::nposとの比較の際に問題がでうるらしいので面倒くさがらずにsize_type型で受け取るようにすること。
std::string::size_type index = str.find("abc");
if(index == std::string::npos) std::cout << "not find";
rfindは後ろから検索する。
std::string::size_type index = str.rfind("abc");
5.3.2. 文字検索¶
文字検索にはfind_first_of、find_last_ofを使う。前者は頭から、後者は後ろから一致する文字を検索する。
std::string::size_type index = str.find_first_of("abc");
std::string::size_type index2 = str.find_last_of("abc");
これは’a’または’b’又は’c’に一致する最初の位置を返す。
5.3.3. tokenによる文字列分割¶
std::vector<std::string> split(const std::string &str, char sep)
{
std::vector<std::string> ret;
std::stringstream ss(str);
std::string buf;
while( std::getline(ss, buf, sep) )
{
ret.push_back(buf);
}
return ret;
}
5.3.4. 文字列挿入¶
std::string str("abc");
str.insert(2, "d");//添字2の要素の前に挿入
5.4. unsigned intの桁数取得¶
unsigned int digit(unsigned int n)
{
return (n==0 ? 1 : (int)log10(n)+1);
}
5.5. std::vector¶
5.5.1. 特定の値を削除する¶
erase-removeイディオムと呼ばれる方法が使える。
v.erase(std::remove(v.begin(),v.end(),100), v.end());//100に一致する要素を削除する。
std::removeは要素の削除を行わない。指定した値に一致する要素をコンテナの末尾に移動してその先頭iteratorを返すだけである。std::vector::eraseは指定した範囲を実際に削除する。このため上述のコードは所望の動作をする。
5.6. 自作ライブラリ¶
あると便利かな、と思うメソッドを作ってみた。バグあるかもなので注意。
5.6.1. vector中の各要素の数え上げ¶
#include <iostream>
#include <vector>
#include <algorithm>
template <class F> std::vector<std::pair<F, int> > count_elements(const std::vector<F> &V)
{
std::vector<std::pair<F, int> > ret;
std::vector<F> v = V;
std::sort(v.begin(), v.end());
F f0 = v[0];
int count = 0;
for(const auto &x: v)
{
if(f0==x)
{
count++;
}
else
{
ret.push_back(std::pair<F,int>(f0,count));
f0 = x;
count = 1;
}
}
ret.push_back(std::pair<F,int>(f0,count));
return ret;
}
int main()
{
std::vector<int> v(5);
v[0] = 0;
v[1] = 10;
v[2] = 0;
v[3] = 10;
v[4] = 1;
auto count = count_elements(v);
for(auto &x: count) std::cout << x.first << "(" << x.second << " ";
return 0;
}
戻り値はstd::vector<std::pair<F, int> >でfirstに一致する要素がsecond個あることを表す。