[C++].hppとは

### .hppとは
ヘッダーファイルで.hpp、.hというファイル形式で保存
.hppはc++が入っている。.hはc言語だがc++でも使用できる

sample.hpp

#ifndef Sample_hpp
#define Sample_hpp

#include <iostream>

using namespace std;

class Sample {
    public:
        string name;
};

#endif

SRM464 ColorfulBoxesAndBalls

You are playing a game where you have numRed red boxes, numBlue blue boxes, numRed red balls, and numBlue blue balls.

You must place a single ball into each box. Each box is then scored as follows:
If the box is red and it contains a red ball, you get onlyRed points.
If the box is blue and it contains a blue ball, you get onlyBlue points.
In all other cases, you get bothColors points.
Your total score is the sum of the scores of all the boxes.

Return the maximum possible total score you can get.

#include <algorithm>
#include <limits.h>
using namespace std;

class ColorfulBoxesAndBalls {
    public:
        int getMaximum(int numRed, int numBlue, int onlyRed, int onlyBlue, int bothColors){
            int ans = INT_MIN;
            int change = min(numRed, numBlue);

            for(int i =0; i <= change; i++){
                int myscore = (numRed - i) * onlyRed
                    + (numBlue - i) * onlyBlue
                    + 2 * i * bothColors;
                ans = max(ans, myscore);
            }
            return ans;
        }
};

max値をfor文で回して、全パターンの最大値を検索するアルゴリズム
数が少ない方をchangeと定義するのがみそ

C++ 入門の入門1

わざとエラーを発生させる

#include <iostream>
using namespace std;

int main(){
    cout << "hello world\n"
}

void main(){
    cout << "hello world\n";
}

### コンパイルオプション
オブジェクトファイル -c
実行ファイル -o
静的ライブラリをリンク -L
ヘッダを追加 -l
警告 -W, -wall
機能有効 -std=c++11
最適化 -O

#### 変数

int main(){
    int a = 12345;
    int b = 98765;
    cout << a + b << endl;
    cout << a - b << endl;
}

intは32bit

#include <iostream>
#include <limits>
using namespace std;

int main(){
    cout << numeric_limits<int>::lowest() << ", " << numeric_limits<int>::max() << endl;
}

floatが32ビットだがdoubleは64bit

int main(){
    double a = 1.23;
    double b = 5.43;
    cout << a * b << endl;
    cout << a / b << endl;
}

[C++] ファイルの入出力

#include <iostream>
#include <fstream>
using namespace std;


int main() {
    
    ofstream fout("test0.txt");
    if(!fout){
        cout << "ファイルをオープンできませんでした。\n";
        return 1;
    }
    else
        cout << "ファイルをオープンしました。\n";

    fout.close();
    cout << "ファイルをクローズしました。\n";

    return 0;
}

ファイル出力

    fout << "Hello\n";
    fout << "Goodbye\n";
    fout << "ファイルに書き込みました。\n";

### 書式を設定してファイル出力

#include <iostream>
#include <fstream>
#include <iomanip>
using namespace std;


int main() {
    
    ofstream fout("test0.txt");
    if(!fout){
        cout << "ファイルをオープンできませんでした。\n";
        return 1;
    }
    else
        cout << "ファイルをオープンしました。\n";

    const int num = 5;
    int test[num];
    cout << num << "人の点数を入力してください。\n";
    for(int i=0; i<num; i++){
        cin >> test[i];
    }

    for(int j=0; j<num; j++){
        fout << "No." << j+1 << setw(5) << test[j] << '\n';
     }

    fout.close();

    return 0;
}

### ファイルから入力

#include <iostream>
#include <fstream>
using namespace std;


