C言語 プログラムを3か月で身につけるための第4週でやるべきこと

  • このエントリーをはてなブックマークに追加
Pocket

C言語を3か月で身につけてるための第4週でやるべきことは、

・構造体
・文字列

です。構造体を使わなくてもプログラムを書くことができますが、データの扱いがバラバラになってほしくないときに、構造体を使うと便利です。
文字列は文字で扱うのとは違うので、注意が必要です。

大まかなスケジュールはこちらのページを参照ください。

———————————————————————–
C言語 プログラムを3か月で身につけるスケジュール
———————————————————————–

では、早速書いていきます。

第4週

構造体とは

配列は、同じ型のデータを複数持つイメージでした。構造体は、複数の変数を1つの名前でまとめたものです。

構造体の宣言の仕方の例です。

  構造体の例
    struct student {
       int  id;       /* 学籍番号 */
       char name[20]; /* 名前 */
       int  kokugo;   /* 国語の点数 */
       int  suugaku;  /* 数学の点数 */
       int  eigo;     /* 英語の点数 */
       int  rika;     /* 理科の点数 */
       int  syakai;   /* 社会の点数 */
    };

student を構造体タグ、構造体の要素 id, name, kokugo, suugaku, eigo, rika, syakai をメンバといいます。

構造体のメンバの型はなんでも構いません。配列もメンバにすることができます。ただし、構造体の中に同じ構造体のメンバを持つことはできません。しかし、構造体のポインタをメンバに持つことは可能です。

構造体を表す変数を定義するには

struct student taro;

と記述します。さらに構造体のメンバにアクセスするには

  taro.id
  taro.name

というようにドットを用いてアクセスします。また、変数がポインタのときは ”->” でアクセスすることができます。

変数の宣言が長くなるので構造体の宣言時に次のようにしておくと便利です。

typedef struct student {
     メンバ宣言
  } STUDENT_S;

  変数宣言時
  STUDENT_S  taro;

と typedef を用いると変数宣言時に短くすることができます。

構造体の使い方

構造体の使う場面ですが、複数ある関連データをひとまとめにしたいときに使います。別に構造体を使わないといけないわけではありませんが、使ったほうが、データの扱いがしやすいというところがあります。

例えば、生徒の各教科の点数、住所録、商品情報など、いろいろあると思います。

ここでは、生徒の各教科の情報を扱う構造体を宣言し、平均点を計算プログラムを書いてみます。

(例) #include <stdio.h>

     typedef struct student {
        int  id;       /* 学籍番号 */
        char name[20]; /* 名前 */
        int  kokugo;   /* 国語の点数 */
        int  suugaku;  /* 数学の点数 */
        int  eigo;     /* 英語の点数 */
        int  rika;     /* 理科の点数 */
        int  syakai;   /* 社会の点数 */
     } STUDENT_S;

     /* 五教科の平均を計算するための関数 */
     double  AverageCalculation( STUDENT_S* sp ) {
        int    total;  /* 五教科の合計 */
        double avg;    /* 五教科の平均 */

        /* 五教科の合計の計算 */
        total = sp->kokugo + sp->suugaku + sp->eigo + sp->rika + sp->syakai;
        /* 平均の計算 */
        avg = (double)total / 5.0;

        return avg;
     } 

     main() {
        STUDENT_S  taro;     /* 太郎の情報 */
        double     average;  /* 平均 */

        /* 太郎情報代入 */
        taro.id = 1;
        taro.name = "taro";
        taro.kokugo = 73;
        taro.suugaku = 90;
        taro.eigo = 80;
        taro.rika = 82;
        taro.syakai = 68;

        /* 平均計算実行 */
        average = AverageCalculation( &taro );

        /* 結果を出力 */ 
        printf( "太郎の五教科の平均は%lf点です。\n", average );
     }

     出力結果
     太郎の五教科の平均は78.6点です。

構造体の情報として、学籍番号、名前、各教科の点数をメンバに持つようにしました。もちろん、これを定義しただけでは何の意味もありません。

次に、五教科の平均点を求める関数AverageCalculationを定義しました。戻値に求めた平均点を浮動小数点型のdoubleで、引数に先ほど作った構造体のポインタを持たせています。

まず、平均点を求めるのに、まずは五教科の合計点を求める必要がありますね。先ほど解説した通り、構造体のメンバへのアクセスはポインタなので、「sp->メンバ変数」を使って各教科の点数を取得しているのがわかると思います。

これらの合計を変数totalへ代入し、五教科なので、5で割って平均点を出しています。ここで、注意してほしいのは、平均点はdouble型なので、変数totalをdouble型に型変換しています。

型変換するには、変数の前に、変換したい型を()で囲めばOKです。ただし、何でもかんでも型変換できるものではないので、変数の型はあらかじめ、表したい桁を決めておくほうがよいです。

