C++ 配列の基本

C++C++Beginner
今すぐ練習

💡 このチュートリアルは英語版からAIによって翻訳されています。原文を確認するには、 ここをクリックしてください

はじめに

この実験では、C++ の配列について学びます。配列を定義して初期化する方法と、配列関数を使用する方法を学びます。


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL cpp(("C++")) -.-> cpp/ControlFlowGroup(["Control Flow"]) cpp(("C++")) -.-> cpp/BasicsGroup(["Basics"]) cpp(("C++")) -.-> cpp/AdvancedConceptsGroup(["Advanced Concepts"]) cpp(("C++")) -.-> cpp/IOandFileHandlingGroup(["I/O and File Handling"]) cpp/BasicsGroup -.-> cpp/variables("Variables") cpp/BasicsGroup -.-> cpp/data_types("Data Types") cpp/BasicsGroup -.-> cpp/arrays("Arrays") cpp/BasicsGroup -.-> cpp/strings("Strings") cpp/ControlFlowGroup -.-> cpp/for_loop("For Loop") cpp/ControlFlowGroup -.-> cpp/while_loop("While Loop") cpp/AdvancedConceptsGroup -.-> cpp/references("References") cpp/IOandFileHandlingGroup -.-> cpp/output("Output") cpp/IOandFileHandlingGroup -.-> cpp/user_input("User Input") subgraph Lab Skills cpp/variables -.-> lab-178535{{"C++ 配列の基本"}} cpp/data_types -.-> lab-178535{{"C++ 配列の基本"}} cpp/arrays -.-> lab-178535{{"C++ 配列の基本"}} cpp/strings -.-> lab-178535{{"C++ 配列の基本"}} cpp/for_loop -.-> lab-178535{{"C++ 配列の基本"}} cpp/while_loop -.-> lab-178535{{"C++ 配列の基本"}} cpp/references -.-> lab-178535{{"C++ 配列の基本"}} cpp/output -.-> lab-178535{{"C++ 配列の基本"}} cpp/user_input -.-> lab-178535{{"C++ 配列の基本"}} end

コンテンツの概要

配列は、一般的に同じ型のデータを格納するために使用されます。それらは効率的で、コンパクトで、アクセスしやすいです。ループと組み合わせると、配列内の要素の操作はかなり簡単です。

配列を作成するには、事前に配列の長さ(またはサイズ)を知っておき、それに応じて割り当てる必要があります。配列が作成されると、その長さは固定され、変更できません。

画像の説明

配列の宣言と使用

30人のクラスの生徒の点数の平均を求めたいとしましょう。この場合、mark1mark2、...、mark30 という30個の変数を作成したくないでしょう。代わりに、30個の要素を持つ単一の変数である 配列 を使用することができます。

配列は、同じ型の要素の リスト であり、角括弧 [ ] のペアで識別されます。配列を使用するには、配列を3つのもので 宣言 する必要があります。名前、および 次元(または サイズ、または 長さ)です。配列には複数形の名前を使用することをお勧めします。たとえば、marksrowsnumbers などです。たとえば、

int marks[5];        // 5つの要素を持つint型の配列marksを宣言する
double numbers[10];  // 10個の要素を持つdouble型の配列を宣言する
const int SIZE = 9;
float temps[SIZE];   // const intを配列の長さとして使用する

// 一部のコンパイラは、配列の長さとして変数をサポートしています。たとえば、
int size;
cout << "Enter the length of the array: ";
cin >> size;
float values[size];

C++では、宣言後の要素の値は未定義であることに注意してください。

宣言時に値のコンマ区切りリストで配列を初期化することもできます。次のようになります。

// 3つの要素を持つint型の配列を宣言して初期化する
int numbers[3] = {11, 33, 44};
// 長さを省略すると、コンパイラが要素を数えます
int numbers[] = {11, 33, 44};
// 初期化時の要素数は、長さ以下でなければなりません
int numbers[5] = {11, 33, 44};  // 残りの要素は0になります。混乱します!これはしないでください
int numbers[2] = {11, 33, 44};  // エラー:初期化子が多すぎます

// {0}または{}を使用してすべての要素を0に初期化する
int numbers[5] = {0};  // 最初の要素を0に、その他もすべて0にする
int numbers[5] = {};   // すべての要素も0になります
/* ローカル配列の初期化をテストする */
#include <iostream>
using namespace std;

int main() {
   int const SIZE = 5;

   int a1[SIZE];   // 初期化されていない
   for (int i = 0; i < SIZE; ++i) cout << a1[i] << " ";
   cout << endl;   //?????

   int a2[SIZE] = {21, 22, 23, 24, 25}; // すべての要素が初期化されている
   for (int i = 0; i < SIZE; ++i) cout << a2[i] << " ";
   cout << endl;   // 21 22 23 24 25

   int a3[] = {31, 32, 33, 34, 35};   // 初期化値からサイズが推測される
   int a3Size = sizeof(a3)/sizeof(int);
   cout << "Size is " << a3Size << endl;   // 5
   for (int i = 0; i < a3Size; ++i) cout << a3[i] << " ";
   cout << endl;   // 31 32 33 34 35

   int a4[SIZE] = {41, 42};  // 先頭の要素が初期化され、残りは0になる
   for (int i = 0; i < SIZE; ++i) cout << a4[i] << " ";
   cout << endl;   // 41 42 0 0 0

   int a5[SIZE] = {0};  // 最初の要素を0に、その他もすべて0にする
   for (int i = 0; i < SIZE; ++i) cout << a5[i] << " ";
   cout << endl;   // 0 0 0 0 0

   int a6[SIZE] = {};   // すべての要素も0になります
   for (int i = 0; i < SIZE; ++i) cout << a6[i] << " ";
   cout << endl;   // 0 0 0 0 0

   for (int i=0;i<5;i++){
       // 配列の各要素に値を割り当てるには、このようにします
       a6[i] = i;
       cout << a6[i] << " ";
   }
}

