[C++/C] 演算子の種類2

sizeof演算子

int main() {
    
    int a = 1;
    int b = 0;

    cout << "short int型のサイズは" << sizeof(short int) << "バイトです。\n";
    cout << "int型のサイズは" << sizeof(int) << "バイトです。\n";
    cout << "long int型のサイズは" << sizeof(long int) << "バイトです。\n";
    cout << "float型のサイズは" << sizeof(float) << "バイトです。\n";
    cout << "double型のサイズは" << sizeof(double) << "バイトです。\n";
    cout << "long double型のサイズは" << sizeof(long double) << "バイトです。\n";
    cout << "変数aのサイズは" << sizeof(a) << "バイトです。\n";
    cout << "式a+bのサイズは" << sizeof(a+b) << "バイトです。\n";
    return 0; 
}

$ g++ -o sample sample.cpp && ./sample
short int型のサイズは2バイトです。
int型のサイズは4バイトです。
long int型のサイズは8バイトです。
float型のサイズは4バイトです。
double型のサイズは8バイトです。
long double型のサイズは16バイトです。
変数aのサイズは4バイトです。
式a+bのサイズは4バイトです。

### シフト演算子
数値を2進数で表した場合の桁を左または右に指定数だけずらす演算です。

### 型変換

int main() {
    
    int inum = 160;
    double dnum;

    cout << "身長は" << inum << "センチです。\n";
    cout << "double型の変数に代入します。\n";

    dnum = inum;

    cout << "身長は" << dnum << "センチです。\n";
    return 0; 
}
int main() {
    
    double dnum = 160.5;
    int inum;

    cout << "身長は" << dnum << "センチです。\n";
    cout << "int型の変数に代入します。\n";

    inum = dnum;

    cout << "身長は" << inum << "センチです。\n";
    return 0; 
}

$ g++ -o sample sample.cpp && ./sample
身長は160.5センチです。
int型の変数に代入します。
身長は160センチです。

### キャスト演算子
型を変換することを明示する
dnum = (double)inum;

### 異なる型同士で演算する

int main() {
    
    int d = 2;
    const double pi = 3.14;

    cout << "直径が" << d << "センチの円の\n";
    cout << "円周は" << d*pi << "センチです。\n";

    return 0; 
}

$ g++ -o sample sample.cpp && ./sample
直径が2センチの円の
円周は6.28センチです。

double とintをかけると doubleになる。

### 同じ型同士の演算

int main() {
    
    int num1 = 5;
    int num2 = 4;
    double div;

    div = num1 / num2;

    cout << "5/4は" << div << "です。\n";

    return 0; 
}

int と intの計算のため、回答は1で出力される。(double)num1/(double)num2とキャストした場合は1.25で出力される。

### practice

int main() {
    

    cout << "0-4は" << 0-4 << "です。\n";
    cout << "3.14x2は" << 3.14*2 << "です。\n";
    cout << "5/3は" << 5/3 << "です。\n";
    cout << "30/7の余りは" << 30%7 << "です。\n";
    cout << "(7*32)/5は" << (7*32)/5 << "です。\n";

    return 0; 
}

三角形の面積

int main() {
    
    double height, base;

    cout << "三角形の高さを入力してください。\n";
    cin >> height;

    cout << "三角形の底辺を入力してください。\n";
    cin >> base;

    cout << "三角形の面積は" << height*base/2 << "です。\n";

    return 0; 
}

$ g++ -o sample sample.cpp && ./sample
三角形の高さを入力してください。
3
三角形の底辺を入力してください。
5
三角形の面積は7.5です。

#include <iostream>
using namespace std;

int main() {
    
    int num1, num2, num3, num4, num5;

    cout << "科目1の点数を入力してください。\n";
    cin >> num1;

    cout << "科目2の点数を入力してください。\n";
    cin >> num2;

    cout << "科目3の点数を入力してください。\n";
    cin >> num3;

    cout << "科目4の点数を入力してください。\n";
    cin >> num4;

    cout << "科目5の点数を入力してください。\n";
    cin >> num5;

    cout << "5科目の合計点は" << num1+num2+num3+num3+num4+num5 << "です。\n";
    cout << "5科目の平均点は" << (num1+num2+num3+num3+num4+num5)/5 << "です。\n";

    return 0; 
}

合計値の場合は、int sum=0, num=0と宣言した上で、
cin >> num;
sum += num;とする方がスマート

[C++/C]式と演算子

int main() {
    
    cout << "1+2=" << 1+2 << "です。\n"; 
    cout << "3+4=" << 3*4 << "です。\n";
    return 0; 
}
int main() {
    
    int num1, num2;

    cout << "整数1を入力してください。\n";
    cin >> num1;

    cout << "整数2を入力してください。\n";
    cin >> num2;

    cout << "結果は" << num1 + num2 << "です。\n";
    return 0; 
}

