第二回C言語講習

最終更新:2014/6/3

今回の内容は概念を理解するというよりは使い方を覚えるというのが主眼になっています。

ですので演習課題以外にも自分でたくさんプログラムを書いて使えるようにしてください。

指定されていない他のAOJの問題を解くのも有効だと思います。

条件分岐

プログラムは常に一本道で動くとは限りません。

例えば数の入力を受け取って100より大きかったらA、小さかったらBというようにしたい場合、

入力された値から判断して処理を分岐させなくてはなりません。

if文、if~else文

そこでif文というものを使います。具体的には以下のようにします。

if(条件式) 条件式が真だった時に実行する文;

なおこれでは1つの文しか実行できません。

しかし{ }で囲むことで複数の文をif文の分岐で実行することが出来ます。

if(条件式){
    条件式が真だったらする処理
}

同様に条件式が成り立たなかった時の処理もelseを使って表現できます。

if(条件式){
    条件式が真だったらする処理
}else{
    条件式が偽だったらする処理
}

これを組み合わせてもっと複雑な条件分岐を作ることができます。

if(条件A){
    Aだった場合の処理
}else if(条件B){
    Bだった場合の処理
}else if(条件C){
    if(条件D){
        CかつDだった場合の処理
    }else if(条件E){
        CかつEだった場合の処理
    }
}else{
    A~Cのどれでもなかった場合の処理
}

では条件式について学んでいきましょう。

真と偽

まず最初にC言語における真と偽というものを知らなくてはなりません。

簡単な定義ですがとてもとても重要です。

C言語において

真(true)とは0以外の値

であり

偽(false)とは0

です。 

比較演算子

数学の等式、不等式に使われる記号と同じものがあります。

演算子数学における記号使用例
==a == b
!=a != b
<a < b
<=a <= b
>a > b
>=a >= b

注意して欲しいのは数学のように 0<x<100 のような書き方が出来ない点です。

そういった式は次の論理演算子を用いて表現します。

論理演算子

こちらも数学で使うものと同様のものが用意されています。

演算子数学における記号使用例備考
&&∧ (AND) 0<x&&x<100
||∨ (OR) a!=0||b!=0
!¬ (NOT) !(a==0&&b==0) 真偽の値を反転させます。

制御構文

100回"Hello World"と表示するプログラムを作成せよ、と言われてprintfを100回各必要はありません。そういった時のために繰り返しを行える構文があります。

while文

英語のwhileの意味のとおり「~の間」だけ処理を繰り返します。具体的には、

while(条件式A){
    条件式が真の間繰り返す処理B
}

こういった繰り返し処理のことをループと読んだりします。

処理の流れとしては

  1. 条件式Aの値を調べる(偽ならBをやらずに4へ)
    1. Bの処理
    2. Bの処理が終ったら1に戻る
  2. 次の処理(これはループの外です)

注意点としては条件式Aが常に真のままだといつまでたってもループから抜け出せない(無限ループ)に陥ることがあります。

do-while文

while文と似たようなものでdo-while文というものがあります。

while文が条件式の値が偽の場合、一度もループ内の処理が行われないのに対してdo-while文は最低でも一度はループ内の処理が行われます。

具体的には以下のように書きます。

do{
    ループで行う処理B
}while(条件式A)

最初に処理Bを行った後に条件式Aの真偽を調べて真なら再度Bを繰り返します。

for文

主に決まった回数繰り返したいときに使われます。

for(開始処理A;繰り返し条件B;継続処理C){
    繰り返したい処理D
}

具体的な処理の順番は

  1. 開始処理A
  2. 繰り返し条件Bの値を調べる(真なら3,偽なら5へ)
    1. 繰り返したい処理D
    2. 継続処理C
  3. 次の処理(これはループの外です)

例えば以下のコードは

int i;
for(i=0;i<10;i++){
    printf("%d\n",i);
}

このような出力をします。

0
1
2
: //省略
7
8
9

注意して欲しいのは変数i0から9までを移動している点です。

break文

何かエラーが起きた等でループ処理の途中でループから抜け出したい時break文が便利です。

break文は実行されると今いる一番小さいループから抜け出します。具体的には

while(条件式1){
    処理  
     :
    if(条件式2){//例えばエラーが起きたかどうか調べる条件式
        break;
    }
     :
    処理
}
ループの外

この場合条件式2が真になるとbreak文が実行されif文よりも後ろの処理を飛ばしてループの外の処理に移行します。

continue文

break文と似ていますがbreak文がループを抜けて次の処理に移るのに対してcontinue文はループの最初に戻ります

またfor文の中でcontinueを使うと継続処理を行った後ループの最初に戻ります。

switch文

2つか3つに分岐するプログラムならif-else文でも書けますが5つや6つ、もしくはそれ以上に分岐する場合if-else文で書こうとすると大変なことになります。

switch文を使うとそういった分岐を簡潔に記述することが出来ます。

switch(値X){
    case A:X==Aなら行う処理;break;
    case B:X==Bなら行う処理;break;
    case C:X==Cなら行う処理;break;
    case D:X==Dなら行う処理;break;
            :
    default:どれでもなかったら行う処理;
}

なおX,A,B,C,D・・・は全て整数の値しか取れません。

最後のbreakを書かないとそれより下のcase全て実行されてしまいます。

変数のスコープ

今まで変数はmain関数の最初でしか宣言してきませんでしたがforやwhileのループの 中でも宣言することが出来ます。

while(hoge){
  int a,b,c;
  a=10;
  b=20;
  c=a+b;
}

ただこのループの中で宣言された変数はこのループの中でしか使えません

こういった変数の有効範囲のことをスコープと言います。

またスコープの中と外で同じ名前の変数が混在している場合、

よりスコープの狭いほうの変数が優先されます。

例えば以下のコードを実行してみると

//scopetest.c   
#include<stdio.h>

int main(){
  int a=10;
  int i;
  for(i=0;i<1;i++){
    int a=20;
    printf("forの中のa%d\n",a);
  }
  printf("forの外のa%d\n",a);
}

以下のようになります。

[hoge@sol ]$ gcc scopetest.c -o scopetest
[hoge@sol ]$ ./scopetest
forの中のa20
forの外のa10

forの中ではforの中で宣言されたaが優先されていることがわかるかと思います。

グローバル変数

main関数のに変数を宣言した場合その変数はプログラム中のどこからでも呼び出すことができます。

#include<stdio.h>

int global;

int main(){
  global=100;

}

一見便利なようですがプログラムのどこからでも変更できるというのは大きなプログラムを作成する際に安全でないことのほうが多いのでなるべく使わないようにしましょう。

演習課題

演習 1: 数値の入力を一つ受け取ってそれが100以上ならば”high”,100未満ならば"low"と出力するプログラムを作成せよ

演習 2: AOJ10003 Small, Large, or Equal

演習 3: AOJ10004 Sorting Three Numbersメンドイ

演習 4: AOJ10005 Print Many Hello World

演習 5: AOJ10006 Print Test Cases

演習 6: AOJ10007 Swapping Two Numbers

演習 7: AOJ 0000 QQ

演習 8: AOJ10010 Simple Calculator発展的な内容

引用、参考文献


各回へのリンク


クリエイティブ・コモンズ・ライセンス
この 作品 は クリエイティブ・コモンズ 表示 - 非営利 - 改変禁止 2.1 日本 ライセンスの下に提供されています。免責事項