C言語[備忘録2]

#配列
配列定義の仕方
要素型、  変数名、    要素数
 　int 、 　 a 、　 　  [5]  

この中身が, a[0],a[1],a[2],a[3],a[4]の５つの要素になる。

配列を利用したプログラム

```
#include<stdio.h>
int main(void){

  int i;
  int v[5];

  for (i = 0; i < 5; i++)
    v[i] = i + 1;

  for (i = 0; i < 5; i++)
    printf("v[%d] = %d\n", i , v[i]);
  
  return 0;
  
}
```
実行結果
v[0] = 1
v[1] = 2
v[2] = 3
v[3] = 4
v[4] = 5

一つづつ走査すると
```for (i = 0; i < 5; i++)
v[i] = i + 1;
```
ここでは、v[0]という要素の中に0+1の答えを代入している。これをi++インクリメントしていき5回繰り返す。

```  for (i = 0; i < 5; i++)
    printf("v[%d] = %d\n", i , v[i]);
```
printf v[%d]はiの0が入り,%dは先ほど一つづつv[0]要素の中に代入した値が表示される。これもまたi++でインクリメントされ5回繰り返す。

###配列のコピー

```
#include<stdio.h>
int main(void){

int i;
int a[5] = {17,23,36};
int b[5];

for (i = 0; i < 5; i++)
  b[i] = a[i];

  puts("  a    b ");
  puts("---------");
  for (i = 0; i < 5; i++)
    printf("%4d%4d\n",a[i],b[i]);
  
  return 0;

}
```
実行結果
  a    b 
'---------'
  17  17
  23  23
  36  36
   0   0
   0   0

一つづつ走査していきます。
```int a[5] = {17,23,36};
int b[5];```
aの配列は5個要素が宣言されているが、三個の整数しか与えられていない。それでもコンパイラエラーは起こさない。中身を確認するとa[17,23,36,0,0]としっかり5個の要素は入っている。同様にb[5]もb[0,0,0,0,0]が入っている。

```for (i = 0; i < 5; i++)
  b[i] = a[i];```
ここで配列のコピーを行っている。
a[i]の要素の値をb[i]の要素に5つ分、値をコピーしている。
ちなみに配列の変数だけのコピーはコンパイラエラーになる。```b = a```エラー

```  puts("  a    b ");
  puts("---------");
  for (i = 0; i < 5; i++)
    printf("%4d%4d\n",a[i],b[i]);```
最後のprintf("%4d%4d\n",a [ i ],b [ i ] ) ;のa[ i ]とb[ i ]はコピーされているので同じ値が出力される。
初めて出た、%4dの4はスペースです。左から半角スペース4個分。

###多次元配列
配列の要素自体が"配列"である配列も作れる。
int a [ 4 ] [ 3 ]
こんな感じです。最初の4は行数、後の3は列数
a[ 0 ]の中身は0,1,2の3個の要素が入っている。
a [ 0 ][ 0 ], a [ 0 ][ 1 ], a [ 0 ][ 2 ]
a [ 1 ][ 0 ], a [ 1 ][ 1 ], a [ 1 ][ 2 ]
a [ 2 ][ 0 ], a [ 2 ][ 1 ], a [ 2 ][ 2 ]
a [ 3 ][ 0 ], a [ 3 ][ 1 ], a [ 3 ][ 2 ]
これで大体わかったと思います。それなので二次元配列を利用したプログラムを記述します。

```
#include<stdio.h>
int main(void){

  int i,j;
  int tensu1[4][3] = {{91,63,78},{67,72,46},{89,34,53},{32,54,34}};
  int tensu2[4][3] = {{97,67,82},{73,43,46},{97,56,21},{85,46,35}};
  int sum[4][3];

  for (i = 0; i < 4; i++){
    for (j = 0; j < 3; j++)
      sum[i][j] = tensu1[i][j] + tensu2[i][j];
      }
      puts("1回目の点数");
      for (i = 0; i < 4; i++){
        for(j = 0; j < 3; j++)
          printf("%4d",tensu1[i][j]);
        putchar('\n');
      }
      puts("2回目の点数");
      for (i = 0; i < 4; i++){
        for(j = 0; j < 3; j++)
          printf("%4d",tensu2[i][j]);
        putchar('\n');
      }
      puts("合計点");
      for (i = 0; i < 4; i++){
        for(j = 0; j < 3; j++)
          printf("%4d",sum[i][j]);
        putchar('\n');
      }

  return 0;
}
```
実行結果
1回目の点数
  91  63  78
  67  72  46
  89  34  53
  32  54  34