出力:

6299128 0 485160213 32595 0 ## 予期しない値いくつか
21 22 23 24 25
Size is 5
31 32 33 34 35
41 42 0 0 0
0 0 0 0 0
0 0 0 0 0
0 1 2 3 4
画像の説明

配列の長さは、式 sizeof(arrayName)/sizeof(arrayName[0]) を使用して求めることができます。ここで、sizeof(arrayName) は配列の合計バイト数を返し、sizeof(arrayName[0]) は最初の要素のバイト数を返します。

配列とループ

配列はループと密接に関連して機能します。ループを使って配列のすべての要素を処理することができます。C++11では、配列全体を反復処理するための範囲ベースのforループ(またはfor-eachループ)が導入されました。たとえば、

/* For-eachループをテストする */
#include <iostream>
using namespace std;

int main() {
   int numbers[] = {11, 22, 33, 44, 55};

   // 配列numbersのnumberと呼ばれる各メンバに対して - 読み取り専用
   for (int number : numbers) {
      cout << number << " ";
   }

   // メンバを変更するには、参照 (&) を使用する必要があります
   for (int &number : numbers) {
      number = 99;
   }

   for (int number : numbers) {
      cout << number << endl;
   }
   return 0;
}

出力:

11 22 33 44 55
99 99 99 99 99
画像の説明

多次元配列

たとえば、

int[2][3] = { {11, 22, 33}, {44, 55, 66} };
画像の説明
/* 多次元配列をテストする */
#include <iostream>
using namespace std;
void printArray(const int[][3], int);

int main() {
   int myArray[][3] = {{8, 2, 4}, {7, 5, 2}}; // 2x3 初期化
                 // 最初のインデックスのみを省略して暗黙的に指定できます
   printArray(myArray, 2);
   return 0;
}

// 3列の配列の各行の内容を表示する (列数は固定)
void printArray(const int array[][3], int rows) {
   for (int i = 0; i < rows; ++i) {
      for (int j = 0; j < 3; ++j) {
         cout << array[i][j] << " ";
      }
      cout << endl;
   }
}

出力:

8 2 4
7 5 2
画像の説明

文字の配列

C言語では、文字列はNULL文字 '\0'(16進数 0 のASCIIコード)で終わる char 配列です。C++ は、<string> ヘッダーの下に新しい string クラスを提供しています。C言語の元の文字列は、C文字列(またはCスタイルの文字列、または文字文字列)として知られています。C文字列は以下のように割り当てることができます。

char message[256];     // char型の配列を宣言する
                       // '\0' で終わる最大255文字のC文字列が入る
char str1[] = "Hello"; // "文字列リテラル" で宣言して初期化する
                       // 配列の長さは文字数 + 1 ('\0' 分)
char str1char[] = {'H', 'e', 'l', 'l', 'o', '\0'};  // 上と同じ
char str2[256] = "Hello";  // 配列の長さは256で、小さな文字列を保持する

初心者には、C文字列は避けてください。前述のC++の string<string> ヘッダーにあります)を使用してください。

C文字列の処理には、cincout を使用できます。

  • cin << は、空白で区切られた文字列を読み取ります。
  • cin.getline(*var*, *size*) は、改行までの文字列を var に読み込み、最大 size-1 の長さで、改行を破棄します('\0' に置き換えられます)。*size* は通常、C文字列配列の長さに対応します。
  • cin.get(*var*, *size*) は、改行までの文字列を読み取りますが、入力バッファに改行を残します。
  • cin.get() は引数なしで、次の文字を読み取ります。
/* C文字列のテスト */
#include <iostream>
using namespace std;

int main() {
   char msg[256]; // 最大255文字の文字列を保持する ('\0' で終わる)

   cout << "Enter a message (with space)" << endl;
   cin.getline(msg, 256);  // msgに最大255文字読み込む
   cout << msg << endl;

   // NULL終端の文字配列を介してアクセスする
   for (int i = 0; msg[i]!= '\0'; ++i) {
      cout << msg[i];
   }
   cout << endl;

   cout << "Enter a word (without space)" << endl;
   cin >> msg;
   cout << msg << endl;

   // NULL終端の文字配列を介してアクセスする
   for (int i = 0; msg[i]!= '\0'; ++i) {
      cout << msg[i];
   }
   cout << endl;
   return 0;
}

出力:

Enter a message (with space)
hello, how are you?
hello, how are you?
hello, how are you?
Enter a word (without space)
helloworld
helloworld
helloworld
画像の説明

まとめ

C/C++ は配列の インデックス境界チェック を行いません。言い換えると、インデックスが配列の境界を超えている場合、警告/エラーを発行しません。それでも、長さを見積もり、上限を割り当てる必要があります。これはおそらく配列を使用する主な欠点です。C++ には vector テンプレートクラスがあり(C++11では array テンプレートクラスも追加されました)、これは動的にリサイズ可能な配列をサポートしています。