コンテンツにスキップ

C++ の基礎 Day 1

1. 最小のプログラム

  • C++ の最小のプログラムは次のようになる。
int main()
{

}
  • int main()(イント・メイン)関数は、C++ プログラムのエントリーポイント。
  • ここでの intmain 関数が int 型の値を戻り値として返すことを示す。
    • 正常終了時に 0 を返すのが慣例。
  • main 関数に限り、戻り値を返す return 0;(リターン・ゼロ)を省略してよい。省略した場合は return 0; を書いたものとみなされる。
  • 波括弧 {} で囲まれた部分が、main 関数の本体。

2. 字下げスタイル

  • C++ における字下げスタイルは次の 2 つがメジャー。
  • どちらのスタイルを使ってもよいが、一貫性を持たせるべき。

オールマンスタイル

int main()
{

}

K&R(ケーアンドアール)スタイル

int main() {
	
}

3. コマンドライン引数が必要な場合

  • main 関数には、コマンドライン引数を受け取るための引数を追加できる。
  • プログラムの中でコマンドライン引数を活用したい場合は次のように書く。
int main(int argc, char* argv[])
{

}
  • argc(アーグシー)は、コマンドライン引数の個数を表す整数。
  • argv(アーグブイ)は、コマンドライン引数の値を表す文字列の配列。
コマンドライン引数を表示するプログラム
#include <print>

int main(int argc, char* argv[])
{
	for (int i = 0; i < argc; ++i)
	{
		std::println("argv[{}] = {}", i, argv[i]);
	}
}

4. 標準ライブラリの利用

  • C++ のコア言語は基本的な文法を提供する。
C++ のコア言語機能の例
  • int, double, char などの基本的なデータ型
  • 基本的なデータ型に対する +, -, *, /, ++, -=, == などの演算子定義
  • iffor, switch, int main(), コメントなどの基本構文
  • 0"Hello, World!" などのリテラル
  • class, struct, enum など、ユーザー定義型を作るための機能
  • [[nodiscard]] などの属性指定子
  • 複雑な処理を行うためには、標準ライブラリが提供する機能を利用する。
C++ の標準ライブラリが提供する機能の例
  • 標準入出力
  • 文字列操作
  • 数学関数
  • ファイル操作
  • コンテナ(配列、リスト、マップなど)
  • アルゴリズム
  • スレッド
  • C++ の標準ライブラリの機能は、それぞれの機能に対応した標準ライブラリヘッダ <〇〇〇> をインクルードすることで利用できる。
  • 標準ライブラリのすべての機能は std(エスティーディー)名前空間で提供される。サンプルコード内では std::(エスティーディー・コロンコロン)の有無で標準ライブラリの機能であるかどうかを判断できる。
std:: 付きのものが標準ライブラリの機能
#include <iostream>
#include <string>
#include <vector>
#include <cmath>

int main()
{
	int a = 42;
	double d[] = { 1.0, 2.0, 3.0 };
	const int b = a + 20 + sizeof(d);
	if (b == 86)
	{
		std::cout << "Hello, World!\n";
	}

	std::string str = "C++!";
	std::vector<int> v = { 1, 2, 3, 4, 5 };
	std::cout << std::sqrt(2.0) << '\n';
}

C++23 での変更点

C++23 からは標準ライブラリがモジュールに対応し、import std;(インポート・エスティーディー)の一行だけで標準ライブラリのすべての機能を利用できるようになる。

5. 文字列リテラル

  • ダブルクォーテーション " " で囲まれた文字列は文字列リテラル。
  • C 言語の文字列リテラルから仕様を引き継ぎ、実体はヌル終端された文字列を格納する char(チャー)型の配列である。

std::string とは無関係

文字列リテラルは C++ 標準ライブラリの文字列クラス std::string(ストリング)とは無関係。"abc".length()(レングス)のように、文字列リテラルで使えるメンバ関数は存在しない。

  • 文字コードは実装依存。UTF-8 が多いが、日本語環境の Visual Studio では CP932(Shift_JIS の派生)がデフォルト。

本講義での設定

