PP#10~Fortran Tips#5

PP#10~Fortran Tips#5

サブルーチンstrtoimdの作成編の最終回です。これで文字列呼び込みルーチンReadDblArrayが完成します。

前回は読み込んだ文字列の文字数をカウントしましたが、今回は読み込んだ文字数を数値に変換する処理を行います。

繰り返しますが、文字”*”の前段の数値は後段の実数を読み込む回数の事です。念のため。

subroutine strtoimd(Line, Nx, Words, NumValue, IntValue, DblValue)
!********************************************************************************
!*                                                                              *
!*  Convert the String to Integer and Double                                	*
!*                                                                              *
!********************************************************************************
    implicit none
    integer,intent(in)::     Nx 
    integer,intent(out)::    NumValue,    IntValue(Nx)
    real*8,intent(out)::     DblValue(Nx)  
    character,intent(inout)::Line*(*)
    integer::   NumWord,NumChar(Nx),length, cbegin, cend,   count,  star,       &
                endPtr,     i,      j,      k
    character:: Words(Nx)*(*)
    logical::	digit
!================================================================================
!   Function	    :	Convert string to float including the expression like
!   			:	"15*100.0", which is read as double (100.0) by int (15)
!	Line		    :	Each line in the input data
!	NumWord		:	Number of words in the Line
!   NumChar     :   Number of characters in each word      
!	Words		:	Array of the words comprised of the line
!	NumValue	:	Number of values extracted from the Line
!	IntValue	:	Integer value extracted from the Line
!	DblValue	:	Double  value extracted from the Line
!   endPtr      :   Pointer of the remaining word after converting the word
!   length      :   Length of Line    
!  	cbegin      :   Location of the first character of each word
!	cend        :   Location of the last  character of each word
!	count       :   Number of count	
!================================================================================
!Extract words from Line given
!================================================================================    
    length = len_trim(Line)        !Calculate length of the string without space

    !Global loop to find the "void" character
	cbegin = 1
	cend   = 1
	count  = 0
    do while (cbegin <=length)	

		if ( Line(cbegin:cbegin) == '0' .or. Line(cbegin:cbegin) == '1' .or. &
             Line(cbegin:cbegin) == '2' .or. Line(cbegin:cbegin) == '3' .or. &
             Line(cbegin:cbegin) == '4' .or. Line(cbegin:cbegin) == '5' .or. &
             Line(cbegin:cbegin) == '6' .or. Line(cbegin:cbegin) == '7' .or. &
             Line(cbegin:cbegin) == '8' .or. Line(cbegin:cbegin) == '9' .or. &
             Line(cbegin:cbegin) == '-' .or. Line(cbegin:cbegin) == '.' ) then
        
            count = count + 1
			do j=cbegin+1,length+1   !Local loop to find the next "void" character
				if (Line(j:j) == ' ' .or. Line(j:j) == '\0' .or. Line(j:j) == '\n') then
					cend = j - 1
					exit
                endif
                cend = j
            enddo

			NumChar(count) = cend - cbegin + 1
            do k=1,NumChar(count)
                Words(count)(k:k) = Line(cbegin+k-1:cbegin+k-1)
            enddo
            cbegin = cend
        endif
        cbegin = cbegin + 1   
        
    enddo
    NumWord = count
    
    !print *, "Numword= ",NumWord, ", Word= ",Words(NumWord)
!================================================================================
!Convert words to digit
!================================================================================
	count = 0   !Count number of values

	do i=1,NumWord
        
		digit = .true. 
		do j=1,NumChar(i)
            !Check if Words is digit or letter
			if (.not.( Words(i)(j:j) == '0' .or. Words(i)(j:j) == '1' .or. &
                       Words(i)(j:j) == '2' .or. Words(i)(j:j) == '3' .or. &
                       Words(i)(j:j) == '4' .or. Words(i)(j:j) == '5' .or. &
                       Words(i)(j:j) == '6' .or. Words(i)(j:j) == '7' .or. &
                       Words(i)(j:j) == '8' .or. Words(i)(j:j) == '9' .or. &
                       Words(i)(j:j) == '-' .or. Words(i)(j:j) == '.' .or. &
                       Words(i)(j:j) == '*' ) )     digit = .false.
        enddo

		!Convert the string to float
		if (digit) then !Words contains digit only

			!Check if string contains '*' and location number
			star = index( Words(i)(1:NumChar(i)), '*' )

            !Convert the string to int and double
			if (star > 0) then
				count = count + 1
				IntValue(count) = atoi( Words(i)(:star-1))
				DblValue(count) = atof( Words(i)(star+1:NumChar(i)))
			else 
				count = count + 1
				IntValue(count) = 1
				DblValue(count) = atof( Words(i)(1:NumChar(i)))
            endif
            
        endif
		NumValue = count

        !print *,"Words = ",Words(i),", NumValue = ",NumValue,", IntValue = ",IntValue(i),", DblValue = ",DblValue(i),", ChrValue = ",ChrValue(i)
        
    enddo
