[C言語]入力された点数からヒストグラムを表示するプログラム[コード付き]

C言語

今回はC言語で、入力された点数を読み込んで標準出力にそのデータのヒストグラムを表示するプログラムを書いていきます。switch文を用います。


ヒストグラムとは

ヒストグラムとは、縦軸に度数、横軸に階級をとった統計グラフの一種である
(wikipediaより)

まあ簡単に言ったらなんかのデータを集めてそれを一定の区間で区切って(階級)それを棒グラフで表したものですね。

C言語でどうやってヒストグラムを表示するの?

方法は色々あると思いますが、今回はシンプルに実行結果の部分に文字*を用いてヒストグラムを表現します。

一応、生徒のテストの点数データをヒストグラムで表示するっていう設定でやっていきます。

コード実装

まずは大まかな構想を考えましょう。
パッと思いつくのは

  • データを読み込む部分
  • データを階級ごとに分ける部分
  • ヒストグラムを表示する部分

ですかね。

階級分けの部分

まずここから作りましょう。
必要な機能を箇条書きすると

  • 点数のデータが入った配列を受けとる
  • データを一つ一つ見ていき、どこの階級に振り分けるか判断する

となります。

とりあえず関数の引数でデータ配列を受け取ります。
ここから点数のデータを0~100の間で5つに分けた階級に振り分けていくのですが、

このように実際に振り分けたりはしません。

このようにデータ配列の要素をひとつずつ見ていって、その要素が振り分けられるべき階級のカウンターを1ずつ増やしていきます。
ヒストグラムを表示するだけならその階級の度数さえ分かれば良いですしね。

階級の判別は要素を20で割った時の商を用います。

具体的には
商が0なら階級は0~19、
商が1なら階級は20~39といった感じです。

商で振り分ける際の便利な点は、その式をそのままswitch文で使えることですね。
本当は点数が100の時だけ20で割った商が5になってしまうのですが、それだと見栄えが悪いので最後の階級は80~100とします。
そのためにcase4でなくdefaultとしていることを確認してください。

switch文で分岐した先では、その階級のカウンターを1つ増加させます。
この作業をfor文で繰り返してすべてのデータに対して判断したら準備完了。

ヒストグラム表示

次にヒストグラム表示です。
各階級においてprintfで階級の範囲を表示した後に、対応するカウンターの数だけforループでputchar文で*を表示していきます。
各階級が終わるたびに改行を出力してヒストグラムの体裁を整えます。

階級分けと、ヒストグラム表示をまとめて関数にしたものがこちら

void histgram(int v[N]){
    int i=0;
    
    int X[5]={};
    
    for(i=0; i<N; i++){
        switch(v[i]/20){
            case 0: X[0]++; break;
            case 1: X[1]++; break;
            case 2: X[2]++; break;
            case 3: X[3]++; break;
            default: X[4]++; break;
        }
    }
    
    for(i=0; i<4; i++){
        int n;
        printf("%2d- %2d :",20*i,20*(i+1)-1);
        for(n=0; n<X[i]; n++)
            putchar('*');
        
        printf("\n");
    }
    
    printf("80-100 :");
    
    for(i=0; i<X[4]; i++)
        putchar('*');
    
    printf("\n");
}

X[5]が各階級におけるカウンターです。

またヒストグラムを表示する部分の階級の範囲の表示は一つ一つ打ち込むのがめんどかったので計算式にしました。20×i ~ 20×(i+1)-1ですね。

だけどここでも100がハブられているので80~100だけ個別に書きました。なんかいい方法あったかな…
そこでも改行は忘れずに!!

データ読み込みとmain関数

ここではまず点数のデータをユーザーから受け取りましょう。
今回は標準入力、つまりキーボートからの打ち込みで受け取ります。
受け取り用の配列を用意してfor文でデータの数scanfで受け取るだけですね。超簡単。

注意として今回は100点満点のテストで、ヒストグラムもそれを前提として表示するのでそこだけ気をつけましょう。
具体的には受け取る際に、入力された値が0~100かを判定して大丈夫なら良し!大丈夫じゃないならdo-while文で範囲内の値を受け取るまで繰り返せば良いですね。
判別には( date[i]>100 || date[i]<0)でいきましょう。

そんで全部のデータを受け取ったらさっき作った関数に渡しましょう。こんだけです。超簡単ですね。

int main(void) {
    int date[N];
    int i;
    
    printf("点数を入力してください (%d人分)\n",N);
    for(i=0; i<N; i++){
        do{
            printf(":");
            scanf("%d",&date[i]);
            if(date[i]>100 || date[i]<0)
                printf("正しい値を入力してください");
        }while( date[i]>100 || date[i]<0);
    }
    
    histgram(date);
    
    return 0;
}

2つのコードを組み合わせて完成です!

ちなみにNはオブジェクト形式マクロです。自分で好きな値にしましょう。
また#include <stdio.h>もわすれずに。

実際に動かしてみた

N=30で適当にデータを入力して動かしてみると、

異常無しですね。完成!!


終わりに

ここらへんはC言語を習って序盤に必ず通る課題だと思うので誰かの役に立てば幸いです。
今回始めてプログラミングの記事を書きましたが、こんな感じで大学生の課題に出てきそうなアルゴリズムなどを定期的に取り上げるのでぜひこれからもこのブログをチェックしていただけると嬉しいです!

ではまた次の記事で会いましょう!

コメント

タイトルとURLをコピーしました