沖の雑記帳

基本的には趣味に絡んで雑多な内容を色々と

FORTRAN 77でマイナンバーのチェックデジットを計算

先日、WindowsバッチファイルとAwkチェックデジットを計算するプログラムを書きました。
その続きです。多分最後です。

Windowsバッチファイルでマイナンバーのチェックデジットを計算 - 沖の雑記帳

awkでマイナンバーのチェックデジットを検証・集計 - 沖の雑記帳

元の記事と同様に参照元は以下のQiitaの記事です。

マイナンバーのチェックデジットを計算する - Qiita

このシリーズいつまで続けようか?そもそも需要がない言語がほとんどだよね?
この辺は私がおっさんなので新しい言語を触ってないというよりも仕事柄古い言語を触ることが多いだけでもあるんだけどね。

さて、続きは長くなるので一旦折りたたみ

マイナンバーのチェックデジットを計算するコード

さて、早速だけどコードに入ろうか

c----------------------------------------------------------------
c マイナンバーの検証を行なう
c----------------------------------------------------------------
      program valid_mynumber
      implicit none             ! 変数は宣言して使おうね
      logical validate_chkdigit ! 関数の事前宣言必要なんだった

      character*13 numstr       ! 12にしちゃうと多い時判別できない
      integer l
      logical b
      call getarg(1,numstr)   ! 引数の取得(getargはサブルーチン)
      l = len_trim(numstr)    ! 空白を除去した文字数
      ! 文字数のチェックだね
      if (l.gt.12) then
        write (*,*) 'Input is over 12-digits.'
        stop
      else if(l.lt.12) then
        write (*,*) 'Input is less than 12-digits.'
        stop
      end if
      ! ここまで来たらサブルーチンまかせ
      b = validate_chkdigit(numstr)
      if (b) then
        write (*,*),'Valid number.'
      else
        write (*,*),'Invalid number.'
      end if
      stop
      end program

      ! 入力された番号が正しいか計算・検証する
      ! これがやりたいことなんだよ
      logical function validate_chkdigit(str)
        implicit none
        character*12 str    ! 引数の型宣言必要なんだった
        character c
        integer chkdigit,validdigit
        integer i,q,p,nsum,remainder
        integer atoi        ! atoiもどき
        atoi(c) = ichar(c) - ichar('0')
        nsum = 0
        !chkdigit = ichar(str(12:12)) - ichar('0')
        chkdigit = atoi(str(12:12))
        validate_chkdigit = .false.
        do i = 1, len_trim(str) - 1, 1
          !q = ichar(str(12-i:12-i)) - ichar('0')
          q = atoi(str(12-i:12-i))
          if (i.le.6) then
            p = i + 1
          else
            p = i - 5
          end if
          nsum = nsum + (p * q) ! +=とか使えなかったっけ…
        end do
        remainder = mod(nsum,11)
        if (remainder.le.1) then
          validdigit = 0
        else
          validdigit = 11 - remainder
        end if
        if (chkdigit.eq.validdigit) then
          validate_chkdigit = .true.
        else
          validate_chkdigit = .false.
        end if
      end

まとめ

まとめというか久しぶりにFORTRAN 77なんて書いてハマったこととか

  • implicit noneを入れないと変数宣言しなくても1文字目で型が決まっちゃうんだった

  • 関数の事前宣言の仕方を忘れてた

  • ブロック関数って便利な機能があったんだよね

  • +=みたいな書き方ができたような気がしたんだけどできなかった

  • サブルーチンはcallじゃないと呼べないんだった

  • 配列ってあふれた部分は切り捨てられるし、文字列は不足してると空白を埋められちゃう。だからlen(str)はちょうどのサイズだと12文字ちょうどか判別できない

と、まぁ数年ぶりに書いたらうろ覚えもいいところだよね。
でも、古い言語でもそれなりに覚えておいて損はないと思うんだよね。
そういう意味では、同じことを実現するために複数の言語で書くことができればその言語の得手不得手みたいなところも見えてきて選択範囲が広がると思うんだよね。

ちなみにFortran 90以降で書けば書き始めのカラム位置の制限はなくなるよ。1行の文字数も増えるよ。
そもそもFortran 90ではコンパイル通りませんでした。FORTRAN 77じゃないと無理っぽいです。
FORTRAN 77なんて過去の遺産…って言いたいんだけども、まだまだ使用しているシステムは結構あったりするんだよ。

強引に丸め込んじゃったけどもこれでおしまし…だと思う

追記(2016-04-11)

このページも含めリンクしてくださっている、yumedotoさんのページリンクを追加
様々な言語での実装状況まとめも作成されています。

qiita.com