C++プログラミングのまとめ
概要
大学の講義や普段している競プロの勉強の中で学んだC++の知識についてまとめます。自身の備忘録的な側面もありますが、できるだけ他の人が見ても分かってもらえるようにまとめていきたいです。
更新履歴
更新日 | 更新内容 |
---|---|
2022/10/25 | 記事作成 |
2022/10/25 | 「C++のクラス機能」を追加 |
2022/11/03 | 「C++のクラス機能」を更新 |
2022/11/08 | クラスの配列とメモリ演算子について追加 |
2022/11/15 | ポインタのお話と参照について追加 |
2022/11/22 | 関数のオーバーロードについて追加 |
2022/11/29 | 演算子のオーバーロードについて追加 |
2022/12/07 | 継承のアクセス性、多重継承について追加 |
2022/12/13 | C++の入出力について追加 |
2022/12/20 | マニピュレータの作成について追加 |
C++の基本文法
デフォルト引数
関数の呼び出し時に指定されない引数があるとき、対応する仮引数にデフォルトの値を設定できる。
void f(int a = 0, int b = 0){
cout << "a:" << a << ", b:" << b << '\n';
}
int main(){
f(); // -> a:0, b:0
f(10); // -> a:10, b:0
f(10, 99); // -> a:10, b:99
}
C++の入出力システム
プログラム実行開始後に開く4つのストリーム
名前 | 機能 |
---|---|
cin | 標準入力 |
cout | 標準出力 |
cerr | 標準エラー出力 |
clog | バッファ付き出力 |
iosのメンバー関数による書式設定
書式セットに用いる関数:fmtflags setf(fmtflags flags);
書式リセットに用いる関数:void unsetf(fmtflags flags);
flagの種類
flag | 書式 |
---|---|
skipws | ストリーム入力中に先頭の空白文字を読み飛ばす |
left | 左寄せ |
right | 右寄せ |
internal | 符号と数字の間にブランクを入れる |
dec | 10進数表記 |
oct | 8進数表記 |
hex | 16進数表記 |
showbase | 基数表示 |
showpoint | 浮動小数点の出力で小数点、右端の0、eを表示 |
uppercase | 数字の前に符号を表示 |
scientific | 実数値を浮動小数点表示 |
fixed | 固定小数点表示 |
unitbuf | 出力ごとにすべてのストリームにフラッシュ |
Stdio | 出力ごとにstdout, stderrをフラッシュ |
flagの使用例。[stream]
にはcinやcoutのような作用させたいストリーム名を入れる。
[stream].setf(ios::showpoint);
[stream].setf(ios::showpoint | ios.fixed);
入出力マニピュレータ
入出力文字の内部で使用できる特別な入出力書式関数。endlなどもこれに含まれる。使用例:
#include <iomanip>
cout << hex << 100 << endl; // => 64
cout << oct << 10 << endl; // => 12
cout << setfill('X') << setw(10);
cout << 100 << " hi " << endl; // => XXXXXXX144 hi
<<演算子と>>演算子をオーバーロードする
class Coord {
int x, y;
public:
Coord() { x = 0; y = 0; }
Coord(int i, int j) { x = i; y = j; }
friend ostream& operator<<(ostream& stream, Coord ob);
friend istream& operator>>(istream& stream, Coord &ob);
};
ostream& operator<<(ostream& stream, Coord ob) {
stream << ob.x << ", " << ob.y << '\n';
return stream;
}
istream& operator>>(istream& stream, Coord &ob) {
cout << "座標を入力:";
stream >> ob.x >> ob.y;
return stream;
}
独自マニピュレータの作成
入力マニピュレータであればistream
、出力マニピュレータであればostream
istream &マニピュレータ名(istream &stream){
// 独自のプログラムコード
return stream;
}
ostream& setup(ostream& stream) {
stream.width(10);
stream.precision(4);
stream.fill('*');
return stream;
}
ostream& note(ostream& stream) {
stream << "注意:";
return stream;
}
int main() {
cout << setup << 123.123456 << endl;
cout << note << "消灯" << endl;
}
ファイル入出力
fstreamヘッダをインクルードする。3つのストリーム(ifstream in; ofstream out; fstream io;)がある。
ofstream fout("test.txt"); // 出力ファイルを作成する
if (!fout) {
cout << "出力ファイルが開けません" << endl;
return 1;
}
fout << "Hello!" << endl;
fout << 100 << ' ' << hex << 100 << endl;
fout.close();
ifstream fin("test.txt"); // 入力ファイルを開く
if (!fin) {
cout << "入力ファイルが開けません" << endl;
return 1;
}
char str[80];
int i;
fin >> str >> i;
// while (!fin.eof()) {
// fin >> ch;
// if (ch == ' ') ch = '|';
// if (!fin.eof()) fout << ch;
// }
cout << str << ' ' << i << endl;
fin.close();
その他の出力設定
以下の設定は、出力のたびに設定しなおす必要がある。
- フィールド幅の調整:
streamsize width(streamsize w);
- 精度の調整:
streamsize precision(streamsize p);
- 充填文字の設定:
char fill(cahr ch);
C/C++のポインタ
ポインタ、アドレスとは
プログラム上で用いられる値(数値や文字列、配列)は、コンピュータの中のメモリというところに保存されている。あるデータが、どこのメモリに保存されているか分かるように、メモリにはそれぞれに住所が振れられていて、これがアドレスである。ポインタとは、このアドレスを覚えておく変数にあたる。
例を用いて、次のような対応関係を考える。
例え | コンピュータ上の用語 |
---|---|
人 | データ |
家 | メモリ |
住所 | アドレス |
住所のメモ | ポインタ変数 |
人に会いに行く | データを読み込む |
ある人Aさんが住所aaaに住んでいるに住んでいた。Aさんに会いに行くためには、この住所を覚えておく必要があるだろう。そこでAさんの住所をメモしておく。こうすれば、毎回住所を聞かなくても、このメモを見てAさんを訪ねることができる。
この例におけるメモが、プログラム上のポインタ変数に当たります。伝わりますでしょうか…。分かりづらいなどあれば、コメントまでお願いいたします。
ポインタ変数の基本
- ポインタ変数の宣言は、型名(もしくは変数名の前)に「*」を付けて行う。
- 変数のアドレスは、変数名の前に「&」を付けて参照できる。
- アドレスの先に保存されている値を参照するには、ポインタ変数の前に「*」を付ける。
int main(){
int num = 1; // int型変数
int *p_int; // int型ポインタ変数
p_int = &num // 変数numのアドレスをポインタ変数に代入
cout << p_int << '\n'; // 変数numのアドレスを表示
cout << *p_int << '\n'; // 変数numの値(=1)を表示
}
ポインタの性質
- ポインタ変数には、int型のポインタ、char型のポインタのように型がある。
- アドレスを保存したいデータの型とポインタの型は、一致させる必要がある。
- 配列はデータが連続したアドレスに保存される。
- 配列の変数名を書くと、配列の先頭アドレスを参照できる。
(ポインタ) + 1
のように書くと、配列の1つ隣の値のアドレスになる。- (応用)char型のポインタに+1をすると、隣の要素のアドレスは1増える。int型のポインタに+1すると、隣の要素のアドレスは4増える。これは、char型が1バイト(アドレス1番地分)、int型が4バイト(アドレス4番地分)で保存されているためである。
int main() {
int i_arr[] = {0, 1, 2, 3};
int *p_int;
p_int = i_arr; // 配列の先頭アドレスが格納される。
// &i_arr[0] == i_arr となり、どちらも配列の先頭アドレスを返す。
p_int = &i_arr[1] // 配列の2番目の要素のアドレスが格納される。
// &i_arr[1] == (i_arr + 1) となり、ポインタ+1で配列の次の要素を参照できる。
}
ポインタの詳しい話
- ポインタ変数aは、ポインタをデータとして保存しているから、そのポインタの変数aの保存先アドレスも別で存在する(ポインタのポインタ)
- ポインタのポインタを使うとクラスの配列の宣言が楽に行える。
参照(関数に変数を渡す)
- 何もせずに関数の引数に変数を渡すと、その変数のコピーが関数の中で扱われる。
- 引数で渡した元の変数をいじりたい場合は、その変数のアドレス(ポインタ)を渡していじれるようにする(ポインタ渡し)か、引数を参照で受け取るように指定する(参照渡し)必要がある。
- ポインタ渡しは、仮引数の変数はあくまでもポインタ変数であって、値にアクセスするには「*」が必要。
- 参照渡しは、仮引数の変数を呼び出しで渡したものと同じものとして扱う。
void f1(int n){ n = 1; } // main関数のnは変更されない。
void f2(int* n){ *n = 1; } // ポインタ渡し。ポインタの指し示す先の値(「*」を付けて)を変更する。
void f3(int& n){ n = 1; } // 参照渡し。
C++のクラス機能
クラスという概念についての説明は、ここで始めるとキリが無くなってしまうので、この記事では省きます。今後、クラスを始めとするオブジェクト指向についての説明も時間があるときに書きたいと思います。
クラスの定義
class (クラス名) {
private:
// プライベートメンバの宣言
int a;
void calc(int x, int y);
public:
// 公開メンバの宣言
double num;
void setA(int a);
};
メンバのアクセス性はコロン「:」で区切って宣言する。「private:」は省略できる。クラス宣言の最後にはセミコロンが必要。
メンバ関数の定義
void (クラス名)::calc(int x, int y){ (関数の内容); }
クラス名にコロン2つ「::」を付けて関数の中身を定義する。「::」はスコープ解決演算子と呼ばれる。
関数の多重定義(ポリモーフィズム)
int abs(int value){
return (value < ? -n : n);
}
double abs(double value){
return (value < ? -n : n);
}
同じ関数名でも、引数の型によって複数定義することができる。
コンストラクタ関数 / デストラクタ関数
class MyClass {
public:
MyClass(); // コンストラクタ
~MyClass(); // デストラクタ
}
MyClass::MyClass(){ ~~~ } // コンストラクタの実装
MyClass::~MyClass(){ ~~~ } // デストラクタの実装
インスタンスが生成されるときにコンストラクタが呼び出され、インスタンスが破壊されるとき(スコープ外になる/プログラム終了時)にデストラクタが呼び出される。
コンストラクタ/デストラクタの名前はクラス名と同じにし、戻り値は定義しない。デストラクタの場合はクラス名にチルダ「~」を付す。
コンストラクタの多重定義 / コピーコンストラクタ
- 柔軟性を得る
- 配列をサポートする
- コピーコンストラクタを作成する
コピーコンストラクタ。
class A {
int* a;
public:
A(int b){ a = new int(b); }
A(const A& ob);
}
A::A(const A &ob){
int value = *ob.a;
a = new int;
*a = value;
}
メンバへのアクセス
#include <iostream>
using namespace std;
class MyClass {
private:
int a;
public:
int num = 5;
void setA(int n);
};
void MyClass::setA(int n) {
a = n;
}
int main() {
MyClass myC1;
MyClass* p;
p = &myC1;
myC1.setA(10);
cout << myC1.num << " == " << p->num;
}
メンバ変数、メンバ関数へのアクセスは、ドット演算子「.」で行える。
ポインタを用いたインスタンスのメンバーへのアクセスは、アロー演算子「->」を使って行える。
クラスの継承
あるクラスが他のクラスの機能を受け継ぐ仕組み。
図形クラス(基本クラス):高さと幅の変数
四角形クラス:面積を計算するメソッド
図形クラスを継承した四角形クラスでは、図形クラスの持つ高さと幅の変数を参照できる。
class A {
int i;
public:
void func();
};
class B : public A {
int j;
};
継承したいクラスを、クラス名の後ろにコロン「:」を付けて追加する。継承したいクラス名にpublicを付けると、親クラスのpublicメンバーがpublicのまま引き継げる。
コンストラクタは親クラスが先に呼ばれ、デストラクタは子クラスが先に呼ばれる。
親クラスのコンストラクタに引数を渡す場合には、次のように記述する。
class B : public A{
int j;
public:
B(int n, int m) : A(m) { j = n; }
}
クラスの多重継承
一般形:
class クラス名 : [アクセス演算子] 基本クラス名1, [アクセス演算子] 基本クラス名2, ...{
// クラスの定義
}
また、多重定義の場合のコンストラクタの呼び出しは次の形式で記述する。
クラス名(引数) : 基本クラス名1(仮引数), 基本クラス名2(仮引数), ...{
// コンストラクタの定義
}
派生クラスが複数の基本クラスを継承する際、その基本クラスが同一のクラスが継承しているかもしれない。これにより、どちらの最上位クラスを参照するのか分からなくなってしまう。このときに仮想基本クラスを用いて、1つしか含まれないようにする。
class Base { ... };
class Derived1 : virtual public Base{ ... };
class Derived2 : virtual public Base{ ... };
// 基本クラスのコピーは1つしか持たない
class Derived3 : public Derived1, public Derived2{ ... };
クラスの継承のアクセス制御
一般形:
class クラス名:[アクセス指定子] 基本クラス名{
// クラス定義
}
- アクセス指定子をpublicにした場合、class A, B両方のpublicメンバにアクセスが可能。protectedのメンバはprivateの扱いになる。
- アクセス指定子をprivateにした場合、class Bのpublicメンバにのみアクセスが可能
- アクセス指定子をprotectedにした場合、クラスBの中であればクラスAのprotectedとpublicメンバにアクセス可能(≒private)
class B : public A
クラスのファイル分割
クラス用のヘッダーファイルとソースファイルを別に作成して管理する。
VisualStudioでは、「ヘッダーファイルフォルダ」と「ソースファイルフォルダ」にファイルを追加。
クラスの実装を書くソースファイルとmain関数のあるソースファイルでは、#include "(クラス名).h"
として宣言部をインクルードする。
クラスの配列
インスタンスは変数なので、配列として扱うことができる。
コンストラクタがある場合は、次のようにして呼び出す。なお、コンストラクタの引数が複数ある場合は、呼び出しを省略できない。
class A{
public:
A(int n){ ~~~ };
};
int main(){
A sample[4] = {-1, -2, -3, -4};
// これは {A(-1), A(-2), A(-3), A(-4)} が省略されている。
}
多次元配列の場合も同様に記述できる。
class A{
public:
A(int n){ ~~~ };
};
int main(){
A sample[2][2] = {
-1, -2,
-3, -4
};
// これは {A(-1), A(-2), A(-3), A(-4)} が省略されている。
}
ポインタのポインタを使うことにより、for文などで個々にコンストラクタを呼び出せる。
int main() {
MyClass** p;
p = new MyClass* [10];
// 個々にコンストラクタを呼び出す。
for (int i = 0; i < 10; i++) {
p[i] = new MyClass('A' + i);
}
return 0;
}
MyClassの実体はp[i] = new MyClass('A' + i);
で生成される。生成したものそれぞれアドレスが、配列としてpの中に保存されている。
C++のメモリ周り
メモリの割り当てと解放
用途 | C言語 | C++ |
---|---|---|
メモリの割り当て | malloc() | new演算子 |
メモリの解放 | free() | delete演算子 |
new演算子は、メモリの割り当てに失敗するとヌルを返す。
int main(){
int *p;
p = new int [5]; // 配列のメモリ割り当て
if(!p){ //メモリ割り当てエラー }
~~~;
delete [] p; // メモリを解放
}
演算子のオーバーロード
演算子の機能を、クラスによって各々に設定できる。
(戻り値) (クラス名)::operator(拡張したい演算子) (仮引数){
// 実行する処理
}
2項演算子のオーバーロード
class Vector2 {
int x, y;
public:
Vector2() { x = 0, y = 0; }
Vector2(int i, int j) { x = i; y = j; }
void GetXY(int& i, int& j) { i = x; j = y; }
Vector2 operator+(Vector2 obj);
int operator==(Vector2 obj);
};
int Vector2::operator==(Vector2 p) {
return x == p.x && y == p.y;
}
Vector2 Vector2::operator+(Vector2 p) {
Vector2 temp;
temp.x = x + p.x;
temp.y = y + p.y;
return temp;
}
単項演算子のオーバーロード
インクリメント演算子やデクリメント演算子では、前置と後置でそれぞれオーバーロードを作成する必要がある。
class Vector2 {
int x, y;
public:
Vector2() { x = 0, y = 0; }
Vector2(int i, int j) { x = i; y = j; }
void GetXY(int& i, int& j) { i = x; j = y; }
Vector2 operator++(); // 前置用
Vector2 operator++(int a); // 後置用
};
Vector2 Vector2::operator++() {
++x;
++y;
return *this;
}
Vector2 Vector2::operator++(int as) {
Vector2 old = *this;
++* this;
return old;
}
QK REPORTに参加しました
6月12日に行われたQuizKnock主催の「学生記者発表会 QK REPORT」に参加しました。稚拙ながら、そこでの内容、得た知見、感じたこと、考えたことをまとめたいと思います。
この記事で初めてブログを見てもらう人も居るかと思いますので、簡単に私の自己紹介をしておきます。理工系の男子大学生で、主に情報工学などを専攻しています。理系でかつ男子大学生というと、QuizKnockの視聴者層からみてもなかなか少数なのかなと認識していますが、それだからこその独自の視点からお伝えしていきたいです。記事の内容は、イベントで伊沢さんや須貝さんがお話になっていた内容と、それについて私自身が考えたこと、という2部構成でやっていこうかと思います。
イベント概要
まずは、QK REPORTの概要をお伝えします。QK REPORTは、QuizKnockに対する質問を学生記者から直接募り、それにQuizKnockのメンバーが答えるというイベントです。今回の開催では、QuizKnockから伊沢さんと須貝さんが参加されて学生記者の質問に答えていました。それから、質問の受け答えを参加者が各々記事にして発信することで、より多くの人にQuizKnockを知ってもらいたいというねらいもあるようです。
私はQuizKnockをかれこれ3,4年は見ています。知的な好奇心をそそるコンテンツ、それを全力で楽しむ出演者などなど、どれをとっても本当に飽きることがありません。ただ、「好き」を的確に表現し伝えることの、なんと難しきことか…。私の記事でQuizKnockを広めるお手伝いになるか不安ですが、この記事を読んでくださる皆さんに、文章全体から私の「好き」や、QuizKnockの持つ飽きない「楽しさ」を感じ取っていただければなと思っています。
QuizKnockとしての伝え方
QuizKnockとして、また伊沢さん、須貝さんにとっての、物事を伝えるということについて沢山のお話をお聞きしました。その中から、自分なりの3つの視点で、そもそも物事を分かりやすく相手に伝えること、web記事やYouTube動画といった楽しめるコンテンツとして伝えること、最後にQuizKnockの掲げる「楽しいから始まる学び」を見据えた知る楽しみ、という風に分けてお伝えしようかと思います。
分かりやすい伝え方
物事を分かりやすく楽しく伝えるときの思考や気を付けていることについて、伊沢さんは分かってもらうための順序が大事であると言っていました。物事を伝えるときには、様々な定義や概念のような、分かるうえで無視してはいけないような事柄があります。そうしたものを、数学問題の誘導にように順序だてて、適切な順番で教えるということが分かるに繋がるだろうということでした。話の中では、先日再生回数1,000万回を達成したサマーウォーズの動画も例に挙げて、あの動画は順序だてという面でとてもしっかりしているという風にもおっしゃっていました。
須貝さんは、説明の際に言わないことを考えているということでした。例えば、科学の話題であれば、ある事柄を説明するために専門的な用語や数式を使うことで詳細までを話すことができます。それでも、そうした難しい言葉をあえて言わない、その途中に細かい難しい話で面白い内容が沢山あるんだけど、それも言わないでおこう。それで、聞き手に分かってもらって、もっと詳しく知りたいと思ってくれれば、いつでも話せる準備はしている、そんな風に話されていました。よく頭の良い人は説明が上手いと言われますが、そういう人たちも実際は専門用語を使わなくて良いところまでで話を留めて分からせてくれているのだといいます。
ここからは私の考えた話や感じたことになりますが、私も理系で大学受験を迎えて、数学の問題を沢山解いてきました。やっぱり問題どれも難しいんですが、伊沢さんのおっしゃっていたような問題の誘導に、何度も助けられ、そして感心したのを覚えています。序盤の(1)とか(2)は比較的優しめな問題も多くて、なんでこんなの解かせるんだろうという風にも思ったりもします。それが中盤以降の難しい問題になってきて、あっ、(1)で証明したこの式使えば解けるじゃんとか、複雑な式書いてあるけど(2)の式で変形したらできるじゃんとか、そういう伏線回収が登場します。それで難しい問題でも解けるんです。そんな解き方があったのかと、問題を解いている最中でも感心してしまいます。あと、やっぱり解けると嬉しいです。数学楽しい!ってなります。もう終わってしまいましたが、数学のセンター試験とかまさにそうで、誘導無しじゃ手も付けられないような難しい問題が、誘導に身を任せて解くことですらすら解けるんです。こうした数学の問題のような、適切な誘導を作って分かる・解けることを導くということを、普段の物事の伝え方へも応用すれば良いのだと気付かされました。
須貝さんのお話されていたあえて言わない説明ですが、私もそれを実践して人に伝わった経験があったので、うんうんと頷きながらお聞きしていました。以前友人に、その人がほとんど知らない「情報理論」という学問はどういうものなのかを話す機会がありました。難しい用語や式もあるんですが取り合えずその時は言わないで、イメージしやすい一般的な例示を用いて説明をしました。そうしたら、話した後に友人から「説明の仕方分かりやすいな」というようなことを言ってもらえたのが、今でも嬉しい記憶として残っています。物事を説明するのに、自分の知っている全てを詰め込んだような話を相手にするのではなくて、取り敢えず大枠だけでも理解してもらいたい、この学問の楽しい所だけでも知ってもらいたい、そんな想いからの説明でした。それが、相手にとっての新たな教養となり、その事柄なんか面白そうだな、気になるなというきっかけになってもらえたならば嬉しいですね。
あとは、今回のお話では出てこなかったものとして、説明するときに双方の理解している前提を共有するというのを私は普段意識してやっています。QuizKnockさんのような1対多の説明では難しいかもしれませんが、1対1など少人数に説明する上ではとても役立っています。前提を確認してから、その前提に立って説明をすることで、分かっていることを再度説明する二度手間を省けますし、説明箇所の相違などの非効率も防ぐことができます。だから、私が説明するときは、「ここまでは分かる?」とか「これはこういうことでやってみたんだよね?」とか、そういう確認をまずは行っています。
楽しめるコンテンツ
QuizKnockの提供する楽しさの1つに、分かる楽しさがあるということをお二人ともお話されていました。逆に分かりさえすれば面白くなるため、内輪ネタのようなものも須貝さんは大好きだという風に言っていました。
web記事や動画といったコンテンツを作るうえでより楽しいコンテンツを作り上げるために工夫されていることとしては、伊沢さんは発信者が楽しみを持って発信するということをお話されていました。動画などの映像メディアであれば、笑顔であることや笑っていることを意識されていると言います。YouTubeを始めたころはヒカキンさんをお手本にしていたそうです。ヒカキンさんは表情が分かりやすく、今何をしているのかが画面を見るだけでとても伝わってきます。伊沢さんとしても特にそこを大事にして、楽しいときに笑い、悲しいときに泣いて、悔しいときに悔しがるようにやっているということでした。また、web記事のような顔が見えないコンテンツにおいても、楽しそうな文章を書くということで、楽しみを表現しているといいます。
ここからは私の話になります。やっぱり分かる楽しさは最高なものだと思います。先ほど例にあげさせていただいた数学の問題でも、解き方が分かったときが私にとって一番楽しいです。うーんうーんと頭を悩ましているよりも、ある程度悩んで解けなそさそうであれば解答を見てみて、それで「あぁー!こう解くのかーー!」となる、これだけで気持ちが良いものです。次に同じ問題に出会ったときに、今度は解答を見ずに問題が解けたなら、成長した自分を感じることもできてもっと嬉しく、数学が好きになります。私は胸を張って「勉強が好きだ」と言えますが、好きな理由はやっぱりこの分かる楽しみがあるからです。QuizKnockを好きになった一因にも、コンテンツの中の分かる楽しみがあったのだと思います。
知るを楽しく
学生記者として質問した方のうちお一人は、web上のニュースメディアを運営されている方で、ニュースと絡めて知識をより広く知ってもらう、深く掘ってもらうという視点についても尋ねていました。須貝さんは、財テクにはまったことでニュースが自分ごとになり、ニュースに強く関心を持つようになったと言います。そのように自分ごとになって自分とニュースが繋がると、もっと詳しく知りたいだったり、関連する内容も気になるだったりして調べていく、そうして知識が広がっていくんだ、というふうにお話されていました。
伊沢さんは、クイズプレイ-として色々なことを知っていなければいけないというプレッシャーから、ニュースを見るようになったということでした。そいうった強いられる状況というのは便利ではあるものの楽しくはありません。そうではなくて、理解できた喜びやそんな見方があるのかと知ること、そういう何かをゲットしたんだという喜びを主軸にしたいと言っていました。ニュースを知らないと明日死ぬとかそうものではありません。それでもやっぱり知ったらちょっと嬉しい、自分が進化しているような進化の喜びを訴えていきたいということでした。
それから、知識を手に入れる手段を聞かれて、お二人ともそれは何であっても構わないということを言っていました。伊沢さんはどんなものでも逆に知識が増えないものの方が少ないと言っていました。須貝さんは小説を例に挙げられて、小説を読むにも物語の背景すべてを知っている訳ではないのだから、小説を読んで知ったことがあってもいいと言っていました。また逆に、作中に登場する事柄に興味をもって、それはなんだと調べ新しいことを知るというのでも良いだろうと話していました。
ここからは私の話になります。前の項でも話した知ることの喜び、言い換えれば知識欲というような点で、伊沢さんの話されていた内容はとても共感できるものでした。私もしょっちゅうニュースや新聞を読みます。きっかけはあまり明確には覚えていませんが、実家で朝の食卓にあったものを幼少期から眺めていたとことだと思います。いつの間にか、そこに並ぶ知らない出来事、知らない世界、美しい表現に興味をそそられ、面白さの対象として捉えていました。普段、数学や科学、テクノロジーの勉強を好きだと言って続けられるのも、新しい知識、その分野特有の物事の捉え方、そんなものを知るのが楽しいからです。
知識を手に入れる手段という点でも、僕は小学生でゲーム機を買ってもらって以来根っからのゲームっ子でした。それでも「桃鉄」で日本の地理を知って、「A列車で行こう」というシミュレーションゲームで経営の知識を知って、「とびだせどうぶつの森」というゲームで同級生と通信をして沢山の人とコミュニケーションがとれたと思っています。特にあまり自由にもなれない小中学生の頃に、そうやって知識を得ることができて良かったと思います。高校生になって以降は、自分の興味のある本が買えるようになったり、色々なイベントに参加できるようになったりして、ゲームをする時間は減ってしまいました。それでも、色々なイベントに出て色々な経験をして、色々な本を読んで、いろいろな出来事が起きて、そうして毎日のように新しいことを学ばせていただけるそんな日々を過ごしています。こう知ることが嬉しいというのは前々から感じていましたが、今回のお話の中で伊沢さんが「進化の喜び」だと表現されていたのがとても合っているなと思ったので、今後も使っていきたいです!
須貝さん、伊沢さんの高校時代の過ごし方
本イベントでは、伊沢さんや須貝さんの主に高校時代の過ごし方、どう勉強をしていたのか、クイズや部活をどう両立していたのかというようなお話をお聞きすることもできました。QuizKnockの魅力を発信するという目的からは少しそれてしまうかもしれませんが、その内容に非常に感銘を受けて伝えられたらなと思ったのでここに書かせていただきます。
伊沢さんは、高校時代からクイズ一筋の生活だったと言います。学校の同級生がみんないろいろなことに夢中になっていて、その中で伊沢さんのアイデンティティとなるものがクイズでした。クイズを通して伊沢さん自身何が得意で、何が苦手なのかを知ることができ、それが受験勉強にも役立ったとおっしゃっていました。
それから、いろいろなことについてを「高校生の時間のあるうちに探究しておくべきだった」ともおっしゃっていました。興味のある分野に突き進むみたいな、偏った勉強の仕方が、高校生のうちからできます。伊沢さんは大学に行けばそういうことができると考えていたそうですが、実際は大学生も大学生で、バイトをしたり学校に行ったり、意外と時間が無かったと言います。高校生の頃のスポンジのような柔軟性、自由度でそういうことができていたらな、という後悔を語られていました。具体的に「暗記アプリ作ればよかった」とも言っていて、当時から発想も需要もあったのに、自分で「作れない」という天井を決めてしまっていたのだと言います。そうした経験も踏まえて、「自分の壁を作らないことがめっちゃ大事」だと話してくださいました。
須貝さんは、勉強と部活の両立という点で、「宿題を家に持って帰らないようにしていた」そうです。宿題は休み時間に全部やるとか、昼休みは休まないとか、そうして放課後に部活のための時間を取れるようにしていました。授業中もその時間はやるべき時間が与えられているのだと考えて、全部集中する、サボろうとしない、そんな気持ちで取り組まれていたそうです。
高校時代を振り返った今では、もっと調べたら本当はもっとできることがあったのではないかと思っていると言います。学校の中には筋トレルームがあって借りることができたり、AETの先生が居て英作文の相談ができたりしました。そうしたものをもっと有効に使えていたら、野球部でももっと強くなれていたかもしれないし、もっと良い成績を残せていたかもしれません。そうしたことから須貝さんは 「今やっている「それ」をもっとより使える使い方があるんじゃないか」と探してみることが大事だという風におっしゃっていました。
ここからは私の話になります。伊沢さんの言っていた高校時代から「自分の壁を作らない」という話は、自分の高校時代を思い出しながら聞いていました。私は中学生の頃からプログラミングに興味があって、高校ではもっとできるようになるぞ!と意気込んでいました。それで、在学中からPythonでコードを書いてみたり、日本情報オリンピックというプログラミングの大会に参加してみたり、色々と取り組んでいました。少なくとも同じ学校の同学年の中では、プログラミングが1番できたかそれに近しいものでした。そういう状況で満足していた自分がいました。
大学生になりより広い視野を得るようになって、この時の私の満足には「自分の学校」という天井があったことに気が付きます。世の中には高校生の頃から国から支援を受けるほどプログラミングができる人が居たり、先ほどの情報オリンピックを優勝して大人にも勝るとも劣らない技術を持ち合わせる人が何人も居ました。自分はそういった存在は知らずに、学校の中では他よりもできるから、高校生としてやれることはやったものだと慢心していたんだと思い知りました。まさに井の中の蛙ですね。そういった慢心から、高校ではそれ以上もっと頑張れなかった、もうサボってしまったという後悔があります。
そういう私から、もし読んでくださっている高校生や中学生の方がいらっしゃったら伝えたいのは、自分の天井を決めないことはもちろんですが、それに加えてぜひ幅広く情報を集めてください。プログラミングだと情報オリンピックとかセキュリティキャンプとか未踏とか、高校生以下のあなたでも輝ける場所が沢山あります。他にも言語学や地学や物理などでも「○○甲子園」や「○○オリンピック」と銘打って、高校生向けのイベントが開かれていたりします。そして、そこには大人から同級生まで幅広い人々からなるコミュニティがあったりします。ぜひ自分の興味のある分野でそういうものを探してみて、今見えている天井のさらにその上の場所へ、広い視野で飛び出して行って欲しいです。
それから、須貝さんの言っていた授業中で全部集中するというのは、本当にそのとおりだと思って私も大学で実践しています。やっぱり授業の時間は決まっていて、その時間は教室から出られなかったり、オンライン授業でもzoomを聞いている必要があったり、少なからず自身の自由は制限されます。そういう制限された状況の中で何か他のことをして、授業後の完全に自由な時間でわざわざさっきの授業の確認や課題をやるのは、ものすごく非効率的だなと思います。授業中でがーっと集中して、それでもまだちょっと分からんなという時は授業後に復習の時間を作って、そうでなければ時間がかかるような課題をしたり、好きな他の勉強をしたり、疲れていたらちょっと休憩したり、そういう時間の使い方で有意義に時間を使いたいなと意識していることです。1人暮らしなので家事をしたりもあって、家ではやっぱりゆっくり時間を使いたいですね。
さいごに
いつも動画などで拝見しているお二人のお話ではありましたが、学生時代の過ごし方や日頃のコンテンツ制作の取り組み方など、普段目にしている姿とはまた違った視点からお話を聞くことができ、とても楽しい内容でした。この記事に書ききれていないこともたくさんありますが、他の方々の記事が投稿されているかと思いますので、そちらもご覧いただければなと思います。しっかりとした物書きが久しぶりだったり、ちょっと大学が忙しかったりで記事執筆が遅くなってしまい申し訳ありませんでした。
私事ではありますが、今年の初めごろにもっとアウトプットを増やしたい!という想いからこのブログを開設していました。それでも、やっぱりやる気を出すのはなかなか大変なことで、半ば放置気味という状況でした…。今回、QK REPORTというイベントが開かれる、しかも個人ブログ枠がある!ということで、これはQuizKnockさんが与えてくれた、アウトプットへの踏切版なのだと思い、本イベントに参加したという経緯があります。前に述べたような本イベントにおけるQuizKnockさんたちの思惑もあるとは思いますが、事柄には偶然的な要素が含まれることもあるということで、今回のイベント、この記事をきっかけに、学びの手段の1つとしてのブログでの情報発信を、今後も続けていけたらなと意気込んでおります。3日坊主になっても、また思い出した日にすぐ書きます。
こういう機会を設けていただき、ありがとうございました。また、似たようなイベントがあれば、今度はもっと余裕を持って参加したいと思います。
ここまでお読みいただきありがとうございました。
アウトプットを増やそうと思います。
ご挨拶
こんにちは、籾がらです。
色々なことを知るのが好きで、本を借りて勉強したり、ネットの文献を漁ってみたりしているのですが、知識のインプットばかりで、アウトプットが少ないなぁというのを前々から思っていました。
僕が学んだこと、普段の生活の中で得た知見を、頭の中で咀嚼して自分自身の言葉で消化できるように、こんなブログを作りました。普段は雑記的に知識を忘れないようにメモしておいて、ある程度知識がたまったら将来の自分のため、また、同じことを学ぼうとしている人のためにも、項目立ててまとめていけたら良いなと思っています。
内容は科学系と情報系が多くなります。記事の内容で誤っている点、もっと知りたいというような点などありましたら、コメントを頂けると嬉しいです。
拙い文章にはなりますが、今後ともよろしくお願いいたします。