第4回:ポインタと配列


 今週は,C言語を学習する上でもっとも挫折することの多い,でも,C言語のもっともC言語らしいところである,ポインタについて取り上げます.


【先週の演習】

次の成績表から,各人の合計点,偏差値を求めなさい.

ヒント: 出席番号は1から始まるが,配列は0から始まることに注意しよう

出席番号 国語 数学 理科 社会 英語 合計点 偏差値
1 65 71 74 82 97 - -
2 84 83 74 64 65 - -
3 74 74 78 80 78 - -
4 90 90 90 90 90 - -
5 87 78 85 60 88 - -
6 93 95 94 92 95 - -

ステップ1

各人の合計点と,試験全体の平均値を求めるプログラムを作ろう.

[ステップ1の答え]

#include <stdio.h>

void main()
{
    int i, j;
    float seiseki[6][7]={{65,71,74,82,97,0,0},
                               {84,83,74,64,65,0,0},
                               {74,74,78,80,78,0,0},
                               {90,90,90,90,90,0,0},
                               {87,78,85,60,88,0,0},
                               {93,95,94,92,95,0,0}};
    float sum=0;

    for(i = 0; i<6; i++){
        for(j=0; j<5; j++){
            seiseki[i][5] += seiseki[i][j];
        }
        printf("%d 番目の人の合計点: %f\n", i+1, seiseki[i][5]);
        sum += seiseki[i][5];
    }

    printf("平均値=%f\n", sum/6.0);
}

ここで,平均を求める際に,(整数)÷(整数)の形で計算すると,結果も整数になってしまうので,注意しよう.


 ポインタの前に,ウォーミングアップとして アドレス について復習します.


アドレスとは?

 変数や配列は,コンピュータのメモリ上にあります.このメモリには,アドレスという連続した番号がついていて,管理されています.

 では,ある変数の使っているメモリのアドレスを調べるには,どうしたらよいでしょうか.変数名の頭に「&」を付けると,そのデータがしまわれているメモリのアドレスを意味します.(scanf関数を用いてキーボードから値を読み取るとき,変数名の頭に,「&」を付けたのを思い出してください.)

#include <stdio.h>

void main()
{
    int a;
    
    printf("aのアドレスは,%x です\n", &a);
}

 逆にあるアドレスにしまわれている値を調べるには,どうしたらよいでしょうか?


ポインタ変数とは?

データのメモリアドレスを指し示す(ポイントする)ための変数

ポインタ変数の値 = メモリアドレス

  参考 : 普通の変数の値 = 数値や文字


ポインタ変数の基本的な書式

int *p;
ポインタ変数の宣言.型を指定し,変数名の前に*をつける
p = &a;
ポインタ変数pにはint型変数aのアドレスが入る.ポインタ変数にアドレスを入れるには,対象となる変数の前に&をつける
b = *p;
ポインタ変数に格納されているアドレスに格納されているを取り出すには,ポインタ変数の前に*をつける

例:

#include <stdio.h>

void main()
{
    int a, b;
    int *p;

    a = 3;
        printf("aのアドレスは,%x です\n", &a);  
    p = &a;
        printf("ポインタ変数の値(アドレス)は,%x です\n", p);  
        printf("ポインタ変数のさしている値は,%d です\n", *p);  
    b = *p;
        printf("bの値は,%d です\n", b);
}

配列とポインタの関係

 配列の名前そのものは,実は,配列の最初の要素を指し示すポインタです.

 例を見てみましょう.

#include <stdio.h>

void main()
{
    int a[5] = {10, 20, 30, 40, 50};   /* 配列 */
    int *p;   /* ポインタ変数 */
    int b, c;

    printf("配列aの先頭のアドレスは,%x です\n", a);
    printf("aのさしている値は,%d です\n", *a);

    p = a+2;    /* pは,aから2つ先をさします */
    printf("a[2]の中身は,%d です\n", *p);

    b = *(a+3);    /* bは,aから3つ先の値が代入されます */
    printf("a[3]の中身は,%d です\n", b);  

    c = *a+3;     /* cは,a[0]の値に3足した値が代入されます */
    printf("a[0]+3 は,%d です\n", c);  
}

今日の演習

【1】

変数a,bに数字をキーボードから入力し,a+bを求めて表示するプログラムをポインタ変数を使って書き換えよ.

元になるプログラム:

#include <stdio.h>

void main()
{
    int a, b;

    scanf("%d", &a);
    scanf("%d", &b);

    printf("a + b = %d\n", a+b);
}

書き換えるプログラム:

#include <stdio.h>

void main()
{
    int a,b;
    int *pa,*pb;

    pa = &a;
    pb = &b;

    scanf("%d",?????);
    scanf("%d",?????);

    printf("a + b = %d\n",?????????);
}

【2】

整数型配列に初期値として,(10,20,30,40,50)を設定したとき,全ての要素の値を表示するプログラムをポインタを用いて作成しなさい.


【3】

二つの文字列,「abc」と「xyz」を,一つの配列にするプログラムをポインタを用いて作成しなさい.


Oh-o! Meijiのレポートから(第4回)のところへ,演習で作成したプログラムを送る.プログラムには必ず,学年,組,番号,氏名を記入すること.