プログラミング基礎覚え書き⑥(配列とデータの格納)

 ゴールデンウィーク第二部突入・・・!あと4日でC言語の課題をすべて終わらせないといけないんだけど、ひとつの単元を仕上げるのに何時間もかかるようになってきて、いよいよ厳しくなってきた。ふんじゃねーよ。
 まず、使う構文が増えた上に、効果がかぶっている奴が多くて、なのに課題では「この構文を使うこと」と指定してくるところ。ふんじゃねーよ。特にwhile文。ふんじゃねーよ。お前いらねえよ。for文で済むわ。
 次に、テキストは分かりやすくて、本当に“やさしい”のだが、本文に載っているソースコードがあまりにもやさしすぎて(かつ例が少ない)、テキストの例をいじくるだけじゃ課題のコードがいよいよ書けなくなってきたこと。

 ふんじゃねーよ!(´;ω;`)

参考文献:高橋麻奈著『やさしいC第5版』

配列(array)
アレイ。大量のデータを一括記憶する方法。学年全員のテストの点数など、同じようなデータを複数の箱に収めるようなイメージ。
変数と同様に、配列も名前をつけて宣言する。その際、使う箱の数(要素数)も宣言する。

int arrayA[5]; //5つの要素を使う「アレイA」という名前の配列。

このように配列を宣言すると、

arrayA[0]
arrayA[1]
arrayA[2]
arrayA[3]
arrayA[4]

と、指定した数だけ箱が用意される。※0からカウントされるのに注意。
箱の各ナンバーは添字(インデックス)と言う。
また指定した箱の数を超えるコード(箱が5個しかないのに50個目の箱のデータを開けようとするなど)を書いてしまうと、コンピュータが暴走する可能性がある。

配列の各要素を取り出して出力するコード
for文などの繰返し文を用いる。

int test[5]
int i;
test[0]
test[1]
test[2]
test[3]
test[4]

for(i=0;i<5;i++)
{
printf("%d番目の人の点数は%dです。\n",i+1,test[i]); //インデックスの数は要素数より1少ないのでi+1というように補正してあげる。
}

配列順を逆にするコード
for文の()の中の条件式を変える。

#include

int main(void)
{
int test[5];
int i;

test[0]=1;
test[1]=2;
test[2]=3;
test[3]=4;
test[4]=5;

for(i=4;i>=0;i=i-1) //test[4]の箱から初めて、1つずつ数を減らして行けという意味。
{
printf("test[%d]=%d \n",i+1,test[i]);
}

return 0;
}

コンパイルすると
test[5]=5
test[4]=4
test[3]=3
test[2]=2
test[1]=1

フィボナッチ数列を10番目まで順に表示する配列コード
花びらや葉っぱのつき方など、自然界によく見られるパターン。
フィボナッチ数列は0番目と1番目だけが規則違反をしておりどちらも1なので、それをまずはじめに指定してしまう。

#include

int main(void)
{
int i;
int fib[10]; //配列フィボの宣言

fib[0] = 1;
fib[1] = 1; //2つの例外を指定。


for(i = 2; i <= 9; i++) //それ以外の場合の求め方を指定。
{
fib[i] = fib[i-2] + fib[i-1]; //フィボナッチ数列は1つ前の数と2つ前の数の和。
}

for(i=0; i<10; i++) //0~9までの10個のインデックスを表示させる。
{
printf("fib[%d]=%d \n", i,fib[i]);
}

return 0;
}

コンパイルすると
fib[0]=1
fib[1]=1
fib[2]=2
fib[3]=3
fib[4]=5
fib[5]=8
fib[6]=13
fib[7]=21
fib[8]=34
fib[9]=55

整数を順番に入力し、負の数が入力されたら、それまでに入力された正の整数を、 入力された順番とは逆に全角空白で区切って出力するコード
すごいイジワルな問題だと思う。こんなコード使うことあるのかっていう。
ちなみにwhile(1)という文は、いわゆる無限ループの構文で、{}の中に脱出口(break)を作ってやる必要がある。

#include

int main(void){

int i,num,count=0;
int test[10];

while(1) //入力された値が0より下じゃない限り、整数を入力させ続けろという意味。
{
printf("整数:");
scanf("%d", &num);
if(num<0)break;

test[count]=num;
count++;
}

for(i=count-1; i>=0; i--)
//初項は最大カウントから(ただしカウントを止めた最後の負数は合計しないので-1で調整)

{
printf("%d ",test[i]); //全角スペースに注意!
}

printf("\n");

return 0;
}

入力された得点を入力順に配列に保存し、その入力順を学生番号と考えて、学生番号に対応する得点を表示するコード
いよいよ複雑なコードが出てきた。すごい難しかった。
この授業ってクリアするとほかの学生のコードも見れるんだけど、解答例もいろいろあって何が正しいのかがわからない。
自分のコードも絶対おかしい気がするけど、なぜかクリアになった。
とりあえず、テキストの187ページをパクって、入力された値を配列に格納する変数iと、格納された値を出力する変数oを、別にしてコードを書いてみた。
ただ、おそらく先生が望んでいるのは、マイナスの点数が入力されるというエラーが起きるまで、半永久的に学籍番号を増やし続けるようなコードだと思う。
ただ、そうなると配列の宣言時に箱の数が確定せず、[ ]の中も小難しい式になりそうなので、なんとなく5個でごまかした。

#include

int main(void) {

int score[5];
int i; //配列に入力するための変数
int o; //配列から出力するための変数

printf("得点を入力してください。\n");

for(i=0;i<5;i++) //入力回数条件。
{
scanf("%d",&score[i]);

if(score[i]<0){break;} //0点未満の点数が入るとエラーということで強制終了。

}

for(o=0; o<5; o++) //出力回数条件。
{printf("学籍番号:%d \n %d点です。\n",o+1,score[o]);
}

return 0;
}

先生の模範解答
やはり難しかったのかVTRで正解のコードを見せていた(基本的には講義でそういうコーナーはない)。オレの2時間を返せ(´;ω;`)