!================================================================================
end subroutine

呼び出すルーチンを含めて、これまで作成した一連の関係サブルーチンを下記に纏めておきます。

program call_ReadDblArray
!********************************************************************************
!*  call_ReadDblArray                                                           *
!********************************************************************************
    implicit none
    integer,parameter::     fin = 5
    integer,parameter::     Nx = 10,    LINEMAX = 130       
    character(len=LINEMAX)::inkey
    integer::   Inx,    ip
    real*8::    DblArray(Nx)                 
!================================================================================
    do
        call getline(fin, inkey)
        print '("Key to be input (/ to exit): ", a)', inkey
        if (inkey == '/') exit
        Inx = 0;    call ReadDblArray(inkey, LINEMAX, Inx, Nx, DblArray)
        print '("Value to be output:")'
        do ip=1,Inx
            print '("DblArray (",i2,") = ",f20.7)', ip, DblArray(ip)
        enddo
    enddo
    print '("Reached end of program")'
!================================================================================
    stop
!================================================================================
    contains
!================================================================================   
        integer function atoi(String)
        !************************************************************************
        !*  Convert String to Interger Value                                    *
        !************************************************************************
            implicit none
            character,intent(in)::	String*(*)
            integer::   count,  digit
        !========================================================================
            !read(String,'(i10)') atoi
        !========================================================================
            count = 1
            atoi  = 0
            do while (count<=len(trim(String)))
                if (String(count:count) >= '0' .and. String(count:count) <= '9') then
                    read(String(count:count),*) digit
                    atoi = 10*atoi + digit
                endif
                count = count + 1
            enddo
            !print '("atoi ", i10)', atoi
        !========================================================================          
        end function      
        real*8 function atof(String)
        !************************************************************************
        !*  Convert String to Double Precision Value                            *
        !************************************************************************
            implicit none
            character,intent(in)::	String*(*)
        !========================================================================
        read(String,*) atof     
        !========================================================================          
        end function      
        subroutine getline(File, Line)
        !********************************************************************************
        !*  Read Data in a Line                                                         *
        !********************************************************************************
        implicit none
        integer,intent(in)::     File
        character,intent(inout)::Line*(*)
        !================================================================================
        read(File, '(a)') Line
        !================================================================================
        end subroutine
		subroutine ReadDblArray(Line, LineMax, Inx, Nx, DblArray)
		!********************************************************************************
		!*  Read the Double Array                                                       *
		!********************************************************************************
		    implicit none
		    integer,intent(in)::     Nx,        LineMax
		    integer,intent(inout)::  Inx
		    real*8,intent(out)::     DblArray(Nx)           
		    character,intent(inout)::Line*(*)
		    integer::   NumWord,    NumValue,   IntValue(Nx),       i,      j
		    real*8::    DblValue(Nx)   
		    character:: Words(Nx)*LineMax
		!================================================================================
		!   Line	        :   Line string given
		!   LineMax     :   Max characters in Line
		!   Inx		    :   Index of the DblArray	
		!   Nx          :   Number of array of the words comprised of the line
		!   DblArray	    :   Array to be inputed
		!   NumWord     :   Number of words in the Line
		!   Words       :   Array of the words comprised of the line
		!   NumValue    :   Number of values
		!   IntValue(Nx):   Integer   value extracted from the Line
		!   DblValue(Nx):   Double    value extracted from the Line
		!================================================================================
		!   Extract IntValue and DblValue from the line string given
		!================================================================================
		    call strtoimd(Line, Nx, Words, NumValue, IntValue, DblValue)
		!================================================================================
		!   Input DbleArray given
		!================================================================================
		    do i=1,NumValue
		    do j=1,IntValue(i)
			    Inx = Inx + 1
			    DblArray(Inx) = DblValue(i)
		    enddo
		    enddo
		!================================================================================
		end subroutine        
		subroutine strtoimd(Line, Nx, Words, NumValue, IntValue, DblValue)
		!********************************************************************************
		!*                                                                              *
		!*  Convert the String to Integer and Double                                	*
		!*                                                                              *
		!********************************************************************************
                .................
		!================================================================================
		end subroutine
end program

事例として二つの文字列を入力させた結果はこんな感じ。

call_ReadDblArray2

如何でしたか?

因みに、strtoimdとはString To Integer and Doubleを示します。うろ覚えですが。

以上

Comments are closed.