C++ での配列と文字列の操作

C++Beginner
オンラインで実践に進む

はじめに

この実験(Lab)では、C++ における配列と文字列の操作方法を学びます。この実験では、1 次元配列の作成と初期化、配列要素へのアクセスと変更、2 次元配列の実装、C スタイルの文字列と String クラスの操作、配列要素のソート、線形探索の実行、getline() による文字列入力の処理など、幅広いトピックを扱います。これらの実践的な演習を通して、C++ プログラミングにおける基本的な配列と文字列操作について深く理解を深めることができます。

一次元配列の作成と初期化

このステップでは、C++ で 1 次元配列を作成し、初期化する方法を学びます。配列は、同じ型の複数の要素を連続したメモリ位置に格納できる基本的なデータ構造です。

WebIDE を開き、~/projectディレクトリにarrays_intro.cppという新しいファイルを作成します。配列を初期化するさまざまな方法を探ります。

touch ~/project/arrays_intro.cpp

arrays_intro.cppファイルに以下のコードを追加します。

#include <iostream>

int main() {
    // Method 1: Declare and initialize an array with specific size
    int numbers[5] = {10, 20, 30, 40, 50};

    // Method 2: Let compiler determine array size
    int scores[] = {85, 92, 78, 95, 88};

    // Method 3: Initialize array with default value zero
    int zeros[6] = {0};

    // Method 4: Create an array and initialize later
    int temperatures[4];
    temperatures[0] = 72;
    temperatures[1] = 68;
    temperatures[2] = 75;
    temperatures[3] = 80;

    // Print array elements
    std::cout << "First method - numbers array:" << std::endl;
    for (int i = 0; i < 5; i++) {
        std::cout << "Element " << i << ": " << numbers[i] << std::endl;
    }

    return 0;
}

配列の初期化について詳しく見ていきましょう。

  1. int numbers[5] = {10, 20, 30, 40, 50};: 配列のサイズを明示的に定義し、すべての要素を初期化します。
  2. int scores[] = {85, 92, 78, 95, 88};: コンパイラに配列サイズを決定させます。
  3. int zeros[6] = {0};: すべての要素をゼロに初期化します。
  4. インデックスを使用して値を手動で割り当てます:temperatures[index] = value

プログラムをコンパイルして実行します。

g++ arrays_intro.cpp -o arrays_intro
./arrays_intro

出力例:

First method - numbers array:
Element 0: 10
Element 1: 20
Element 2: 30
Element 3: 40
Element 4: 50

配列に関する重要なポイント:

  • 配列は、宣言されるとサイズが固定されます。
  • 配列のインデックスは 0 から始まります。
  • 配列は複数の方法で初期化できます。
  • 常に配列の範囲を超えないようにしてください。

インデックスを使用して配列要素にアクセスし、変更する

このステップでは、C++ でインデックスを使用して配列要素にアクセスし、変更する方法を学びます。前回の配列初期化のステップに基づいて、個々の配列要素とのやり取りについて探求します。

WebIDE を開き、~/projectディレクトリにarray_indexing.cppという新しいファイルを作成します。

touch ~/project/array_indexing.cpp

array_indexing.cppファイルに以下のコードを追加します。

#include <iostream>

int main() {
    // Create an array of student scores
    int scores[5] = {85, 92, 78, 95, 88};

    // Accessing array elements by index
    std::cout << "First student's score: " << scores[0] << std::endl;
    std::cout << "Third student's score: " << scores[2] << std::endl;

    // Modifying array elements
    std::cout << "Original second student's score: " << scores[1] << std::endl;
    scores[1] = 96; // Update the second student's score
    std::cout << "Updated second student's score: " << scores[1] << std::endl;

    // Calculating array element sum
    int total_score = 0;
    for (int i = 0; i < 5; i++) {
        total_score += scores[i];
    }
    std::cout << "Total class score: " << total_score << std::endl;

    // Average score calculation
    double average_score = static_cast<double>(total_score) / 5;
    std::cout << "Average class score: " << average_score << std::endl;

    return 0;
}

配列インデックスに関する重要なポイント:

  • 配列のインデックスは 0 から始まります。
  • 要素にアクセスするには角括弧[]を使用します。
  • インデックスを使用して要素を読み取り、変更できます。
  • 配列の範囲外のインデックスにアクセスしないように注意してください。

