配列・文字列

本日の内容

    8-1. 復習
    8-2. データ構造(1)---配列
    8-3. 文字列
    8-4. if や while で使う演算子

8-1. 復習

とりあえず C のプログラムを作った

C 言語の文法

変数を使うには、宣言が必要

小数点のない数を使う
int x;
小数点のある数を使う
float x;

数式の計算は手順通りに素直に書き下せば良い。

例題

二元一次連立方程式を解くプログラムを作った

a x + b y = e
c x + d y = f
  1. a d - b c が 0 でなければ、
    x = (d e - b f)/(a d - b c)
    y = (a f - c e)/(a d - b c)
    

    これだけでプログラムを書くと次のようになる。

    #include <stdio.h>
    main(){
      float a,b,c,d,e,f,x,y,det;
      a=1.0; b=2.0; c=3.0; d=4.0; e=5.0; f=6.0;
      det=a*d-b*c;
      /* det が 0 でないとき */
      x=(d*e-b*f)/det;
      y=(a*f-c*e)/det;
      printf("x=%f, y=%f\n",x,y);
    }
    

    crossing lines

  2. そうでないとき
    1. 解がない場合
        x + y = 1
        x + y = 2
      
      つまり a=1, b=1, c=1, d=1, e=1, f=2 の時
      parallel lines
    2. 解が無限にある場合
        x +   y = 1
      2 x + 2 y = 2
      
      つまり a=1, b=1, c=2, d=2, e=1, f=2 の時
      duplicating lines

8-2. データ構造(1)---配列

大抵のプログラミング言語に存在する配列と呼ばれるデータ形式を学ぶ。 これは、数学で習った数列と同様の記法である。

C 言語では、大カッコを使用し、

a[1], a[2], a[3],...
などと書く。

宣言の仕方

int a[10];

と宣言すると整数型の配列変数 a[0],a[1],a[2], ..., a[9] が使用できる。 [ ] の中に入れられる数字を「添字(そえじ)」と言う

使用法

  1. 通常の変数と同様
    b=a[1]+a[3]+c;
    
  2. 添字に式を書いても良い。整数型の変数や計算式を添字に使用できる。
    i=1;
    a[i]=3;
    a[i+1]=4;
    
  3. 変数宣言時にまとめて代入ができる。
    int a[10]={4,5,3,1,7,8,9,2,0,6};
    

配列を使うと、大量のデータを扱うことができる。

例題: 数の和を求める。

値が a[0], ..., a[9] まで、次のように与えられた時、和を求める。

int a[10]={4,5,3,1,7,8,9,2,0,6};
  1. 素朴な解決法
    #include <stdio.h>
    int a[10]={4,5,3,1,7,8,9,2,0,6};
    main()
    {
      int sum;
    
      sum=a[0]+a[1]+a[2]+a[3]+a[4]+a[5]+a[6]+a[7]+a[8]+a[9];
      printf("Sum=%d\n",sum);
    }
    

    問題点: データ数が 1000 個などになると、この方法ではお手あげ

  2. 漸化式を使用する。

    (コンピュータプログラムではよく使われる手法)

    「-1 番目までの和」 =  0
    「 i 番目までの和」 = 「i-1 番目までの和」 + a[i]
    
  3. 工夫のない解決法
    #include <stdio.h>
    int a[10]={4,5,3,1,7,8,9,2,0,6};
    main()
    {
      int sum;
    
      sum=0;
      sum=sum+a[0];
      sum=sum+a[1];
      sum=sum+a[2];
      sum=sum+a[3];
      sum=sum+a[4];
      sum=sum+a[5];
      sum=sum+a[6];
      sum=sum+a[7];
      sum=sum+a[8];
      sum=sum+a[9];
      printf("Sum=%d\n",sum);
    }
    
  4. 添字に変数を使う。
    #include <stdio.h>
    int a[10]={4,5,3,1,7,8,9,2,0,6};
    
    main()
    {
      int i,sum;
    
      sum=0;i=0;
      sum=sum+a[i];i=i+1;
      sum=sum+a[i];i=i+1;
      sum=sum+a[i];i=i+1;
      sum=sum+a[i];i=i+1;
      sum=sum+a[i];i=i+1;
      sum=sum+a[i];i=i+1;
      sum=sum+a[i];i=i+1;
      sum=sum+a[i];i=i+1;
      sum=sum+a[i];i=i+1;
      sum=sum+a[i];i=i+1;
      sum=sum+a[i];i=i+1;
      printf("Sum=%d\n",sum);
    }
    
  5. 繰り返しの利用

    while 文を使用して、 i が 10 未満なら続けるようにする。

    プログラム 1
    #include <stdio.h>
    int a[10]={4,5,3,1,7,8,9,2,0,6};
    
    main()
    {
      int i,sum;
    
      sum=0;i=0;
      while(i<10)
      {
        sum=sum+a[i];i=i+1;
      }
      printf("Sum=%d\n",sum);
    }
    

    これなら 10 を 1000 に替えても、プログラムの大きな変更は必要ない。

演習8-1

次のように定義されている配列 a の平均値を求めるプログラムを書きなさい。

int a[10]={4,5,3,1,7,8,9,2,0,6};

for 文

プログラミングにおいて、この書き方は定石なので、一括して書く構文がある。