演算子の種類
+, -, *, /, %, +, -, ~, &, |, ^, <<, >>, ++, –, >, >=, < 前後のインクレメント b = ++a; は代入前なので1となる。 代入演算子のバリエーション +=, -=, *=, /=, %=, &=, ^=, |=, <<=, >>=

int main() {
    
    int sum = 0;
    int num = 0;

    cout << "1番目の整数を入力してください。\n";
    cin >> num;
    sum += num;

    cout << "2番目の整数を入力してください。\n";
    cin >> num;
    sum += num;

    cout << "3番目の整数を入力してください。\n";
    cin >> num;
    sum += num;

    cout << "合計値は" << sum << "です。\n";
    return 0; 
}

[C++/C] 型, 変数, キーボードからの入力, 定数

基本型
bool, char, unsigned char(符号なし), short int, unsigned short int, int, unsigned int, long int, unsigned long int, float, double, long double

bitとbytes
2進数の1桁分をbitと呼ぶ
00101110

2進数の8桁の数値はbyteと呼ぶ

### 変数の利用

#include <iostream>
using namespace std;

int main() {
    int num;
    num = 3;

    cout << "変数numの値は" << num << "です。\n";

    return 0;
}

変数の値を変更

int main() {
    int num = 3;
    cout << "変数numの値は" << num << "です。\n";

    num = 5;

    cout << "新しい変数numの値は" << num << "です。\n";

    return 0;
}

他の変数の値を代入

int main() {
    int num1, num2;
    num1 = 3;

    cout << "変数num1の値は" << num1 << "です。\n";

    num2 = num1;

    cout << "変数num2の値は" << num2 << "です。\n";

    return 0;
}

値の代入と型変換

int main() {
    int num1;
    double num2;

    num1 = 3.14;
    num2 = 3.14;

    cout << "変数num1の値は" << num1 << "です。\n";
    cout << "変数num2の値は" << num2 << "です。\n";

    return 0;
}

$ g++ -o sample sample.cpp && ./sample
変数num1の値は3です。
変数num2の値は3.14です。
// 小数点以下は切り捨てられる

キーボードからの入力
=> cin >> 変数; と記載する

int main() {
    int num = 0;

    cout << "整数を入力してください。\n";

    cin >> num;

    cout << num << "が入力されました。\n";

    return 0;
}

2つ以上の数値の入力

int main() {
    int num1, num2;

    cout << "整数を2つ入力してください。\n";

    cin >> num1 >> num2;

    cout << "最初に" << num1 << "が入力されました。\n";
    cout << "次に" << num2 << "が入力されました。\n";

    return 0;
}

定数はconstを指定する
初期化によって変数を変更できないようにする

int main() {
    const double pi = 3.1415;

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

    return 0;
}

practice 1

int main() {
    double pi;

    cout << "円周率の値は幾つですか?\n";

    cin >> pi;

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

    return 0;
}

practice 2

int main() {
    char str;

    cout << "アルファベットの最初の文字は何ですか?\n";

    cin >> str;

    cout << "アルファベットの最初の文字は" << str << "です。\n";

    return 0;
}

practice 3

int main() {
    double height, weight;

    cout << "身長と体重を入力してください。\n";

    cin >> height >> weight;

    cout << "身長は" << height << "です。\n";
    cout << "体重は" << weight << "です。\n";

    return 0;
}

c++では文字列の変数名はstrよりもchの方が型との違いがなく表現としては望ましそうです。

[C++/C] ポインタ

ポインタは変数のアドレスを持つ変数のこと
変数のアドレス場所を表すには、変数の頭に&をつける

ポインタ型とは、変数のアドレスを保存しておくための型
下記は同じ意味

char* test;
char *test;
#include <stdio.h>

int main(void) {

    char buf[50] = "bitcoin";
    char *test;

    test = buf;
    printf("%s", test);
    return 0;
}

文字列の後ろにつけるアスタリスクがあるのかと勘違いしてしまいますね。

[C++/C] uint256

uint256は256bitの符号付き整数型を宣言する
cpp uint256は、C++言語で使用される256ビットの符号なし整数型です。このデータ型は、非常に大きな整数値を扱うために使用されます。cpp uint256は、暗号通貨やブロックチェーンの開発において、特にハッシュ計算や暗号学的な操作に必要とされます。この型は、十進数や16進数などの異なる形式で整数を表現することもできます。cpp uint256は、その大きな範囲と精度のために、セキュリティや数値計算の要件を満たすために重要な役割を果たします。

The function uint256.ToString() is a method that convert a 256-bit unsigned integer into a string representation. This function is commonly used in cryptographic algorithms.

#include <iostream>
#include <string>

using namespace std;
using namespace boost::multiprecision;

