C 言語における配列要素の操作

CBeginner
オンラインで実践に進む

はじめに

この実験では、C プログラミングにおける配列要素の操作方法を学びます。この実験では、配列の宣言と初期化、配列要素のアクセスと変更、配列の反復処理、配列計算の実行、および配列メモリの動的割り当てといった基本的なスキルがカバーされます。特定の値で配列を宣言および初期化したり、配列を部分的に初期化したり、配列要素に値を動的に割り当てたりするなど、配列を操作するさまざまな手法を探求します。この実験が終了するとき、C 言語における配列データ構造を効果的に管理および操作する方法を十分に理解しているようになります。

配列を宣言して初期化する

このステップでは、C プログラミングにおける配列の宣言と初期化方法を学びます。配列は、同じ型の複数の要素を連続したメモリ領域に格納できる基本的なデータ構造です。

配列の宣言と初期化を調べるために新しい C ファイルを作成しましょう。

cd ~/project
touch array_basics.c

次に、配列の宣言と初期化のさまざまな方法を示すプログラムを書きましょう。

#include <stdio.h>

int main() {
    // 方法 1: 特定の値で配列を宣言して初期化する
    int numbers[5] = {10, 20, 30, 40, 50};

    // 方法 2: 配列を宣言して後で初期化する
    int scores[3];
    scores[0] = 85;
    scores[1] = 92;
    scores[2] = 78;

    // 方法 3: 配列を部分的に初期化する (残りの要素は 0 に設定される)
    int grades[4] = {100, 95};

    // 初期化を確認するために配列を表示する
    printf("Numbers array: ");
    for (int i = 0; i < 5; i++) {
        printf("%d ", numbers[i]);
    }
    printf("\n");

    printf("Scores array: ");
    for (int i = 0; i < 3; i++) {
        printf("%d ", scores[i]);
    }
    printf("\n");

    printf("Grades array: ");
    for (int i = 0; i < 4; i++) {
        printf("%d ", grades[i]);
    }
    printf("\n");

    return 0;
}

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

gcc array_basics.c -o array_basics
./array_basics

出力例:

Numbers array: 10 20 30 40 50
Scores array: 85 92 78
Grades array: 100 95 0 0

配列の初期化方法を分解してみましょう。

  1. int numbers[5] = {10, 20, 30, 40, 50};

    • 5 つの要素を持つ整数型の配列を宣言する
    • すべての要素を特定の値で初期化する
    • サイズは初期化子リストの要素数によって決まる
  2. int scores[3]; その後個々の要素に代入する

    • まず配列を宣言する
    • 後で個々の要素に値を代入する
    • 値を動的に設定したい場合に便利
  3. int grades[4] = {100, 95};

    • 配列を部分的に初期化する
    • 不明な要素は自動的に 0 に設定される
    • 一部の初期値のみを設定したい場合に時間を節約できる

覚えておくべき要点:

  • 配列のインデックスは 0 から始まる
  • 配列が格納する要素の型を指定する必要がある
  • 配列は宣言後、固定サイズになる
  • 常に宣言されたサイズを超えて配列要素にアクセスしないようにすること

配列要素にアクセスして変更する

このステップでは、C プログラミングにおいて配列の個々の要素にアクセスして変更する方法を学びます。前のステップを基に、インデックスを使って配列要素とやり取りする方法を調べ、配列の内容を操作するさまざまな方法を示します。

配列要素にアクセスして変更する練習をするために新しい C ファイルを作成しましょう。

cd ~/project
touch array_access.c

次に、配列要素のアクセスと変更を示すプログラムを書きましょう。

#include <stdio.h>