int main() {
    
    ifstream fin("test0.txt");
    if(!fin){
        cout << "ファイルをオープンできませんでした。\n";
        return 1;
    }

    char str1[16];
    char str2[16];
    fin >> str1 >> str2;
    cout << "ファイルに書き込まれている2つの文字列は\n";
    cout << str1 << "です。\n";
    cout << str2 << "です。\n";

    fin.close();

    return 0;
}
int main() {
    
    ifstream fin("test0.txt");
    if(!fin){
        cout << "ファイルをオープンできませんでした。\n";
        return 1;
    }

    const int num = 8;
    int test[num];
    for(int i=0; i<num; i++){
        fin >> test[i];
    }

    int max = test[0];
    int min = test[0];
    for(int j=0; j<num; j++){
        if(max < test[j])
            max = test[j];
        if(min > test[j])
            min = test[j];
        cout << "No." << j+1 << setw(5) << test[j] << "\n";
    }

    cout << "最高点は" << max << "です。\n";
    cout << "最低点は" << min << "です。\n";

    fin.close();

    return 0;
}

$ g++ -o sample sample.cpp && ./sample
No.1 80
No.2 68
No.3 22
No.4 33
No.5 56
No.6 78
No.7 33
No.8 56
最高点は80です。
最低点は22です。

### コマンドライン引数

#include <iostream>
#include <fstream>
using namespace std;


int main(int argc, char* argv[]) {

    if(argc != 2) {
        cout << "パラメータの数が異なります。\n";
        return 1;
    }
    
    ifstream fin(argv[1]);
    if(!fin){
        cout << "ファイルをオープンできませんでした。\n";
        return 1;
    }

    char ch;
    fin.get(ch);

    while(!fin.eof()){
        cout.put(ch);
        fin.get(ch);
    }

    fin.close();

    return 0;
}

### practice

int main() {

    for (int i=1; i<=30; i++){
        cout.width(3);
        cout.fill('-');
        cout << i;
        if(i % 5 == 0) {
            cout << "\n";
        }
    }

    return 0;
}

$ g++ -o sample sample.cpp && ./sample test0.txt
–1–2–3–4–5
–6–7–8–9-10
-11-12-13-14-15
-16-17-18-19-20
-21-22-23-24-25
-26-27-28-29-30

#include <iostream>
#include <fstream>
#include <iomanip>
using namespace std;


int main(int argc, char* argv[]) {
    
    ifstream fin(argv[1]);
    if(!fin){
        cout << "ファイルをオープンできませんでした。\n";
        return 1;
    }

    const int num = 8;
    int test[num];
    for(int i=0; i<num; i++){
        fin >> test[i];
    }

    int max = test[0];
    int min = test[0];
    for(int j=0; j<num; j++){
        if(max < test[j])
            max = test[j];
        if(min > test[j])
            min = test[j];
        cout << "No." << j+1 << setw(5) << test[j] << "\n";
    }

    cout << "最高点は" << max << "です。\n";
    cout << "最低点は" << min << "です。\n";

    fin.close();

    return 0;
}

[C++] マニピュレータ

入出力の書式に関する定義をmanipulatorという

int main() {
    
    cout << "こんにちは!" << endl;
    cout << "さようなら!" << endl;

    return 0;
}

10進数以外の出力

int main() {
    
    cout << "10を10進数で表記すると" << dec << 10 << "です。\n";
    cout << "10を8進数で表記すると" << oct << 10 << "です。\n";
    cout << "12を8進数で表記すると" << 12 << "です。\n";
    cout << "10を16進数で表記すると" << hex << 10 << "です。\n";

    return 0;
}

$ g++ -o sample sample.cpp && ./sample
10を10進数で表記すると10です。
10を8進数で表記すると12です。
12を8進数で表記すると14です。
10を16進数で表記するとaです。

出力幅指定

int main() {
    
    for(int i=0; i<=10; i++){
        cout << setw(3) << i;
    }
    cout << '\n';

    return 0;
}

[C++] ストリーム