本講義では Visual Studio の環境構築の手順で、デフォルトの文字コード設定を UTF-8 にしている。

#include <print>
#include <cstring>

int main()
{
	"Hello, World!";

	"こんにちは、世界!";

	""; // 空文字列(からもじれつ)

	std::println("{}", std::strlen("ABC")); // 3: 文字列の長さ
	std::println("{}", sizeof("ABC")); // 4: 配列のサイズ

	std::println("{}", std::strlen("")); // 0: 空文字列の長さ
	std::println("{}", sizeof("")); // 1: 配列のサイズ

	std::println("{}", "ABC"[0]); // A
	std::println("{}", "ABC"[1]); // B
	std::println("{}", "ABC"[2]); // C
}
出力
3
4
0
1
A
B
C

6. エスケープシーケンス

  • 文字および文字列リテラル内で特殊な文字を表現するために、バックスラッシュ \ で始まるエスケープシーケンスを用いる。
エスケープシーケンス 意味
\' シングルクォーテーション '
\" ダブルクォーテーション "
\\ バックスラッシュ \
\t 水平タブ
\n 改行 (line feed)
\r キャリッジリターン (carriage return)
\u●●●● 16 進数 4 桁の Unicode(ユニコード)コードポイント
\U●●●●●●●● 16 進数 8 桁の Unicode コードポイント

#include <print>

int main()
{
	std::println("Hello,\n\"World\"!");
}
出力
Hello,
"World"!

7. 文字リテラル

  • シングルクォーテーション ' ' で囲まれた 1 文字は文字リテラル。
  • 文字リテラルは char 型の値として扱われる。
  • 文字が 1 バイトに収まらない場合は不正となる。
int main()
{
	'A';
	'3';
	' ';
	'\n';

	'あ'; // 不正な文字リテラル
}

8. Unicode 文字・文字列リテラル

  • シングルクォーテーションやダブルクォーテーションの前にプレフィックスを付けると、Unicode に準拠した文字や文字列リテラルを表現できる。
プレフィックス 意味 要素の型
(なし) マルチバイト文字・文字列 char
L ワイド文字・文字列 wchar_t
u8 UTF-8 文字・文字列 char8_t
u UTF-16(ユーティーエフじゅうろく)文字・文字列 char16_t
U UTF-32(ユーティーエフさんじゅうに)文字・文字列 char32_t
  • ワイド文字列の文字コードは実装依存。Windows 環境では UTF-16, それ以外の環境では UTF-32 が多い。
  • 標準入出力を含む C++ 標準ライブラリ機能の多くがマルチバイト文字のみにしか対応しないため、u8, u, U, L を使う機会は限られる。
  • 文字コードを変換する機能は標準ライブラリには用意されていない。

#include <print>

int main()
{
	// マルチバイト文字列リテラル
	"Hello, World!";

	// ワイド文字列リテラル
	L"Hello, World!";

	// UTF-8 文字列リテラル
	u8"Hello, World!";

	// UTF-16 文字列リテラル
	u"Hello, World!";

	// UTF-32 文字列リテラル
	U"Hello, World!";

	std::println("こんにちは、世界!");
}
出力
こんにちは、世界!

9. 整数リテラル

  • 10 進数、16 進数、8 進数、2 進数の整数リテラルを表現できる。

#include <print>

int main()
{
	42; // 10 進数
	0x2A; // 16 進数
	052; // 8 進数
	0b101010; // 2 進数

	std::println("{}", 42);
	std::println("{}", 0x2A);
	std::println("{}", 052);
	std::println("{}", 0b101010);
}
出力
42
42
42
42

  • 整数リテラルは数字の間の任意の位置に '(アポストロフィ)を挿入して、桁区切りを表現できる。

#include <print>

