情報科学概論
2003.6.10

Back to index page



  1. 本日の作業内容

  2. 制御構造 (条件分岐2)

    • if 文の続き

      英語で文章を書く場合,ifを使う例文で二つの用法を習ったと思います.

      If it rains tomorrow, the excursion will be postponed.
      
      The excursion will be postponed, if it rains tomorrow.
      

      Rubyでもこのような2種類の書き方ができます.

      a = ARGV[0].to_f
      
      a = -a if a < 0
      printf "The absolute value of a, |a|, is %f.\n", a
      

      このように if を後ろに置く場合ですと,end による指定が 不要になり,短くすっきり書ける場合があります.else の処理 が無い場合だと記述が簡単になります.

      また,複数行に分けて記述していた if 文ですが,1行で書くことも可 能です.次に例を示しますが,その場合には構文をはっきりさせるために,これ まで省略可能としていた then が必ず必要になります.

      a = ARGV[0].to_f
      
      if a < 0 then a = -a end
      printf "The absolute value of a, |a|, is %f.\n", a
      

      1行で書く場合でも else を入れることができます.ただし,1行が長 くなる場合には見づらいスクリプトになるので注意が必要です.

      a = ARGV[0].to_i
      
      if a % 2 == 0 then str = "even" else str = "odd" end
      printf "The number %d is %s.\n", a, str
      

    • unless

      if と意味が逆になるのが unless 文です.これも英語の意 味そのままですので,「もし〜でなければ」となります.すなわち,if 文では条件が「真」のときに処理が実行されましたが,unless では,条件が「偽」のときに処理が行われます.先ほどの例を unless に変えてみましょう.

      a = ARGV[0].to_f
      
      a = -a unless a >= 0
      printf "The absolute value of a, |a|, is %f.\n", a
      

      正規の構文で表現することもできます.

      a = ARGV[0].to_f
      
      unless a >= 0
        a = -a
      end
      
      printf "The absolute value of a, |a|, is %f.\n", a
      

      unless 文においても else は使えますが,elsif に相当するものはありません.注意してください.

    • case

      いくつかの選択肢について場合分けする場合に,elsif を用いること が可能であることは先週紹介しました.条件式によってはここで紹介する case 文を使用する方が簡単になる場合もあります.次の例は,引数として 与えた月が何日あるかを返すスクリプトです.

      m = ARGV[0].to_i
      
      case m
      when 2
        d = "28 or 29"
      when 4,6,9,11
        d = "30"
      else
        d = "31"
      end
      
      printf "The month %d has %s days.\n", m, d
      

      when による条件指定はいくつでも置くことが可能です.また,上記の 例のように,一つの when のところに複数の条件を置くことも可能で す.次のようなことも可能です.

      a = ARGV[0].to_f
      
      case a
      when 0..1
        d = "in"
      else
        d = "out of"
      end
      
      printf "The number is %s the range 0 ≦ x ≦ 1.\n", d
      

      この例では引数として与えた数値が0と1の範囲内にあるかを判定しています.す なわち,0 ≦ x ≦ 1 を判定しています.注意するのは,範囲指定でも 両側が決まっていないもの,例えば,正か負かを判定するような場合にはちょっ とした工夫が必要なことです.数値が正であるか,負であるか,それとも0であ るかを判定するには,次のようにします.

      a = ARGV[0].to_f
      
      case a
      when 0
        d = "zero"
      when 0..(1.0/0)
        d = "positive"
      else
        d = "negative"
      end
      
      printf "The number is %s.\n", d
      

      また,「以上」や「以下」の判定は実現できますが,「大なり」「小なり」は工 夫が必要です.上の例では先に0であるかを判定させておいて,その後で正の判 定に移るようにしています.

  3. 実習作業

    この時間に学習したスクリプトを自分で変更を加えたりしながら応用してみて下 さい.以下には,応用例のいくつかを示しておきます.適宜参考にしてください. スクリプトのダウンロードも可能ですので,リンクを右クリックして利用してく ださい.

    教室のパソコン利用者の学生番号推定スクリプト

    引数をつけずに実行すると,作業者の学生番号を推定します.

    dir = `pwd`
    
    if /\/home\/b/ =~ dir
      str1 = dir[14,3].gsub(/b/,"s")
      str2 = dir[17,2]
      if str1 =~ "s9"
        add = "6"
      elsif str1 =~ "s0"
        add = "40"
      end
      printf "Your student number is %s%s%s.\n", str1, add, str2
    else
      printf "You are not student.\n"
    end
    

    解説

    • 引用符," ` " (バッククオート) でくくった文字列はシェルのコマンドとして利用可 能.コマンドの結果が変数に代入される.

    • / / ではさまれたものは「正規表現」という文字列の規則を示す. 上記の例は,変数の値に /home/b という文字列が含まれている かを判定.文字列の正規表現の比較には演算子として =~ が利用 される.

    • dir[14,3] とは変数 dir の値の文字列について「15番目 の文字から3文字分」と言う意味.序数は0から始まることに注意.図1参照

      図1 dir[14,3] の意味

    • gsub(/b/,"s") は正規表現 /b/ に該当する部分を文字 列 s で置き換える操作を,くっついている変数に対して行う. ここではログイン名の先頭のbを学生番号のsに置換.図2参照

      図2 gsub(/b/,"s") の意味

    学生番号から所属学部学科を推測する

    引数に学生番号を与えると,所属を推測して答えます.総合理工以外は間違って いるかも知れません.(学生番号生成の規則を良く知らないもので..)

    num = ARGV[0]
    
    case num[0,1]
      when "l", "L"
        faculty = "法文学部"
        case num[3,1]
          when "1"
            department = "法学科"
          when "2"
            department = "社会システム学科"
          when "3"
            department = "言語文化学科"
        end
      when "e", "E"
        faculty = "教育学部"
        case num[3,1]
          when "1"
            department = "学校教育教員養成課程"
          when "2"
            department = "生涯学習課程"
          when "3"
            department = "生活環境福祉課程"
        end
      when "s", "S"
        faculty = "総合理工学部"
        if num[1,1] == "9"
          case num[3,1]
            when "1","2"
              department = "物質科学科"
            when "3"
              department = "地球資源環境学科"
            when "4","5"
              department = "数理・情報システム学科"
            when "6"
              department = "電子制御システム工学科"
            when "8"
              department = "材料プロセス工学科"
          end
        else
          case num[3,1]
            when "1"
              department = "物質科学科"
            when "2"
              department = "地球資源環境学科"
            when "3"
              department = "数理・情報システム学科"
            when "4"
              department = "電子制御システム工学科"
            when "5"
              department = "材料プロセス工学科"
          end
        end
      when "a", "A"
        faculty = "生物資源科学部"
        case num[3,1]
          when "1"
            department = "生物科学科"
          when "2"
            department = "生態環境科学科"
          when "3"
            department = "生命工学科"
          when "4"
            dpartment = "農業生産学科"
          when "5"
            department = "地域開発科学科"
        end
    end
    
    printf "あなたの所属学部学科は,%s %s です.\n", faculty, department
    

    ロト6風数当て

    コマンドライン引数として6桁の数字を入力します.計算機が発生させた乱数と 比較して的中するかどうかをみます.当たっても賞金は出ません.

    #!/usr/bin/ruby
    
    num = rand(1000000)
    zero = "0"
    printf "当選番号は %s でした.\n", num
    
    case num
      when 0
        ans = zero*6
      when 1..9
        ans = zero*5 + num.to_s
      when 10..99
        ans = zero*4 + num.to_s
      when 100..999
        ans = zero*3 + num.to_s
      when 1000..9999
        ans = zero*2 + num.to_s
      when 10000..99999
        ans = zero + num.to_s
      else
        ans = num.to_s
    end
    
    your_number = ARGV[0]
    point = 0
    
    point += 1 if your_number[0,1] == ans[0,1]
    point += 1 if your_number[1,1] == ans[1,1]
    point += 1 if your_number[2,1] == ans[2,1]
    point += 1 if your_number[3,1] == ans[3,1]
    point += 1 if your_number[4,1] == ans[4,1]
    point += 1 if your_number[5,1] == ans[5,1]
    
    case point
      when 6
        printf "全問的中,賞金1億円です.\n"
      when 5
        printf "5問的中,賞金100万円です.\n"
      when 4
        printf "4問的中,賞金1万円です.\n"
      when 3
        printf "3問的中,でも賞金はありません.\n"
      when 2
        printf "2問的中,でも賞金はありません.\n"
      when 1
        printf "1問的中,でも賞金はありません.\n"
      else 
        printf "残念でした.\n"
    end
    

    解説

    1. 乱数の発生は rand により行う.括弧内の引数を最大値とし てそれより小さい数を乱数として発生させる.

    2. 発生した乱数を6桁の数にするために,先頭に必要な数だけ0を足す.

    3. 6桁の数のうち,何個一致したものがあるかを先頭の桁から順に調べ,当たっ た個数を数える.

    4. 当たった個数にしたがった結果の表示を行う.

  4. 小テスト

    授業の残り20分くらいでAクラスBクラス別々の小テストを行いますので,アナウンス に注意してください.

  5. 宿題

    授業の最後にAクラスBクラス別々の宿題の案内も出しますので,アナウンスに注意してください.


目次ページに戻る