int main() {
    // 配列を宣言して初期化する
    int temperatures[5] = {72, 68, 75, 80, 65};

    // 個々の配列要素にアクセスする
    printf("First temperature: %d\n", temperatures[0]);
    printf("Third temperature: %d\n", temperatures[2]);

    // 配列要素を変更する
    temperatures[1] = 70;  // 2 番目の要素を変更する
    temperatures[4] = 73;  // 最後の要素を変更する

    // 変更された配列を表示する
    printf("Modified temperatures: ");
    for (int i = 0; i < 5; i++) {
        printf("%d ", temperatures[i]);
    }
    printf("\n");

    // 配列要素の計算を示す
    int average = (temperatures[0] + temperatures[1] + temperatures[2] +
                   temperatures[3] + temperatures[4]) / 5;
    printf("Average temperature: %d\n", average);

    return 0;
}

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

gcc array_access.c -o array_access
./array_access

出力例:

First temperature: 72
Third temperature: 75
Modified temperatures: 72 70 75 80 73
Average temperature: 74

重要な概念を分解してみましょう。

  1. 配列のインデックス

    • 配列は 0 から始まるインデックスを使ってアクセスされます
    • temperatures[0] は最初の要素を指します
    • temperatures[4] は 5 要素の配列の最後の要素を指します
  2. 配列要素の変更

    • 個々の要素はそのインデックスを使って直接変更できます
    • temperatures[1] = 70; は 2 番目の要素を 70 に置き換えます
    • 有効なインデックスのいずれかで要素を変更できます
  3. 配列要素の計算

    • 個々の配列要素を使って計算を行うことができます
    • 例では、平均気温を計算しました
    • 数学的演算ではインデックスを使って要素に直接アクセスします

避けるべき一般的な落とし穴:

  • 配列の範囲外のインデックスにアクセスしないでください
  • 配列のインデックスは 0 から始まり、1 からではありません
  • 配列の宣言されたサイズを超えないように注意してください

配列を反復処理する

このステップでは、C プログラミングにおいて配列を反復処理するさまざまな方法を学びます。反復処理は、配列要素を効率的に処理し、配列の内容に対してさまざまな操作を行うために重要です。

配列の反復処理技術を調べるために新しい C ファイルを作成しましょう。

cd ~/project
touch array_iteration.c

次に、配列を反復処理する複数の方法を示すプログラムを書きましょう。

#include <stdio.h>

int main() {
    // 学生の点数の配列を宣言して初期化する
    int scores[6] = {85, 92, 78, 90, 88, 95};
    int total = 0;

    // 方法 1: 標準的な for ループを使用する
    printf("方法 1 - 標準的な For ループ:\n");
    for (int i = 0; i < 6; i++) {
        printf("点数 %d: %d\n", i + 1, scores[i]);
        total += scores[i];
    }

    // 合計点を計算して表示する
    float average = (float)total / 6;
    printf("\n合計点数:%d\n", total);
    printf("平均点数:%.2f\n", average);

    // 方法 2: 逆順反復処理
    printf("\n方法 2 - 逆順反復処理:\n");
    printf("逆順の点数:\n");
    for (int i = 5; i >= 0; i--) {
        printf("点数 %d: %d\n", i + 1, scores[i]);
    }

    // 方法 3: while ループによる反復処理
    printf("\n方法 3 - while ループによる反復処理:\n");
    int j = 0;
    while (j < 6) {
        if (scores[j] >= 90) {
            printf("高得点検出:%d\n", scores[j]);
        }
        j++;
    }

    return 0;
}

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

gcc array_iteration.c -o array_iteration
./array_iteration

出力例:

方法 1 - 標準的な For ループ:
点数 1: 85
点数 2: 92
点数 3: 78
点数 4: 90
点数 5: 88
点数 6: 95

合計点数: 528
平均点数: 88.00

方法 2 - 逆順反復処理:
逆順の点数:
点数 6: 95
点数 5: 88
点数 4: 90
点数 3: 78
点数 2: 92
点数 1: 85

方法 3 - while ループによる反復処理:
高得点検出: 92
高得点検出: 90
高得点検出: 95