2回目の点数
  97  67  82
  73  43  46
  97  56  21
  85  46  35
合計点
 188 130 160
 140 115  92
 186  90  74
 117 100  69

一つづつ走査していきます。
```for (i = 0; i < 4; i++){
    for (j = 0; j < 3; j++)
      sum[i][j] = tensu1[i][j] + tensu2[i][j];
      }```
この処理はtensu1と2の合計を処理している部分です。
まずfor文で配列の中身を一つづつ取り出しています。例としてtensu[0][0]は91が値になる。tensu2[2][0]は97の値が取り出せる。
その値の合計値をsumの配列に代入している。
sum[0][0]= tensu1[0][0] + tensu2[0][0]　　中身↓
sum 0 = 91 + 97 
sum[0][1]= tensu1[0][1] + tensu2[0][1]　　中身↓
sum 0 = 63 + 67
sum[0][2]= tensu1[0][2] + tensu2[0][2]　　中身↓
sum 0 = 78 + 82
次に値を表示させる。
```puts("1回目の点数");
      for (i = 0; i < 4; i++){
        for(j = 0; j < 3; j++)
          printf("%4d",tensu1[i][j]);
        putchar('\n');
      }
      puts("2回目の点数");
      for (i = 0; i < 4; i++){
        for(j = 0; j < 3; j++)
          printf("%4d",tensu2[i][j]);
        putchar('\n');
      }
            puts("合計点");
      for (i = 0; i < 4; i++){
        for(j = 0; j < 3; j++)
          printf("%4d",sum[i][j]);
        putchar('\n');
      }```
tensu1と2とsumの配列の中身の値を表示させている。配列の添字を一つずつ繰り返し表示する。

###有効範囲とファイル有効範囲
ある関数で使われている変数はその関数特有の変数です。その名前が通用する範囲を```「有効範囲」```という。ソースコードに複数の関数があり、各関数の変数の名前が同じである場合でもその関数間(ブロック)でしか変数は通用しない```「ブロック有効範囲。」```


配列のように関数の外で宣言された変数の識別子は宣言された場所からそのソースプログラムの終端まで通用する。それを```「ファイル有効範囲」```

```
#include<stdio.h>
#define NUMBER 5
int tensu[NUMBER];　/*配列の実体を作るための宣言*/
int top(void); /*関数原型宣言*/

int main(void){
  extern int tensu[]; /*配列の宣言*/
  int i;

  printf("%d人の点数を入力してください。\n", NUMBER);
  for (i = 0; i < NUMBER; i++){
    printf("%d : ",i + 1);
    scanf("%d", &tensu[i]);
  }
  printf("最高点=%d\n", top());

  return 0;
}

int top(void){
  extern int tensu[]; /*配列の宣言*/
  int i;
  int max = tensu[0];

  for(i = 1; i < NUMBER; i++)
    if (tensu[i] > max)
      max = tensu[i];
  return max;
}
```
一つづつ走査していきます。
```int tensu[NUMBER];　/*配列の実体を作るための宣言*/```
配列tensuを作り出す宣言。定義でもある。
```int top(void); /*関数原型宣言*/```
コンパイラは基本先頭から末尾へと読み進めていきます。
本プログラムでは関数topはmain関数より後ろ側に配置されています。なので関数topは引数を受け取らず```関数topで出力される値を返す関数```とコンパイラは知る必要があります。このことを「関数原型宣言」という。だが、一般的に呼び出される側の関数を前に配置すればこのような宣言はしなくて済む。
```extern int tensu[]; /*配列の宣言*/```
externとはどこかで作られたtensuを使う。と宣言されている。なので関数外で定義された配列を使いますよという意味。

``` printf("%d人の点数を入力してください。\n", NUMBER);
  for (i = 0; i < NUMBER; i++){
    printf("%d : ",i + 1);
    scanf("%d", &tensu[i]);
  }
  printf("最高点=%d\n", top());```
配列tensuのなかに整数を5つ入力していく。
最高点を出す関数topの呼び出し。
```extern int tensu[]; /*配列の宣言*/
int max = tensu[0];
  for(i = 1; i < NUMBER; i++)
    if (tensu[i] > max)
      max = tensu[i];
  return max;
}```
値が入っている配列tensuを呼び出し、max = tensu[0]配列の一番前にある値を変数maxに代入する。
そこからfor文とif文でtensu[1]〜[4]まで評価していく。もしmaxより大きい数字ならmaxに代入され、そのまま評価されていき繰り返しがおわったらmaxとして戻り値main関数にいく。