int main() {
    
    uint256_t value = 1000000000000000000000000000000000000000000000000000000000000000;
    string str_value = value.ToString();
    cout << "Value as string: " << str_value << endl;
    return 0;
}


Boost.Multiprecisionから提供される多倍長整数

#include <iostream>
#include <boost/multiprecision/cpp_int.hpp>

namespace mp = boost::multiprecision;

int main() {
    
    mp::cpp_int x = 1;

    for (unsigned int i = 1; i <= 100; ++i) {
        x *= i;
    }

    std::cout << x << std::endl;
    return 0;
}

$ g++ -o sample sample.cpp && ./sample
93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000

[C++] iteratorとは?

イテレータとはコンテナ内での要素の位置を指すもので、ポインタのように扱うことができる。イテレータを使用することで、コンテナの種類に依存しないで処理を共通化できる。

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

int main() {
    
    vector<int> x = {0, 1, 2, 3, 4};

    // begin()でコンテナ内の先頭要素を指す
    auto it = x.begin();

    cout << *it << endl;

    ++it;

    cout << *it << endl;

    return 0;
}

$ g++ -o sample sample.cpp && ./sample
0
1

end()は要素の1つ先となる。

    vector<int> x = {0, 1, 2, 3, 4};
    for (auto it = x.begin(); it != x.end(); ++it) {
        cout << *it << endl;
    }

    return 0;

この性質によってコンテナの種類に依存せず algorithmで提供される機能を使用できる。

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

int main() {
    
    vector<int> x = {0, 1, 2, 3, 4};
    auto n = std::count_if(x.begin(), x.end(), [](const int v){
        if (v <= 0) {
            return false;
        }
        if (v % 2 != 0){
            return false;
        }
        return true;
    });
    cout << n << endl;

    return 0;
}

[C++] endlとは

endl; とは出力の最後に改行を押し込むという意味

#include <iostream>
using namespace std;

int main() {
    
    cout << "I'm hpscript!" << endl;

    return 0;
}

$ g++ -o sample sample.cpp && ./sample
I’m hpscript!

[C++] Ubuntu22.04にBoost install

Boost is a set of libraries for the C++ programming language that provides support for tasks and structures such as linear algebra, pseudorandom number generation, multithreading, image processing, regular expressions, and unit testing.

$ sudo apt-get install libboost-all-dev

#include <iostream>
#include <boost/version.hpp>

int main() {
    
    std::cout << "Ver." << BOOST_VERSION << '\n' <<
        "Lib Ver." << BOOST_LIB_VERSION << std::endl;

    return 0;
}

$ g++ -o sample sample.cpp && ./sample
Ver.107400
Lib Ver.1_74

[C++/C] mapとは

mapはvector同様、配列の一種。
vectorが要素へのアクセスを0, 1, 2…といったインデックスで行っている一方、mapはキーが要素隣、連想配列とも言われる。

#include <iostream>
#include <string>
#include <map>

using namespace std;

int main() {
    map <string, int> score;
    string names[] = {"Tom", "Bob", "Mike"};
    score[names[0]] = 100;
    score[names[1]] = 80;
    score[names[2]] = 120;
    int i;
    for(i = 0; i < 3; i++){
        cout << names[i] << ":" << score[names[i]] << endl;
    }
    return 0;
}

$ g++ -o sample sample.cpp && ./sample
Tom:100
Bob:80
Mike:120

[C++/C] external宣言

C言語において、extern宣言はグローバル変数を共有する仕組み

グローバル変数とローカル変数

#include <stdio.h>

int gNumber = 100;

void func(void) {
    gNumber += 100;
}

int main(void) {
    int tmp = 100;

    func();

    printf("tmp : %d\n", tmp);
    printf("gNumber : %d\n", gNumber);
}

$ gcc test.c -o test && ./test
tmp : 100
gNumber : 200

複数ファイルにする
main.c

#include <stdio.h>

void func();

int main(void) {

    func();
    printf("gNumber : %d\n", gNumber);
}

sub.c

int gNumber = 100;

void func(void) {
    gNumber += 100;
}

この場合、sub.cのコンパイルは通るがmain.cのコンパイル時にgNumberが定義されていない識別子としてエラーになる。
$ gcc -c sub.c
$ gcc -c main.c
main.c: In function ‘main’:
main.c:8:30: error: ‘gNumber’ undeclared (first use in this function)
8 | printf(“gNumber : %d\n”, gNumber);
| ^~~~~~~
main.c:8:30: note: each undeclared identifier is reported only once for each function it appears in

そこでmain.cでexternで宣言する

#include <stdio.h>

extern int gNumber;
void func();

int main(void) {

    func();
    printf("gNumber : %d\n", gNumber);
}

$ gcc -c main.c
$ gcc main.o sub.o -o main
$ ./main
gNumber : 200