前処理
while(条件式)
{
  文;
  後処理;
}

は次のように書き換えられる。

for(前処理;条件式;後処理)文

例題

プログラム 1 の while を、 for を使用して書き替える。

#include <stdio.h>
int a[10]={4,5,3,1,7,8,9,2,0,6};

main()
{
  int i,sum;

  sum=0;
  for(i=0;i<10;i=i+1)
  {
    sum=sum+a[i];
  }
  printf("Sum=%d\n",sum);
}

演習8-2

for 文を使用して、平均を求めるプログラムを書け

演習8-3

1 から 100 までの数を画面に表示するプログラムを書け

演習8-4

標準偏差を求めるプログラムを書け

標準偏差=√分散
分散=(Σ(値 - 平均)の二乗)/全体の数
(正の平方根は sqrt() により計算できる)

演習8-5

点数が配列に入っている時、偏差値を印刷するプログラムを書け
偏差値 = (値-平均)*10/標準偏差 + 50
配列を扱う時、配列のサイズはプログラムのいたるところで必要となる。 参照ミスを防ぐために、また、後々配列のサイズを変更する必要が出てくる場合に対応しやすいように、配列のサイズを定数として定義してしまうというテクニックがある。
#include <stdio.h>
#define ASIZE 10
main(){
  int a[ASIZE]={4,5,3,1,7,8,9,2,0,6};
  int i,sum;

  sum=0;
  for(i=0;i<ASIZE;i=i+1)
  {
    sum=sum+a[i];
  }
  printf("Sum=%d\n",sum);
}

回答例

演習8-2

和をとるところまでは例題と同じ。 但し、あらかじめ

  float average;

を宣言しておく。 あと、割り算の結果が int ではなく float になるようにするため、一工夫必要。

  average=(float) sum/ANUM;
  printf("Average=%f",average);
}

演習8-3

#include <stdio.h>
main()
{
  for(i=1;i<=100;i=i+1)
  {
    printf("%d\n",i);
  }
}

演習8-4

平均点をとるところまでは演習8-2と同じ。
但し
  int sum2;
  float bunsan,hyouzyunhensa;
をあらかじめ宣言しておく。

  sum2=0;
  for(i=0;i<ANUM;i=i+1)
  {
    sum2=sum2+(a[i]-average)*(a[i]-average);
  }
  bunsan=(float)sum2/ANUM;
  hyouzyunhensa=sqrt(bunsan);
  printf("Hyouzyunhensa = %f\n",hyouzyunhensa);
}

演習8-5

標準偏差をとるところまで、演習8-4と同じ。 但し、

  int hensachi;
をあらかじめ定義しておく

  for(i=0;i<ANUM;i=i+1)
  {
    hensachi=(a[i]-average)*10/hyouzyunhensa+50;
    printf("soten %d, hensachi %d\n",a[i],hensachi);
  }

8-3. 文字列

C 言語には文字列型という型の変数はない。 しかし、文字列は文字型の配列で定義される。

文字列を使用する際の約束:
配列の最後に\0 という文字を入れる

文字列の変数の使い方

宣言

char a[10]
a[9] に \0 を入れなければならないので、文字列の長さは 9 文字
char a[10]="abcdefghi";

char a[10]={'a','b','c','d','e','f','g','h','i','\0'};

と同じで
a[0]='a'; a[1]='b'; a[2]='c'; a[3]='d'; a[4]='e'; a[5]='f'; a[6]='g'; a[7]='h'; a[8]='i'; a[9]='\0';
と同じ意味である。

さらに、文字列があらかじめ与えられる時は文字数を指定しなくても良い

char a[]="abcdefghi";

文字列に関する問題

char a[]="    This   is a   sample sentence.";

が定義されているとする。

例題: 文字列に含まれる空白の数を数える。

  1. num=0;
  2. 文字列が終るまで文字列の空白を調べ、変数 num に空白の数を入れる。
  3. num を出力する。
空白の数の数え方
漸化式的考え方:
array a

while を使うと

  1. while (i 番目の文字で文字列終了してないとき)
  2. i 番目の文字が空白だったら num を一つ増やす
  3. i を一つ増やす
#include <stdio.h>
main(){
  int i,num;
  char a[]="    This   is a   sample sentence.";
  printf("%s\n",a);/*文字列の印刷のしかた*/
  i=0;
  num=0;
  while(a[i]!='\0'){
    if(a[i]==' '){num=num+1;}
    i=i+1;
  }
  printf("This string contains %d spaces.\n",num);
}

演習8-6

文字列の先頭に空白がいくつあるかを数えるプログラムを書け

演習8-7

文字列に単語がいくつあるかを数えるプログラムを書け


8-4. if や while で使う演算子

比較演算子

==等しい
!=異なる
<小さい
>大きい
<=以下
>=以上

プログラムの動作がおかしいと思ったら、まず、 if や while の中の ===と書き間違えてないかチェックする

論理演算子

!否定
&&かつ
||または

!(x==0)
x が 0 でないとき。x!=0
(x==0)&&(y==1)
x が 0 で、かつ、 y が 1 のとき。
(x==0)||(x==1)
x が 0 または 1 のとき。

坂本直志 sakamoto@c.dendai.ac.jp