- プログラミングは,次のサイクルを繰り返します.
- ソースコードの作成・修正
- コンパイル
- 実行
- C++のソースコードのファイル名には,拡張子"
.cpp
"をつけてください - 本講義では,コンパイラ
g++
をオプション-std=c++11
付きで使用. - コンパイル例(ソースコードファイルを
prog1.cpp
,実行ファイルをprog1
とします): g++ -std=c++11 prog1.cpp -o prog1
- 実行例:
./prog1
.cpp
"をつけてくださいg++
をオプション-std=c++11
付きで使用.prog1.cpp
,実行ファイルをprog1
とします): g++ -std=c++11 prog1.cpp -o prog1
./prog1
以下のコードをprog1.cpp
という名前で保存し,コンパイル,実行してください.endl
の右端の文字l
はエルです.
#include <iostream> using namespace std; int main(){ cout << "Hello" << endl; }
cout
(標準出力)に"<<
"を使って文字列を代入(出力)することができます.例では,下記のようにHello
と改行(endl
)が端末へ出力されます../prog1 Hello
#include <iostream>
は,「標準入力や標準出力とのやりとりに必要なライブラリを使う」という意味.このプログラムでは必須以下のコードをprog1.cpp
という名前で保存し,コンパイル,実行してください
#include <iostream> #include <string> using namespace std; int main(){ string s1 = "選挙権は"; string s2 = "円周率は"; int age = 18; double pi = 3.14; cout << s1 << age << ", " << s2 << pi << endl; }
string
は文字列変数s1,s2
を,int
は整数型変数age
を,double
は浮動小数点型変数pi
のための「型」.#include <string>
は,文字列を扱うため./prog1 選挙権は18, 円周率は3.14
コマンドの引数を変数に代入することができます.そのためにmain
関数の書き方を変えます(引数がない場合も使えます).以下のコードをprog1.cpp
という名前で保存し,コンパイル,実行してください.引数があるので注意
#include <iostream> #include <string> using namespace std; int main(int argc, char* argv[]){ string name = argv[1]; int age = stoi(argv[2]); cout << "名前は" << name << ", 年齢は" << age << endl; }
argv[1]
とargv[2]
によりプログラム内で文字列として参照可.age
(整数型)に代入する前に,整数型へ変換する関数stoi
を適用./prog1 Hana 20 名前はHana, 年齢は20
以下のコードをprog1.cpp
という名前で保存し,コンパイル,実行してください
#include <iostream> #include <string> using namespace std; int main(int argc, char* argv[]){ cout << "あなたの名前の入力:"; string name; cin >> name; cout << "名前は" << name << endl; }
cin
(標準入力)から">>
"を使って文字列を代入することができます.例では,あなたの名前の入力:
の表示に続けて文字列を入力しEnterキーを押すとname
に代入されます./prog1 あなたの名前の入力:Hana 名前はHana
以下をdata1.dat
とprog1.cpp
いう名前で保存し,ソースコードはコンパイルしてください.
1 2 3
#include <iostream> #include <string> #include <fstream> using namespace std; int main(int argc, char* argv[]){ string fileName = argv[1]; ifstream ifile( fileName ); int d1, d2, d3; ifile >> d1 >> d2 >> d3; cout << d1 << " " << d2 << " " << d3 << endl; }
ifstream ifile( fileName )
の,ifstream
は,入力ファイルストリームifile
をファイル名fileName
で開くための「型」.#include <fstream>
は,ファイルストリームを扱うため.data1.dat
を第1引数とすれば,そこからデータを順次d1,d2,d3
に代入(下記実行例)
./prog1 data1.dat 1 2 3
#include <iostream> #include <string> #include <fstream> using namespace std; int main(int argc, char* argv[]){ string fileName = argv[1]; ifstream ifile( fileName ); int d; while( ifile >> d ){ cout << d << endl; } }
prog1.cpp
を変更.今度は,while( ifile >> d )
により,入力ファイルストリームifile
から次のデータを変数d
へ代入.データがあればこの代入は真になり,次の文によりデータd
を出力して改行(下記実行例)./prog1 data1.dat 1 2 3
#include <iostream> #include <string> #include <fstream> using namespace std; int main(int argc, char* argv[]){ string fileName = argv[1]; ifstream ifile( fileName ); string buffer; while( getline(ifile, buffer) ){ cout << buffer << endl; } }
prog1.cpp
を変更.今度は,while( getline(ifile, buffer) )
により,入力ファイルストリームifile
から次の1行を文字列としてbuffer
へ代入.データがあればこの代入は真になり,次の文によりデータbuffer
を出力して改行(下記実行例)./prog1 data1.dat 1 2 3
#include <iostream> #include <string> #include <fstream> #include <sstream> using namespace std; int main(int argc, char* argv[]){ string fileName = argv[1]; ifstream ifile( fileName ); string buffer; while( getline(ifile, buffer) ){ istringstream iss(buffer); int d; while( iss >> d ) cout << d << endl; } }
prog1.cpp
を変更.今度は,読み込んだbuffer
を元にistringstream
により,文字列ストリームiss
を宣言.ストリームiss
は入力ファイルストリームと同様に扱え,">>
"を使って変数への代入が可能.#include <sstream>
は,文字列ストリームを扱うため(下記実行例)
./prog1 data1.dat 1 2 3
#include <iostream> #include <string> #include <fstream> #include <sstream> #include <vector> using namespace std; int main(int argc, char* argv[]){ vector<int> vec1(3,0); vector<int> vec2 = {8,9,10}; cout << vec1[0] << " " << vec1[1] << " " << vec1[2] << endl; cout << vec2[0] << " " << vec2[1] << " " << vec2[2] << endl; }
vector<int>
は,整数型int
の配列(=ベクトル)vector
を宣言する型で,vector<int> vec1(3,0)
により,次元数が3の配列を要素値0で初期化してvec1
を宣言,vector<int> vec2 = {8,9,10}
は,値指定で初期化しながらvec2
を宣言.同様にして浮動小数点型double
の配列なども宣言可#include <vector>
は,配列(ベクトル)を扱うため./prog1 0 0 0 8 9 10
#include <iostream> #include <string> #include <fstream> #include <sstream> #include <vector> using namespace std; int main(int argc, char* argv[]){ vector<int> vec1(3,0); vector<int> vec2 = {8,9,10}; vector<vector<int>> vecs; vecs.emplace_back(vec1); vecs.emplace_back(vec2); cout << vecs[0][0] << " " << vecs[0][1] << " " << vecs[0][2] << endl; cout << vecs[1][0] << " " << vecs[1][1] << " " << vecs[1][2] << endl; }
vector<vector<int>>
は,整数型の配列vector<int>
の配列をvector<vector<int>> vecs
により宣言.
vecs.emplace_back(vec1)
とすることで,vecs
の最後尾に配列vec1
と同じ配列を追加vecs
の要素(=配列)は[添字]により参照.参照した配列の要素も[添字]で参照するので,値の参照は[添字][添字]という形になる
./prog1 0 0 0 8 9 10
#include <iostream> #include <string> #include <fstream> #include <sstream> #include <vector> using namespace std; int main(int argc, char* argv[]){ string fileName = argv[1]; ifstream ifile( fileName ); vector<int> vec; int d; while( ifile >> d ){ vec.emplace_back(d); } cout << vec[0] << " " << vec[1] << " " << vec[2] << endl; }
vec.emplace_back(d)
とすることで,vec
の最後尾に整数d
の値を持つ要素を追加.外部ファイルのデータを配列に読み込むことも可.行ごとに配列として読み込み,これを束ねて配列の配列にすることも可(例:教科書p.20のread2D.cpp
)./prog1 data1.dat 1 2 3
関数は,何度も使う一連の処理をまとめ,呼び出して使えるようにしたもの.下記は,形式(左)と例(右)
戻り値の型 関数名( 引数の型と名前,..){ 関数本体 return 戻り値 }
double sum( vector& vec ){ double val = 0; for( int i = 0 ; i < vec.size() ; i++ ) val += vec[i]; return val; }
&
"をつけると引数の「参照渡し」となり,仮引数は呼び出し元と同じように扱え,変更は呼び出し元(実引数)にも反映されます.こちらを使うことが多い&
"をつけなければ「値渡し」となり,仮引数は呼び出し元の実引数と別物になります.その変更は呼び出し元(実引数)には反映されませんvec.size()
の.size()
は,配列vec
のサイズ(要素数)を返すメソッド(≒関数)./prog1 data1.dat 6
#include
を使い,読み込んで利用する(教科書p.50-54)
#include <iostream> #include <string> #include <fstream> #include <sstream> #include <vector> using namespace std; double sum( vector<int>& vec ){ double val = 0; for( int i = 0 ; i < vec.size() ; i++ ) val += vec[i]; return val; } int main(int argc, char* argv[]){ string fileName = argv[1]; ifstream ifile( fileName ); vector<int> vec; int d; while( ifile >> d ){ vec.emplace_back(d); } cout << sum( vec ) << endl; }
mt19937 gen(seed)
は,乱数生成器gen
を乱数初期化の種seed
を使っての宣言.続く2行は,それぞれ一様分布の整数乱数(0以上9以下)と同じく一様分布の浮動小数点乱数(0以上1未満)の宣言.乱数の生成は,乱数生成器gen
を引数にして行う.#include <random>
は,乱数を扱うため.一様分布以外も用意されている#include <iostream> #include <random> using namespace std; int main(int argc, char* argv[]){ int seed = stoi( argv[1] ); mt19937 gen(seed); uniform_int_distribution<int> distInt(0, 9); // [0,9]の整数乱数 uniform_real_distribution<double> distDbl(0, 1); // [0,1)の浮動小数点乱数 cout << distInt(gen) << " " << distInt(gen) << " " << distInt(gen) << endl; cout << distDbl(gen) << " " << distDbl(gen) << " " << distDbl(gen) << endl; }
./prog1 0 7 5 5 0.423655 0.544883 0.602763
C++入門(1) 内山俊郎