int main()
{
	1'000'000; // 1,000,000
	0x123'456; // 0x123,456
	0b1010'1010; // 0b1010,1010

	std::println("{}", 1'000'000);
	std::println("{}", 0x123'456);
	std::println("{}", 0b1010'1010);
}
出力
1000000
1193046
170

整数リテラルのサフィックス
  • 値の範囲と進数とサフィックスによって、整数リテラルの型が変わる。
  • 具体的には、次の各セルで最初にマッチする表現可能な型になる。
サフィックス 10 進数 2/8/16 進数
(なし) int, long int, long long int int, unsigned int, long int, unsigned long int, long long int, unsigned long long int
u または U unsigned int, unsigned long int, unsigned long long int unsigned int, unsigned long int, unsigned long long int
l または L long int, long long int long int, unsigned long int, long long int, unsigned long long int
ul, uL, Ul, UL, lu, lU, Lu, LU unsigned long int, unsigned long long int unsigned long int, unsigned long long int
ll または LL long long int long long int, unsigned long long int
ull, uLL, Ull, ULL, llu, llU, Llu, LLU unsigned long long int unsigned long long int
int main()
{
	auto a = 42; // int
	auto b = 5000000000; // long int または long long int

	auto c = 42L; // long int
	auto d = 42ULL; // unsigned long long int
}

10. 浮動小数点数リテラル

  • 3.14double(ダブル)型の浮動小数点数リテラル。
  • 3.14ffloat(フロート)型の浮動小数点数リテラル。

11. 真偽値リテラル

  • bool(ブール)型の真偽値リテラルは true(トゥルー)と false(フォルス)。

12. 標準出力

  • C++20 までの標準出力には <iostream>(アイオーストリーム)ヘッダの std::cout(シーアウト)を使った。

#include <iostream>

int main()
{
	std::cout << "Hello, World!\n";

	std::cout << "1 + 1 = " << (1 + 1) << '\n';

	std::cout << 3.14 << '\n';
}
出力
Hello, World!
1 + 1 = 2
3.14

  • C++23 以降は <print>(プリント)ヘッダの std::print(プリント)および std::println(プリントエルエヌ)を使う。
  • std::println は、最後に改行を自動で付加する。

#include <print>

int main()
{
	std::println("Hello, World!");

	std::println("1 + 1 = {}", (1 + 1));

	std::println("{}", 3.14);
}
出力
Hello, World!
1 + 1 = 2
3.14

13. 標準出力の書式指定

  • std::print および std::println のフォーマット文字列の中で、書式指定ができる。

13.1 インデックス指定

#include <print>

int main()
{
	std::println("{2}/{1}/{0}", 2024, 12, 31);
	std::println("{0}/{1}/{2}", 2024, 12, 31);
	std::println("{0}{0}{0}", 11, 22, 33);
}
出力
31/12/2024
2024/12/31
111111

13.2 進数指定

#include <print>

int main()
{
	std::println("{:#x}", 42); // 16 進数
	std::println("{:x}", 42); // 16 進数
	std::println("{:o}", 42); // 8 進数
	std::println("{:b}", 42); // 2 進数
}
出力
0x2a
2a
52
101010

13.3 幅指定

#include <print>

int main()
{
	std::println("{:5}", 42); // 幅 5
	std::println("{:05}", 42); // 幅 5、ゼロ埋め
}
出力
   42
00042

13.4 浮動小数点数の精度指定

#include <print>

int main()
{
	std::println("{}", 123.456789);
	std::println("{:.6}", 123.456789); // 6 桁
	std::println("{:.4}", 123.456789); // 4 桁
	std::println("{:.2}", 123.456789); // 2 桁
}
出力
123.456789
123.457
123.5
1.2e+02

13.5 小数点以下桁数指定

#include <print>
#include <numbers>

int main()
{
	std::println("{}", std::numbers::pi);
	std::println("{:.4f}", std::numbers::pi); // 小数点以下 4 桁
	std::println("{:.2f}", std::numbers::pi); // 小数点以下 2 桁
	std::println("{:.0f}", std::numbers::pi); // 小数点以下 0 桁
}
出力
3.141592653589793
3.1416
3.14
3

13.6 「{ }」のエスケープ

  • フォーマット文字列内で {} をエスケープするには {{}} を使う。

#include <print>

int main()
{
	std::println("{{}} {}", 42);
}
出力
{} 42