この型変換ですが、この計算のときだけ、double型として計算するので、変数totalそのものの型はint型のままです。

そして、5で割るのもわざと小数点で表しています。こうすることで、浮動小数点扱いですよと、コンパイラに教えておくわけです。小数点をつけなければ、整数とみなされます。

この関数では、平均点を小数点以下ありで求めていますが、もちろん、整数で求めてもよいです。そのときの求められている精度で決めてください。
整数の割り算は切り捨てられるので、四捨五入して求めておくほうがよいでしょう。しかし、これも求められる内容によります。

また、引数の構造体ポインタspがNULLというポインタでないことを確認していませんが、確認しておいたほうがいいです。ポインタに有効なアドレスが入っていなければ、プログラムが走りません。

main関数ですが、構造体変数をtaroとして宣言しています。ここでは、生徒一人だけのデータの扱いになっています。

もちろん、構造体を配列で宣言することが可能です。したがって、複数人の情報を持ちたければ、「STUDENT_S data_1kumi[40]」とすればいいのです。
これで、1組の生徒分のデータを扱う構造体配列ということになります。

例のプログラムでは複雑になってしまうため、配列にしていません。

taroのデータを入力しています。ここは、printf文、scanf文を使って入力するようにしてもいいでしょう。そうしたほうが、汎用的です。ですが、入力エラーの処理をする必要があるため、例ではプログラムでの代入としています。

main関数での代入は構造体変数がポインタではありませんので、「taro.メンバ変数」で構造体のメンバへアクセスしています。

平均点を求める関数AverageCalculationの引数に構造体変数taroのアドレスを渡しています。変数の前に「&」をつけたら、その変数のアドレスを取得できるということはおわかりですよね?

C言語 プログラムを3か月で身につけるための第3週でやるべきことで解説した内容です。

平均点をaverageに代入し、それを出力して終了です。

これが、構造体配列の場合は、for文を使って、データを入力していけばいいですし、平均点自体を構造体のメンバにして、結果をそのメンバ変数に代入してもよいと思います。

文字列について

すでに、先の構造体の使い方のプログラム例で、文字列を扱っていました。おわかりになりましたか?

そうです。生徒の名前を格納するための構造体メンバのchar name[20]です。

taro.name = “taro”

と記述している箇所です。このname配列を0番目からアクセスすると、

name[0]:'t'
name[1]:'a'
name[2]:'r'
name[3]:'o'

となります。文字を扱うときは’ ‘(シングルクォーテーション)で囲み、文字列として扱うときは” “(ダブルクォーテーション)で囲みます。
代入する際は、文字の場合は、通常の数値と同じように何番目の配列に代入とし、文字列の場合は、配列の先頭アドレスに代入する記述をします。

文字はASCIIコードと呼ばれるデータに変換されるので、’a’とあれば、データは「41」となります。文字のつもりでの name[0] = t という代入はできません。

考えてもらえばわかると思いますが、何も囲われずに「t」と記述されていると、どこかに定義された変数tの値を代入することになってしまいます。
tという変数がどこにも定義されていなければ、コンパイルエラーになります。

組み込みマイコンでは、文字を扱うことはあっても、文字列で扱うことはほとんどありません。通信データで文字の送受信を行うとしても、1文字ずつ扱うことが多いからです。文字と文字列は扱い方が異なるので、注意が必要です。

今の段階では、文字は’ ‘で囲んで変数に代入、文字列は” “で囲んでポインタに代入と覚えておけばいいです。

まとめ

C言語のプログラムを3か月で身につけるための第4週でやるべきことを解説しました。

・構造体
・文字列

ここまで、たどり着いたあなたは、すでにプログラムをある程度組めるようになっています。本当にそうなのかなと思うかもしれませんが、始めた当初と比べてみてください。

いろんなことが出てきたはずです。変数宣言にはじまり、if文、for文、switch文、while文、配列、関数、ポインタ、構造体。他にも細かいもの(breakやcontinueなど)も出てきましたね。

これだけを知っていたら、ある程度プログラムが組めます。ここでは出しませんでしたが、共用体やファイルアクセスなど、挙げればキリがありません。

しかし、いきなりすべてをマスターすることなんて不可能です。また、進むジャンルによっては使用しないものも存在します。組み込みマイコンでいえば、ファイルアクセスをすることはないですし、printf文やscanf文などの標準関数も使いません。

したがって、あなたが進むべきジャンルで覚えておかなくてはいけないものが変わります。どのジャンルでもここまで紹介した内容は、マスターしておく必要があると思いますので、解説してきました。

1か月で最低限の文法と使い方を覚えたら、いよいよ、次は、実際にプログラムをいじっていき、プログラミングに慣れていく段階です。

  • このエントリーをはてなブックマークに追加

コメントを残す

*