O - 1.14.STLの関数 /

Time Limit: 0 msec / Memory Limit: 0 KB

前のページ | 次のページ

キーポイント

  • 関数を使うとプログラムのまとまった機能を簡単に使うことができる
  • C++で用意されている、関数等がまとまっているもののことをSTLという
  • 関数名(引数1, 引数2, ...)で関数を呼び出せる
  • 関数に( )で渡す値のことを引数という
  • 関数の計算結果のことを返り値または戻り値という
  • 引数と返り値は型のルールが決まっており、間違えるとコンパイルエラーになる
関数 min(a, b) max(a, b) swap(a, b)
機能 aとbのうち小さい方の値を返す aとbのうち大きい方の値を返す 変数aと変数bの値を交換する
関数 sort(vec.begin(), vec.end()) reverse(vec.begin(), vec.end())
機能 配列変数vecをソートする(要素を小さい順に並び替える) 配列変数vecの要素の並びを逆にする

STLの関数

関数を使うとプログラムのまとまった機能を簡単に使うことができます。

「C++の関数」と「数学の関数」は似た部分もありますが、基本的には別物であることに注意してください。

関数の使い方

「2つの変数の値のうち小さい方を出力するプログラム」を例として見てみましょう。

関数を使わないで書く場合、次のようになります。

#include <bits/stdc++.h>
using namespace std;

int main() {
    int a = 10, b = 5;

    int answer;
    if (a < b) {
        answer = a;
    }
    else {
        answer = b;
    }

    cout << answer << endl;
}
実行結果
5

「min関数」を使えば次のように書くことができます。

#include <bits/stdc++.h>
using namespace std;

int main() {
    int a = 10, b = 5;

    int answer = min(a, b); // min関数

    cout << answer << endl;
}
実行結果
5

プログラム中で出てくるminは2つの値のうち小さい方を求める関数です。
min(a, b)の「計算結果」としてabの小さい方の値が取得できるので、それを変数answerに代入しています。

STLとは

C++ではminの他にも様々な関数が用意されており、多くの機能を自分でプログラムを書くこと無く利用できます。
C++で用意されている、関数等がまとまっているもののことをSTL (Standard Template Library)といいます。

関数を自分で作る事もできます。それについては「1.15.関数」で説明します。

関数の呼び出し方

関数を使うことを関数呼び出しと言います。

関数呼び出しの記法は以下のとおりです。

関数名(引数1, 引数2, ...)

引数(ひきすう)とは、関数に渡す値のことです。min(a, b)では変数aと変数bがそれに当たります。
min関数では2つの引数がありましたが、引数の数は関数によって異なります。

関数の計算結果の値のことを返り値(かえりち)または戻り値(もどりち)と言います。
int answer = min(a, b);ではmin関数の返り値を変数answerに代入しています。

引数と返り値の型

引数と返り値は関数によって型のルールが決まっており、間違うとコンパイルエラーになります。

次のプログラムは、min関数の引数にint型とstring型を渡そうとして、コンパイルエラーが発生しています。

#include <bits/stdc++.h>
using namespace std;

int main() {
    string s = "hello";

    int a = min(10, s); // min関数にint型とstring型のペアは渡せない

    cout << a << endl;
}
コンパイルエラー
./Main.cpp: In function ‘int main()’:
./Main.cpp:7:22: error: no matching function for call to ‘min(int, std::string&)’
     int a = min(10, s); // min関数にint型とstring型のペアは渡せない
                      ^
(この後長々とエラー文が続く)

STLの関数の使い方を間違えると、非常に長いコンパイルエラー文が出ることがあります。


関数の例

STLの関数の中から3つの関数を紹介します。
これらを暗記しておく必要はありませんが、「この処理はSTLの関数でできた気がする」と思い出して調べられることが大切です。

min関数

min関数は、2つの引数のうち小さい方の値を返します。

#include <bits/stdc++.h>
using namespace std;

int main() {
    int answer = min(10, 5);

    cout << answer << endl; // 5
}
実行結果
5

引数と返り値の型

引数と返り値の型はintdoubleのような数値型(または大小比較が出きる型)ならなんでも良いです。

#include <bits/stdc++.h>
using namespace std;

int main() {
    double answer = min(1.5, 3.1);

    cout << answer << endl; // 1.5
}
実行結果
1.5

ただし、2つの引数の型は同じである必要があります。

#include <bits/stdc++.h>
using namespace std;