重要な反復処理技術:

  1. 標準的な for ループ

    • 配列の反復処理に最も一般的な方法
    • インデックスの精密な制御を可能にする
    • 前方処理に最適
  2. 逆順反復処理

    • 最後の要素から最初の要素まで反復処理する
    • 特定の処理要件に役立つ
    • 降順のループカウンタを使用する
  3. while ループによる反復処理

    • 柔軟な反復処理制御を提供する
    • 条件付き処理を含めることができる
    • 複雑な反復処理ロジックに役立つ

重要な反復処理の原則:

  • 常に明確なループの境界を定義する
  • 配列の長さを使用して範囲外アクセスを防止する
  • 特定のタスクに最適な反復処理方法を選択する

配列の計算を行う

このステップでは、C プログラミングにおいて配列に対してさまざまな計算を行う方法を学びます。最大値と最小値を見つける、合計値や平均値を計算する、および配列要素に数学的変換を適用する技術を探求します。

配列の計算を練習するために新しい C ファイルを作成しましょう。

cd ~/project
touch array_calculations.c

次に、さまざまな配列計算技術を示すプログラムを書きましょう。

#include <stdio.h>
#include <limits.h>

int main() {
    // 販売データの配列を宣言して初期化する
    int sales[7] = {1200, 1500, 980, 1750, 1100, 1300, 1600};

    // 総販売額を計算する
    int total_sales = 0;
    for (int i = 0; i < 7; i++) {
        total_sales += sales[i];
    }
    printf("週間総販売額:$%d\n", total_sales);

    // 平均販売額を計算する
    float average_sales = (float)total_sales / 7;
    printf("日平均販売額:$%.2f\n", average_sales);

    // 最大販売額を見つける
    int max_sales = sales[0];  // 最初の要素から始める
    for (int i = 1; i < 7; i++) {
        if (sales[i] > max_sales) {
            max_sales = sales[i];
        }
    }
    printf("最高日販売額:$%d\n", max_sales);

    // 最小販売額を見つける
    int min_sales = sales[0];  // 最初の要素から始める
    for (int i = 1; i < 7; i++) {
        if (sales[i] < min_sales) {
            min_sales = sales[i];
        }
    }
    printf("最低日販売額:$%d\n", min_sales);

    // 増加率を適用する
    float increase_percentage = 1.1;  // 10% 増加
    printf("\n10% 増加後の販売額:\n");
    for (int i = 0; i < 7; i++) {
        float increased_sale = sales[i] * increase_percentage;
        printf("日 %d: $%.2f\n", i + 1, increased_sale);
    }

    return 0;
}

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

gcc array_calculations.c -o array_calculations
./array_calculations

出力例:

週間総販売額: $9430
日平均販売額: $1347.14
最高日販売額: $1750
最低日販売額: $980

10% 増加後の販売額:
日 1: $1320.00
日 2: $1650.00
日 3: $1078.00
日 4: $1925.00
日 5: $1210.00
日 6: $1430.00
日 7: $1760.00

重要な配列計算技術:

  1. 合計計算

    • すべての配列要素を合計するためにループを使用する
    • 別の変数に値を蓄積する
    • 合計値を見つけるのに役立つ
  2. 平均計算

    • 合計値を要素数で割る
    • 浮動小数点数の精度のために型キャストを使用する
    • 配列要素の平均値を提供する
  3. 最大値/最小値の見つけ方

    • 最初の配列要素で初期化する
    • その後の各要素と比較する
    • 新しい極値が見つかったときに最大値/最小値を更新する
  4. 要素ごとの変換

    • 各要素に数学的演算を適用する
    • 特定のルールに基づいて配列値を変更できる
    • データのスケーリング、調整、または変換に役立つ

重要な計算の原則:

  • 常に配列の範囲を考慮する
  • 適切なデータ型を使用する
  • 整数除算に注意する
  • 計算前に累積変数を初期化する

配列のメモリを動的に割り当てる

このステップでは、C プログラミングにおいて malloc()realloc()、および free() 関数を使って配列のメモリを動的に割り当てる方法を学びます。動的メモリ割り当てにより、実行時に決定されるサイズの配列を作成できます。