int main() {
    
    int i;
    double d;
    char str[100];

    cout << "整数値を入力してください。\n";
    cin >> i;
    cout << "小数値を入力してください。\n";
    cin >> d;
    cout << "文字列を入力してください。\n";
    cin >> str;

    cout << "入力した整数値は" << i << "です。\n";
    cout << "入力した小数値は" << d << "です。\n";
    cout << "入力した文字列は" << str << "です。\n";
    

    return 0;
}

1文字入出力関数

int main() {
    
    char ch;

    cout << "文字を続けて入力してください。\n";

    while(cin.get(ch)){
        cout.put(ch);
    }

    return 0;
}

出力はばの固定

int main() {
    
    for(int i=0; i<=10; i++){
        cout.width(3);
        cout << i;
    }
    cout << "\n";

    return 0;
}

フィル文字指定

int main() {
    
    for(int i=0; i<=10; i++){
        cout.width(3);
        cout.fill('-');
        cout << i;
    }
    cout << "\n";

    return 0;
}

数値の精度

int main() {
    
    double pi = 3.141592;
    int num;

    cout << "円周率を出力します。\n";
    cout << "有効桁数何桁で出力しますか?(1~7)\n";
    cin >> num;

    cout.precision(num);

    cout << "円周率は" << pi << "です。\n";

    return 0;
}

書式状態フラグ
L 左寄せで出力

int main() {
    
    cout.setf(ios::left, ios::adjustfield);
    for(int i=0; i<=5; i++){
        cout.width(5);
        cout.fill('-');
        cout << i;
    }
    cout << '\n';
    cout.unsetf(ios::left);
    cout.setf(ios::right, ios::adjustfield);
    for(int j=0; j<=5; j++){
        cout.width(5);
        cout.fill('-');
        cout << j;
    }
    cout << "\n";

    return 0;
}

[C++] 例外処理

int main() {
    
    int num;
    cout << "1~9までの数を入力してください。\n";
    cin >> num;

    try {
        if(num <= 0)
            throw "0以下を入力しました";
        if(num >= 10)
            throw "10以上を入力しました";
        cout << num << "です。\n";
    }
    catch(char* err) {
        cout << "エラー:" << err << "\n";
        return 1;
    }
    return 0;
}

[C++] テンプレートクラス, STL vector

クラスの雛形から色々な型を扱うクラスを作成できる。

template <class T>
class Array {
    private:
        T data[5];
    public:
        void setData(int num, T d);
        T getData(int num);
};

template <class T>
void Array<T>::setData(int num, T d){
    if ( num < 0 || num > 4)
        cout << "配列の範囲を超えています。\n";
    else
        data[num] = d;
}

template <class T>
T Array<T>::getData(int num){
    if (num < 0 || num > 4){
        cout << "配列の範囲を超えています\n";
        return data[0];
    } 
    else
        return data[num];
}
int main() {
    cout << "int型の配列を作成します\n";
    Array<int> i_array;
    i_array.setData(0, 80);
    i_array.setData(1, 60);
    i_array.setData(2, 58);
    i_array.setData(3, 77);
    i_array.setData(4, 57);

    for(int i=0; i<5; i++)
        cout << i_array.getData(i) << '\n';

    cout << "double型の配列を作成します。\n";
    Array<double> d_array;
    d_array.setData(0, 35.5);
    d_array.setData(1, 45.6);
    d_array.setData(2, 26.8);
    d_array.setData(3, 76.2);
    d_array.setData(4, 85.5);

    for (int j=0; j<5; j++)
        cout << d_array.getData(j) << '\n';

    return 0;
}

C++では standard template libraryをSTLと呼ぶ
vectorは数が決まっていない複数のデータを管理できる構造

#include <iostream>
#include <vector>
using namespace std;