#include

int main(void) {

int i,num,count=0;
int test[100]; //とりあえず上限を100にしていた。

while(1)
{

printf("得点を入力してください。\n");

scanf("%d", &num);
if(num==-1)break; //0点未満の点数が入るとエラーということで強制終了。

test[count]=num;
count++;

}

printf("\n");

while(1)
{

printf("学籍番号:");
scanf("%d", &num);
if (num<=0 || num >count)break;
//学籍番号が0以下だったり、学生数(カウント)よりも多いとエラーで強制終了。

printf("%d点です。\n",test[num-1]);

}

return 0;
}

配列に格納された10個の整数の最小値、最大値を求めて表示するコード
配列に入っている10個の数はあらかじめ設定されている。
その10個の配列をひとつずつ比べていくようにfor文の条件を作る。

#include

int main(void) {

int i;
int max=-1000000; //最大値として使える最小の数を宣言。
int min=1000000; //最小値として使える最大の数を宣言。

int array[10] = { -4,15,0,82,7,-5,12,2,72,-81 };

for(i=0; i<10; i++) //配列のある10個の数をひとつずつ検証するという意味。
{
if(max < array[i])
max = array[i];

if(min > array[i])
min = array[i];
}

printf("最大値は%dで、最小値は%dです。\n",max,min);

return 0;
}

第1種定形外通常郵便物の重さを入力すると料金が出力されるコード
重さと料金の配列をそれぞれ作り、連動させる。

50gまで   120円
100gまで  140円
150gまで  200円
250gまで  240円
500gまで  390円
1000gまで  580円
2000gまで  850円
4000gまで  1150円

#include

int main(void) {

int i,w;
int weight[8]={50,100,150,250,500,1000,2000,4000};
int fee[8]={120,140,200,240,390,580,850,1150};

printf("郵便物の重さ(g):");
scanf("%d", &w);

for(i=0; i<8; i++)
{

if(w<=weight[i]) //配列にある重さ以下の数字なら料金を教えてあげるという意味。
{
printf("料金は%dです。\n",fee[i]);
break;
}

}

return 0;
}

テストの点数の度数分布表
マイナスの点数が入力されるというエラーがない限り、エンドレスに集計するという仕様。
複雑なネストになっておりすごい難しい。先生の模範解答を見ても無理。
それぞれの点数を10段階の階級にふるい分け、さらにその階級の度数をカウントしなければならない。

度数分布
  0~ 10: 2
 11~ 20: 0
 21~ 30: 1
 31~ 40: 0
 41~ 50: 0
 51~ 60: 2
 61~ 70: 0
 71~ 80: 3
 81~ 90: 1
 91~100: 1

#include
int main(void) {

int i; //度数
int num; //点数
int test[10] = {0}; //10個の配列を初期化。

while(1) {

printf("点数(0-100):\n"); //無限ループを作りユーザーはエンドレスに点数入力。
scanf("%d", &num);

if(num < 0) break; //ただマイナスの点数を入力した場合はループ脱出。

for(i=0; i<10; i++)
{if(num <= 10*(i+1)){test[i]++; break;} }

//入力された点数を階級ごとにふるい分け、さらに度数をカウントする肝の部分。
例えば、0~10点は階級i=0にふるい分けなければならないため、10*(i+1)のiに0を代入した値=10と点数numを比較して、それ以下なら階級0としてカウントされるようになっている。
逆に、10を超えた点数ならば、iに今度は1を代入した値=20と点数numを比較、それでもまだ大きい場合はiにさらに2を代入して・・・と比較する階級をどんどん上げてやるという仕組みになっている。こんなん書けるか。

}

printf(" 0~ 10:%d\n",test[0]);
for(i=1; i<10; i++)
{printf("%3d~%3d: %d \n",10*i+1, 10*i+10, test[i] );}

return 0;
Calendar
<< April 2024 >>
SunMonTueWedThuFriSat
 123456
78910111213
14151617181920
21222324252627
282930
search this site.
tags
archives
recent comment
recent trackback
others
にほんブログ村 科学ブログへ にほんブログ村 科学ブログ 恐竜へ カウンター
admin
  • 管理者ページ
  • 記事を書く
  • ログアウト