Closed7
AtCoder C++入門の覚え書き #3-1 キャスト、size_t、printf+string, map, 演算子オーバーロード etc
型のキャスト
キャストのやり方。
int a = 2;
double b = 0.01;
b = (double) a;
暗黙のキャスト
int a = 2;
double b = 0.01;
cout << a + b << endl;
cout << (double) a + b << endl; //上と同じ意味
doubleやfloatをint型に変換すると 小数点以下は切り捨てられる
cout << (int) 3.99 << endl; // 3
文字列変換のための関数
stoi("7"); // int
stoll("8"); // int64_t
stod("3.14"); // double
stof("3.14"); // float
size_t 型
配列長を取る size_t
型は unsigned long なので、数値を加工する際に負になるとオーバーフローしてしまう。
無限に近いループ
vector<int> arr = {}; // 長さゼロの配列
for (int i = 0; i <= arr.size() -1; i++ ) { // arr.size() -1 がオーバーフローする
cout << i;
}
// (int) にキャストすれば意図した動作になる
for (int i = -1; i <= (int) arr.size() - 1; i++ ) {
cout << i; // 1回だけ出力される
}
printf() scanf()
printf()
cout
を使わなくてもフォーマット指定で printf()
で出力できる。
ただし、 stringを出力する際には注意
。 s.c_str()
を実行する必要がある。
string str = "hoge";
printf("string: %s", str.c_str());
scanf()
scanf()
を使えばフォーマット指定で入力を取れる。
int i;
scanf("i = %d", &i);
scanf() で string を読むのは一筋縄ではいかない。
char c[100];
int i;
scanf("s = %4s, i = %d", &c, &i); // "s = hoge, i = 7"
printf("s = %s, i = %d", c, i);
ちなみに char[]
の string
への暗黙キャストはちゃんと行われるのでそこは安心。
vector<char>
から string
への変換は、stringのコンストラクタを使う。
vector<char> c = { 'a', 'b', 'c' };
string s(c.begin(), c.end()); // "abc"
pair, tuple, tie, ignore
- 2組の決まった型を組み合わせて使えるのが
pair<type, type>
型 - 任意数の決まったかたを組み合わせられるのが
tuple<type, type, (...)>
型 -
tie()
で任意の個別の変数にpair, tuple型の値をアサインできる -
tie(ignore)
で任意番目の値の代入を無視できる
pair<string, int> p("hoge", 7);
tuple<string, int, bool> t("fuga", 2, false);
// pair, tupleの値を使う
cout << p.first << endl; // p.first, p.second が使える
cout << get<0>(t) << endl; // get<定数>(t) で任意番目の値にアクセスする。変数は使えない
// tie() で pair や tuple 型の値を個別の変数に格納できる。
string ps;
int pi;
tie(ps, pi) = p;
string ts;
int ti;
bool tb;
tie(ts, ti, tb) = t;
// tie() 中に ignore を入れて値セットの一部の代入を無視できる
tie(ignore, ti, ignore) = t; // ti = get<1>(t)
make_pair() と make_tuple()
make_pair()
make_tuple()
を使ってそれぞれの型のデータを作れる。
pair<string, int> p;
p = make_pair("hoge", 2);
tuple<string, int, bool> t;
t = make_tuple("fuga", 3, true);
map, setはkeyごとにソートされているため、データの挿入と削除に O(log N)
かかる。
ソートする必要がなければ unordered_map
や unordered_set
を代わりに使うことを検討する(平均 O(1)
で動作)
map
map<string, string> m;
string key = "hoge";
m[key] = "fuga"; // 値の追加
m.erase(key); // 値の削除
m.at(k); // 値へのアクセス
m.count(k); // 存在確認
m.size(); // データ数を取得
// 値へのアクセス補足
cout << m.at("no-data") << endl; // 値がない場合エラー
cout << m["no-data"] << endl; // 値がない場合初期値が追加される。m.size()の値が1増える
queue, priority_queue
queueのメソッドはJSの配列と似ているが、細かく違うので気をつける。
特に pop() は要素を削除するだけで値は返さない
点に注意。
最前列の値を取りたければ front()
でアクセスすること(priority_queueの場合は top()
)
queue<int> q;
q.push(3);
q.push(2);
while (!q.empty()) {
cout << q.front() << endl;
p.pop()
}
queueとpriority_queueの違いは以下。
- 先頭要素の取得方法
q.front()
pq.top()
- priority_queueはソートが入るので
pop()
push()
の計算量がO(log N)
その他
- stack, deque(queue+stack)などがある
- unordered_set, unordered_mapの値の追加削除は平均
O(1)
-
*lower_bound(begin, end, i)
*upper_bound(begin, end, i)
覚える
演算子オーバーロード
なかなか使い所がイメージできないので後で必要なときに学ぶことにする。
このスクラップは2023/10/11にクローズされました