int main() {
    double a = 1.5;
    int b = 10;
    int answer = min(a, b); // 引数の型がdouble型とint型なのでエラーになる
}
コンパイルエラー
./Main.cpp: In function ‘int main()’:
./Main.cpp:7:26: error: no matching function for call to ‘min(double&, int&)’
     int answer = min(a, b); // 引数の型がdouble型とint型なのでエラーになる
                          ^
(この後長々とエラー文が続く)

max関数

max関数は、2つの引数のうち大きい方の値を返します。

#include <bits/stdc++.h>
using namespace std;

int main() {
    int answer = max(10, 5);

    cout << answer << endl; // 10
}
実行結果
10

引数と返り値の型

引数と返り値の型についてはminと同様です。

swap関数

swap関数は、2つの引数の値を交換します。

#include <bits/stdc++.h>
using namespace std;

int main() {
    int a = 10, b = 5;

    swap(a, b);

    cout << a << endl; // 5
    cout << b << endl; // 10
}
実行結果
5
10

引数と返り値の型

2つの引数の型は同じである必要があります。
また、swap関数に返り値はありません。このように、返り値が無い関数もあります。


配列を引数にする関数

STLの関数の中から、配列を引数に渡す2つの関数を紹介します。
STLの関数に配列を渡す場合、少し特殊な形式で書く必要があることに注意してください。

reverse関数

reverse関数を使うと、配列の要素の並びを逆にできます。

#include <bits/stdc++.h>
using namespace std;

int main() {
    vector<int> vec = {1, 5, 3};
    reverse(vec.begin(), vec.end()); // {3, 5, 1}

    for (int i = 0; i < vec.size(); i++) {
        cout << vec.at(i) << endl;
    }
}
実行結果
3
5
1

reverse関数は次の形式で呼び出します。

reverse(配列変数.begin(), 配列変数.end());

reverse関数に返り値はありません。

sort関数

データ列を順番に並び替えることをソートといいます。
sort関数を使うと、配列の要素を小さい順に並び替えることができます。

#include <bits/stdc++.h>
using namespace std;

int main() {
    vector<int> vec = {2, 5, 2, 1};
    sort(vec.begin(), vec.end()); // {1, 2, 2, 5}

    for (int i = 0; i < vec.size(); i++) {
        cout << vec.at(i) << endl;
    }
}
実行結果
1
2
2
5

sort関数は次の形式で呼び出します。

sort(配列変数.begin(), 配列変数.end());

sort関数に返り値はありません。

sort関数とreverse関数の組合せ

sort関数を使ってからreverse関数を使うと、大きい順にソートできます。

#include <bits/stdc++.h>
using namespace std;

int main() {
    vector<int> vec = {2, 5, 2, 1};
    sort(vec.begin(), vec.end()); // {1, 2, 2, 5}
    reverse(vec.begin(), vec.end()); // {5, 2, 2, 1}

    for (int i = 0; i < vec.size(); i++) {
        cout << vec.at(i) << endl;
    }
}
実行結果
5
2
2
1

ソートは様々な計算で使われる非常に重要な処理なので、使い方を覚えておきましょう。

配列を渡す形式

STLの関数に配列を渡す場合、次の形式で渡すことが多いです。

関数名(配列変数.begin(), 配列変数.end())

この記法について完全に理解するにはイテレータという機能の知識が必要ですが、それについては後の章で扱います。
とりあえず今の段階では、こう書けば関数の機能を利用できるということだけ理解しておきましょう。


細かい話

細かい話なので、飛ばして問題を解いても良いです。

引数で関数を呼び出した場合

次のプログラムのように、引数で関数を呼び出した場合は内側の関数から実行されます。

min(max(1, 2), 3)
↓
min(2, 3)
↓
2

引数の実行順序

引数の実行順序は環境によって異なります。APG4bの推奨環境である「GCC, C++14」では、次のように最後の引数の式から順に実行されます。

min(1 + 1, 2 + 2)
↓
min(1 + 1, 4)
↓
min(2, 4)
↓
2

その他の環境(Clang等)では、次のように最初の引数の式から順に実行されることがあります。

min(1 + 1, 2 + 2)
↓
min(2, 2 + 2)
↓
min(2, 4)
↓
2

このことを気にする必要がある場面は少ないですが、次の節のように自分で関数を定義する場合はハマりどころになりうるので、頭の片隅においておきましょう。


問題

リンク先の問題を解いてください。

ABCの問題

AtCoder Beginner Contestからソートを活用できる問題を紹介します。
次の2問は「1.13.配列」で「難しめ」として紹介したものですが、ソートを使えばもっと簡単に解くことができます。

前のページ | 次のページ