プログラムをコンパイルして実行します。

g++ array_indexing.cpp -o array_indexing
./array_indexing

出力例:

First student's score: 85
Third student's score: 78
Original second student's score: 92
Updated second student's score: 96
Total class score: 442
Average class score: 88.4

重要なインデックスのルール:

  • 最初の要素はインデックス 0 にあります。
  • 最後の要素はインデックス(配列サイズ - 1)にあります。
  • 配列の範囲外のインデックスにアクセスすると、未定義の動作が発生します。

行列のための二次元配列の実装

このステップでは、C++ で 2 次元配列を作成し、操作する方法を学びます。2 次元配列は、行と列を持つテーブルまたは行列のようなもので、グリッドのような構造でデータを格納し、操作できます。

WebIDE を開き、~/projectディレクトリにmatrix_arrays.cppという新しいファイルを作成します。

touch ~/project/matrix_arrays.cpp

matrix_arrays.cppファイルに以下のコードを追加します。

#include <iostream>

int main() {
    // Method 1: Declare and initialize a 3x3 matrix
    int matrix[3][3] = {
        {1, 2, 3},
        {4, 5, 6},
        {7, 8, 9}
    };

    // Method 2: Declare matrix and initialize later
    int grades[2][4];
    grades[0][0] = 85;
    grades[0][1] = 92;
    grades[0][2] = 78;
    grades[0][3] = 95;
    grades[1][0] = 88;
    grades[1][1] = 90;
    grades[1][2] = 82;
    grades[1][3] = 87;

    // Print the first matrix
    std::cout << "First Matrix:" << std::endl;
    for (int row = 0; row < 3; row++) {
        for (int col = 0; col < 3; col++) {
            std::cout << matrix[row][col] << " ";
        }
        std::cout << std::endl;
    }

    // Print the grades matrix
    std::cout << "\nGrades Matrix:" << std::endl;
    for (int row = 0; row < 2; row++) {
        for (int col = 0; col < 4; col++) {
            std::cout << grades[row][col] << " ";
        }
        std::cout << std::endl;
    }

    return 0;
}

2 次元配列に関する重要なポイント:

  • 要素にアクセスするには 2 つのインデックスを使用します:array[row][column]
  • 最初のインデックスは行を表し、2 番目のインデックスは列を表します。
  • 複数の方法で初期化できます。
  • 通常、行と列を反復処理するには、ネストされたループが使用されます。

プログラムをコンパイルして実行します。

g++ matrix_arrays.cpp -o matrix_arrays
./matrix_arrays

出力例:

First Matrix:
1 2 3
4 5 6
7 8 9

Grades Matrix:
85 92 78 95
88 90 82 87

重要な 2 次元配列の概念:

  • 配列は 3 つ以上の次元を持つことができます。
  • 各行は異なる数の列を持つことができます。
  • 常に配列の範囲に注意して、エラーを回避してください。

C スタイル文字列をヌル終端文字で初期化する

このステップでは、C++ における C スタイルの文字列と、null ターミネータの重要性について学びます。C スタイルの文字列は、文字列の終わりを示す特別な'\0'文字で終わる文字配列です。

WebIDE を開き、~/projectディレクトリにc_style_strings.cppという新しいファイルを作成します。

touch ~/project/c_style_strings.cpp

c_style_strings.cppファイルに以下のコードを追加します。

#include <iostream>
#include <cstring>

int main() {
    // Method 1: Initialize string with explicit null terminator
    char greeting[6] = {'H', 'e', 'l', 'l', 'o', '\0'};
    std::cout << "Greeting: " << greeting << std::endl;

    // Method 2: Initialize as a string literal (automatically adds null terminator)
    char name[] = "John Doe";
    std::cout << "Name: " << name << std::endl;

    // Method 3: Declare with fixed size and initialize
    char message[20] = "Welcome to C++!";
    std::cout << "Message: " << message << std::endl;

    // Demonstrate string length
    std::cout << "Length of name: " << strlen(name) << std::endl;

    // Manual string length calculation
    int length = 0;
    while (name[length] != '\0') {
        length++;
    }
    std::cout << "Manual length of name: " << length << std::endl;

    return 0;
}

