ほぷしぃ

納得C言語!

[第15回]演習問題W 第3問の解答

演習問題W 第3問の解答


3 役職ごとの平均給与

解答プログラム

//プログラムを書くときには「(1),(2),(3)」は書かないでください
#include <stdio.h>
#include <string.h>

// 構造体(3か月分の給与)
struct kyuyo
{
    int kyu_apl;    // 4月分
    int kyu_mar;    // 5月分
    int kyu_jun;    // 6月分
};

// 構造体(社員)
struct shain
{
    int no;                // 社員番号
    char name[256];        // 社員名
    char busyo[256];       // 部署名
    char fp[256];          // 役職
    struct kyuyo money;    // 給与(構造体)
};

// 関数のプロトタイプ宣言
void fp_avg(struct shain *p);

int main()
{
    int i = 0;

    struct shain list[256];

    struct shain *p;
    p = list;

    //社員データ入力
    //説明は(1)でやっているので省略します
    while(1){
        printf("社員番号:");
        scanf("%d",&(p+i)->no);

        if((p+i)->no==0){
            break;
        }

        printf("社員名:");
        scanf("%s",(p+i)->name);
        printf("部署:");
        scanf("%s",(p+i)->busyo);
        printf("役職:");
        scanf("%s",(p+i)->fp);
        printf("給与\n");
        printf("4月:");
        scanf("%d",&(p+i)->money.kyu_apl);
        printf("5月:");
        scanf("%d",&(p+i)->money.kyu_mar);
        printf("6月:");
        scanf("%d",&(p+i)->money.kyu_jun);
        i++;
        printf("\n");
    }

    //社員表表示
    //説明は省略
    printf("                      給与\n");
    printf("社員番号   氏名  部署 役職   4月   5月   6月\n");

    for(i=0;(p+i)->no!=0;i++){
        printf("%8d%11s%8s%6s%10d%10d%10d\n",
            (p+i)->no,
            (p+i)->name,
            (p+i)->busyo,
            (p+i)->fp,
            (p+i)->money.kyu_apl,
            (p+i)->money.kyu_mar,
            (p+i)->money.kyu_jun
            );
    }

    fp_avg(p);
    return 0;
}

//役職ごとの3ヶ月平均給与
void fp_avg(struct shain *p)
{
    int sum=0;    //合計用
    int i=0;      //ポインタ用
    int j=0;      //人数カウント用
    char *str;

    //strに1人目の役職をコピー
 (1)str = p->fp;

    printf("\n役職ごとの3ヶ月の平均給与\n");

    //(p+i)->noが0になるまで繰り返す
    while(((p+i)->no)!=0){

        //strと(p+i)->fpを比較し同じ役職であれば繰り返す
        while((2)strcmp(str,(p+i)->fp)==0){

            //sumに現在の社員の給与を格納(この時sum自身も加算します)
            sum = sum + (p+i)->money.kyu_apl + (p+i)->money.kyu_mar + (p+i)->money.kyu_jun;

            //ポインタを一つ進める
            i++;
            //人数をカウント
            j++;
        }

        //役職の平均給与を算出し表示
        printf(" 役職   給与額\n");
        printf("%6s %10d\n",str,sum/(j*3));

        (3)//人数と合計をで初期化
        j=0;
        sum=0;

        //strを初期化し次の役職を格納する
        str = "";
        str = (p+i)->fp;
    }
}


解説

社員データの入力と表示は(1)、(2)と同じですね。
自作関数内の説明に入ります。
(1)で1人目の役職をstrに格納します。
まず「部長」がstrに格納されますね。

strに一人目を格納

(2)ではstrと(p+i)->noの比較をしています。
このときiは0なので(p+0)->noとstrを比較。
「部長」で同じなのでwhile文の中を実行します。
sumにsumとその社員の3ヶ月分の給与を代入します。
また、iとjの値に1加算します。

役職の比較

そして再びstrcmpで比較します。
まだ部長で同じですね。
なので、sumにsumと2人目の社員の給与を代入します。

iとjが3まできました。

比較を続ける

(3)で比較をすると、strは部長ですが、(p+3)->fpは課長ですね。
なので今回でwhile文から抜け出します。
抜け出したあと、strの役職の平均給与を計算し、表示しています。
このままではjにこれまでの人数が、strに前の役職が格納されたままなので、網掛けの部分で初期化します。
初期化されると下のようになります

strに次の役職を格納

strに課長、jに0が格納されましたね。

これを、社員番号が0になるまで繰り返します。
このくらいのプログラムが書けるようになれば、C言語を理解できたといえるでしょう


あとがき

C言語の学習の方は順調でしょうか?
今回はC言語で最も難しいと言われているポインタと構造体の学習を行いました。
ポインタや構造体は理解するのに時間がかかりますが、使いこなすことが出来ると本当に便利です。

正直、今回の学習ではポインタや構造体の全てを語りきることが出来ませんでした。
この学習を終えて、ポインタや構造体をもう少し詳しく知りたいと思った時にさらに深いところまで調べるといいでしょう。
今よりさらなる壁が立ちはだかりますが、それを乗り越えた時には間違いなくC言語の知識を身に付けたと実感しますよ。

さて、次回はいよいよ最終回です。
ここまでたどり着いたあなたならもう怖いものなしでしょう。


ヒント ページのトップ [第16回]ファイル入出力