動的メモリ割り当てを調べるために新しい C ファイルを作成しましょう。

cd ~/project
touch dynamic_array.c

次に、動的配列のメモリ割り当てを示すプログラムを書きましょう。

#include <stdio.h>
#include <stdlib.h>

int main() {
    // 整数型配列の動的メモリ割り当て
    int array_size;
    printf("要素数を入力してください:");
    scanf("%d", &array_size);

    // メモリを動的に割り当てる
    int *dynamic_array = (int *)malloc(array_size * sizeof(int));

    // メモリ割り当てが成功したかどうかを確認する
    if (dynamic_array == NULL) {
        printf("メモリ割り当てに失敗しました!\n");
        return 1;
    }

    // 配列要素を入力する
    printf("%d 個の整数を入力してください:\n", array_size);
    for (int i = 0; i < array_size; i++) {
        printf("要素 %d: ", i + 1);
        scanf("%d", &dynamic_array[i]);
    }

    // 配列要素を表示する
    printf("\n配列要素:\n");
    for (int i = 0; i < array_size; i++) {
        printf("%d ", dynamic_array[i]);
    }
    printf("\n");

    // 配列のサイズを動的に変更する
    int new_size;
    printf("\n新しい配列サイズを入力してください:");
    scanf("%d", &new_size);

    // メモリを再割り当てする
    int *resized_array = (int *)realloc(dynamic_array, new_size * sizeof(int));

    // 再割り当てが成功したかどうかを確認する
    if (resized_array == NULL) {
        printf("メモリ再割り当てに失敗しました!\n");
        free(dynamic_array);
        return 1;
    }

    dynamic_array = resized_array;

    // 新しいサイズが大きい場合、新しい要素を初期化する
    if (new_size > array_size) {
        for (int i = array_size; i < new_size; i++) {
            dynamic_array[i] = 0;
        }
    }

    // サイズ変更後の配列を表示する
    printf("サイズ変更後の配列:\n");
    for (int i = 0; i < new_size; i++) {
        printf("%d ", dynamic_array[i]);
    }
    printf("\n");

    // 動的に割り当てたメモリを解放する
    free(dynamic_array);

    return 0;
}

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

gcc dynamic_array.c -o dynamic_array
./dynamic_array

実行例:

要素数を入力してください: 3
3 個の整数を入力してください:
要素 1: 10
要素 2: 20
要素 3: 30

配列要素:
10 20 30

新しい配列サイズを入力してください: 5
サイズ変更後の配列:
10 20 30 0 0

重要な動的メモリ割り当ての概念:

  1. malloc() 関数

    • 要求されたメモリを割り当て、ポインタを返す
    • 構文:pointer = (type *)malloc(size * sizeof(type))
    • 割り当てが成功したことを確認するために常に NULL をチェックする
  2. realloc() 関数

    • 以前に割り当てられたメモリブロックのサイズを変更する
    • 配列のサイズを増やすか減らすことができる
    • 拡張時に既存のデータを保持する
  3. free() 関数

    • 動的に割り当てられたメモリを解放する
    • メモリリークを防止する
    • malloc()/realloc() 割り当てに対して呼び出す必要がある

重要なメモリ割り当ての原則:

  • 常に割り当ての成功を確認する
  • 必要なくなったら動的に割り当てたメモリを解放する
  • 配列のサイズを変更する際に注意する
  • 潜在的な割り当て失敗に対処する際には適切に対応する

まとめ

この実験では、C プログラミングにおいて配列を宣言して初期化する方法、配列要素にアクセスして変更する方法、配列を反復処理する方法、配列の計算を行う方法、および配列のメモリを動的に割り当てる方法を学びました。配列を宣言して初期化するさまざまな方法を調べました。それには、直接値を指定する方法、後で値を割り当てる方法、および配列を部分的に初期化する方法が含まれます。また、配列の内容を表示して初期化を確認する方法も学びました。これらの基本的な配列操作は、C のデータ構造を扱う際に不可欠であり、より複雑な配列操作のための土台となります。