C スタイルの文字列に関する重要なポイント:

  • Null ターミネータ'\0'は文字列の終わりを示します。
  • 常に null ターミネータ用に 1 文字余分に割り当てます。
  • 文字列リテラルは自動的に null ターミネータを追加します。
  • strlen()関数は、null ターミネータまでの文字数をカウントします。

プログラムをコンパイルして実行します。

g++ c_style_strings.cpp -o c_style_strings
./c_style_strings

出力例:

Greeting: Hello
Name: John Doe
Message: Welcome to C++!
Length of name: 8
Manual length of name: 8

重要な文字列初期化の概念:

  • Null ターミネータは文字列操作に不可欠です。
  • 常に null ターミネータのための十分なスペースを確保してください。
  • オーバーフローを防ぐために、文字列バッファのサイズに注意してください。

String クラスのメソッド(length, substr, find)の使用

このステップでは、文字列操作をより簡単かつ直感的に行うことができる、C++ の強力な string クラスのメソッドについて学びます。length()substr()、およびfind()などの主要なメソッドを探求します。

WebIDE を開き、~/projectディレクトリにstring_methods.cppという新しいファイルを作成します。

touch ~/project/string_methods.cpp

string_methods.cppファイルに以下のコードを追加します。

#include <iostream>
#include <string>

int main() {
    // Create a string
    std::string message = "Hello, C++ Programming!";

    // Using length() method
    std::cout << "String length: " << message.length() << std::endl;

    // Using substr() method
    std::cout << "First 5 characters: " << message.substr(0, 5) << std::endl;
    std::cout << "Substring from index 7: " << message.substr(7) << std::endl;

    // Using find() method
    std::string search_word = "Programming";
    size_t position = message.find(search_word);

    if (position != std::string::npos) {
        std::cout << "'" << search_word << "' found at index: " << position << std::endl;
    } else {
        std::cout << "Word not found" << std::endl;
    }

    // Additional find() example
    std::string email = "user@example.com";
    size_t at_symbol = email.find('@');
    size_t dot_symbol = email.find('.');

    std::cout << "Username: " << email.substr(0, at_symbol) << std::endl;
    std::cout << "Domain: " << email.substr(at_symbol + 1, dot_symbol - at_symbol - 1) << std::endl;

    return 0;
}

string クラスのメソッドに関する重要なポイント:

  • length(): 文字列内の文字数を返します。
  • substr(): 文字列の一部を抽出します。
    • 最初の引数は開始インデックスです。
    • 2 番目の引数(オプション)は、部分文字列の長さです。
  • find(): 部分文字列または文字を検索します。
    • 最初の出現のインデックスを返します。
    • 見つからない場合はstd::string::nposを返します。

プログラムをコンパイルして実行します。

g++ string_methods.cpp -o string_methods
./string_methods

出力例:

String length: 23
First 5 characters: Hello
Substring from index 7: C++ Programming!
'Programming' found at index: 11
Username: user
Domain: example

重要な string メソッドの概念:

  • String メソッドは、強力なテキスト操作を提供します。
  • インデックスは 0 から始まります。
  • 潜在的なエラーを処理するために、常に戻り値を確認してください。

C スタイル文字列と String クラス間の変換

このステップでは、C スタイル文字列と C++ string クラス間の変換方法について学びます。これらの変換は、C++ で異なる文字列表現を扱う際に不可欠です。

WebIDE を開き、~/projectディレクトリにstring_conversion.cppという新しいファイルを作成します。

touch ~/project/string_conversion.cpp

string_conversion.cppファイルに以下のコードを追加します。

#include <iostream>
#include <string>
#include <cstring>

int main() {
    // C-style string to C++ string
    const char* c_style_str = "Hello, C++ World!";
    std::string cpp_string(c_style_str);
    std::cout << "C++ String: " << cpp_string << std::endl;

    // C++ string to C-style string
    std::string message = "Converting strings";
    const char* c_str = message.c_str();
    std::cout << "C-style String: " << c_str << std::endl;

    // Manual conversion using strcpy
    char buffer[50];
    strcpy(buffer, message.c_str());
    std::cout << "Copied to buffer: " << buffer << std::endl;

    // String length comparison
    std::cout << "C++ string length: " << message.length() << std::endl;
    std::cout << "C-style string length: " << strlen(c_str) << std::endl;

    return 0;
}