int main() {
    
    int num;
    vector<int> vt;

    cout << "幾つ整数データを入力しますか?\n";
    cin >> num;

    for(int i=0; i<num; i++){
        int data;
        cout << "整数を入力してください。\n";
        cin >> data;
        vt.push_back(data);
    }

    cout << "表示します。\n";
    vector<int>::iterator it = vt.begin();
    while(it != vt.end()){
        cout << *it;
        cout << "-";
        it++;
    }
    cout << "\n";


    return 0;
}

vt.begin(), vt.end()で先頭・末尾のデータを知ることができる

### STLによるアルゴリズム

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;


int main() {
    
    vector<int> vt;
    for(int i=0; i<10; i++){
        vt.push_back(i);
    }

    cout << "並び替え前は";
    vector<int>::iterator it = vt.begin();
    while(it != vt.end()){
        cout << *it;
        it++;
    }
    cout << "です。\n";

    cout << "逆順にすると";
    reverse(vt.begin(), vt.end());
    it = vt.begin();
    while(it != vt.end()){
        cout << *it;
        it++;
    }
    cout << "です。\n";

    cout << "並び替え後は";
    sort(vt.begin(), vt.end());
    it = vt.begin();
    while(it != vt.end()){
        cout << *it;
        it++;
    }
    cout << "です。\n";


    return 0;
}

主なアルゴリズムにはcount, find, reverse, replace, remove, merge, sort, searchなどがある。

[C++] コピーコンストラクタ

オブジェクトが他のオブジェクトで初期化される場合に呼び出されるコンストラクタ
Car::Car(const Car& c){}

class Car {
    private:
        int num;
        double gas;
        char* pName;
    public:
        Car(char* pN, int n, double g);
        ~Car();
        Car(const Car& c);
        Car& operator=(const Car& c);
};

Car::Car(char* pN, int n, double g) {
    pName = new char[strlen(pN)+1];
    strcpy(pName, pN);
    num = n;
    gas = g;
    cout << pName << "を作成しました。\n";
}
Car::~Car(){
    cout << pName << "を破棄します。\n";
    delete[] pName;
}
Car::Car(const Car& c){
    cout << c.pName << "で初期化します。\n";
    pName = new char[strlen(c.pName) + strlen("のコピー1") + 1];
    strcat(pName, c.pName);
    strcat(pName, "のコピー1");
    num = c.num;
    gas = c.gas;
}

Car& Car::operator=(const Car& c){
    cout << pName << "に" << c.pName << "を代入します。\n";
    if(this != &c) {
        delete[] pName;
        pName = new char[strlen(c.pName) + strlen("のコピー2") + 1];
        strcat(pName, c.pName);
        strcat(pName, "のコピー2");
        num = c.num;
        gas = c.gas;
    }
    return *this;
}

int main() {
    Car mycar("mycar", 1234, 25.5);
    
    Car car1 = mycar;

    Car car2("car2", 0, 0);
    car2 = mycar;

    return 0;
}

[C++] クラスのメモリ確保

コンストラクタの中で動的にメモリを確保した場合、デストラクタ(destructor)を定義してメモリを解放する 
デストラクタはチルダをつける
デストラクタはオブジェクトの破棄のタイミングで自動的に解放される

#include <iostream>
#include <string>
#include <cstring>
using namespace std;

class Car {
    private:
        int num;
        double gas;
        char* pName;
    public:
        Car(char* pN, int n, double g);
        ~Car();
        void show();
};

Car::Car(char* pN, int n, double g) {
    pName = new char[strlen(pN)+1];
    strcpy(pName, pN);
    num = n;
    gas = g;
    cout << pName << "を作成しました。\n";
}
Car::~Car(){
    cout << pName << "を破棄します。\n";
    delete[] pName;
}
void Car::show(){
    cout << "車のナンバーは" << num << "です。\n";
    cout << "ガソリン量は" << gas << "です。\n";
    cout << "名前は" << pName << "です。\n";
}

int main() {
    Car car1("mycar", 1234, 25.5);
    car1.show();

    return 0;
}