主要な変換メソッド:

  • std::string(c_style_str): C スタイル文字列を C++ string に変換します。
  • .c_str(): C++ string を C スタイル文字列に変換します。
  • strcpy(): 文字列を手動で文字配列にコピーします。

プログラムをコンパイルして実行します。

g++ string_conversion.cpp -o string_conversion
./string_conversion

出力例:

C++ String: Hello, C++ World!
C-style String: Converting strings
Copied to buffer: Converting strings
C++ string length: 18
C-style string length: 18

重要な変換の概念:

  • C++ string から const char*を取得するには、.c_str()を使用します。
  • 変換する際は、バッファサイズに注意してください。
  • strlen()は C スタイル文字列で使用します。
  • .length()は C++ string で使用します。

バブルソートによる配列要素のソート

このステップでは、C++ で配列要素をソートするためにバブルソートアルゴリズムを実装する方法を学びます。バブルソートは、リストを繰り返しステップスルーし、隣接する要素を比較し、順序が間違っている場合はそれらを交換する単純なソート方法です。

WebIDE を開き、~/projectディレクトリにbubble_sort.cppという新しいファイルを作成します。

touch ~/project/bubble_sort.cpp

bubble_sort.cppファイルに以下のコードを追加します。

#include <iostream>

int main() {
    // Initialize an unsorted array
    int numbers[5] = {64, 34, 25, 12, 22};
    int size = 5;

    // Print original array
    std::cout << "Original Array: ";
    for (int i = 0; i < size; i++) {
        std::cout << numbers[i] << " ";
    }
    std::cout << std::endl;

    // Bubble Sort implementation
    for (int i = 0; i < size - 1; i++) {
        for (int j = 0; j < size - i - 1; j++) {
            // Compare adjacent elements
            if (numbers[j] > numbers[j + 1]) {
                // Swap elements
                int temp = numbers[j];
                numbers[j] = numbers[j + 1];
                numbers[j + 1] = temp;
            }
        }
    }

    // Print sorted array
    std::cout << "Sorted Array: ";
    for (int i = 0; i < size; i++) {
        std::cout << numbers[i] << " ";
    }
    std::cout << std::endl;

    return 0;
}

バブルソートの主要な概念:

  • 隣接する要素を比較します。
  • 順序が間違っている場合は要素を交換します。
  • ソートされるまで、配列を繰り返しパスします。
  • 時間計算量:O(n²)

プログラムをコンパイルして実行します。

g++ bubble_sort.cpp -o bubble_sort
./bubble_sort

出力例:

Original Array: 64 34 25 12 22
Sorted Array: 12 22 25 34 64

重要なソートに関する注意点:

  • バブルソートは単純ですが、大きな配列には非効率的です。
  • 教育目的には適しています。
  • 実際のアプリケーションには、より効率的なソートアルゴリズムが存在します。

配列における線形探索の実装

このステップでは、C++ で線形探索アルゴリズムを実装する方法を学びます。線形探索は、ターゲットが見つかるか、配列の末尾に達するまで、各要素を順番にチェックすることにより、配列内の要素を見つける単純な方法です。

WebIDE を開き、~/projectディレクトリにlinear_search.cppという新しいファイルを作成します。

touch ~/project/linear_search.cpp

linear_search.cppファイルに以下のコードを追加します。

#include <iostream>

int linearSearch(int arr[], int size, int target) {
    // Iterate through each element in the array
    for (int i = 0; i < size; i++) {
        // Check if current element matches the target
        if (arr[i] == target) {
            return i;  // Return the index if found
        }
    }
    return -1;  // Return -1 if target is not found
}

int main() {
    // Create an array of student scores
    int scores[] = {85, 92, 78, 95, 88, 76, 90};
    int size = sizeof(scores) / sizeof(scores[0]);

    // Target score to search
    int targetScore = 78;

    // Perform linear search
    int result = linearSearch(scores, size, targetScore);

    // Display search results
    if (result != -1) {
        std::cout << "Target score " << targetScore
                  << " found at index " << result << std::endl;
    } else {
        std::cout << "Target score " << targetScore
                  << " not found in the array" << std::endl;
    }

    // Try another search
    int missingScore = 100;
    result = linearSearch(scores, size, missingScore);

    if (result != -1) {
        std::cout << "Score " << missingScore
                  << " found at index " << result << std::endl;
    } else {
        std::cout << "Score " << missingScore
                  << " not found in the array" << std::endl;
    }

    return 0;
}

線形探索の主要な概念:

  • 各配列要素を順番にチェックします。
  • 見つかった場合は、ターゲットのインデックスを返します。
  • ターゲットが配列にない場合は、-1 を返します。
  • 時間計算量:O(n) - 線形時間
  • シンプルで、ソートされていない配列でも機能します。

プログラムをコンパイルして実行します。

g++ linear_search.cpp -o linear_search
./linear_search

出力例:

Target score 78 found at index 2
Score 100 not found in the array

重要な検索に関する注意点:

  • 線形探索は簡単ですが、大きな配列には非効率的です。
  • 小さな配列またはソートされていないコレクションに適しています。
  • ソートされた配列には、より効率的な検索アルゴリズムが存在します。

getline() を使用した文字列入力の処理

このステップでは、C++ でテキストの完全な行を入力するためにgetline()を使用する方法を学びます。cin >>とは異なり、getline()はスペースを含む文字列を読み取り、より複雑な入力シナリオを処理できます。

WebIDE を開き、~/projectディレクトリにgetline_input.cppという新しいファイルを作成します。

touch ~/project/getline_input.cpp

getline_input.cppファイルに以下のコードを追加します。

#include <iostream>
#include <string>

int main() {
    // Declare a string to store input
    std::string fullName;
    std::string address;

    // Prompt for full name input
    std::cout << "Enter your full name: ";
    std::getline(std::cin, fullName);

    // Prompt for address input
    std::cout << "Enter your full address: ";
    std::getline(std::cin, address);

    // Display input with additional information
    std::cout << "\n--- User Information ---" << std::endl;
    std::cout << "Name: " << fullName << std::endl;
    std::cout << "Address: " << address << std::endl;

    // Demonstrate reading multiple lines
    std::string multiLineText;
    std::cout << "\nEnter a multi-line description (press Ctrl+D to finish):" << std::endl;

    std::string line;
    while (std::getline(std::cin, line)) {
        multiLineText += line + "\n";
    }

    std::cout << "\nYour description:" << std::endl;
    std::cout << multiLineText;

    return 0;
}

getline()の主要な概念:

  • スペースを含むテキストの行全体を読み取ります。
  • 構文:std::getline(input_stream, string_variable)
  • 複数行の入力を読み取ることができます。
  • スペースを含む複雑な入力を処理します。
  • 氏名や住所などを読み取るのに役立ちます。

プログラムをコンパイルします。

g++ getline_input.cpp -o getline_input
./getline_input

対話例:

Enter your full name: John Michael Smith
Enter your full address: 123 Main Street, Anytown, USA

--- User Information ---
Name: John Michael Smith
Address: 123 Main Street, Anytown, USA

Enter a multi-line description (press Ctrl+D to finish):
This is a sample
multi-line description
with several lines of text.

Your description:
This is a sample
multi-line description
with several lines of text.

重要な入力処理に関する注意点:

  • getline()は改行文字まで読み取ります。
  • 完全なテキスト入力を取得するのに役立ちます。
  • 他の入力方法と組み合わせることができます。

まとめ

この実験では、C++ で一次元配列を作成および初期化し、インデックスを使用して配列要素にアクセスおよび変更し、行列用の二次元配列を実装し、null 終端文字で C スタイルの文字列を初期化し、string クラスのメソッドを使用し、C スタイルと string クラスの間で変換し、バブルソートを使用して配列要素をソートし、配列で線形探索を実装し、getline() で文字列入力を処理する方法を学びます。

配列のサイズを指定してすべての要素を初期化する方法、コンパイラにサイズを決定させる方法、すべての要素をゼロに初期化する方法、インデックスを使用して値を手動で割り当てる方法など、さまざまな配列の初期化方法を学習します。また、インデックスを使用して配列要素にアクセスおよび変更する方法、およびエラーを回避するために配列の境界を処理する方法も学びます。さらに、二次元配列、C スタイルの文字列、および string クラスを操作し、それらの間の変換方法とさまざまな操作の実行方法を学習します。