Вы не предоставили достаточно большой образец из вашего входного файла.Но, по сути, вам нужно сначала разделить содержимое файла по разделителю ;
.Затем для каждого полученного вами номера строки замените все тысячи разделителей .
на "" (ничего).Затем замените десятичный символ ,
нормальным десятичным обозначением .
.Вот попытка добиться этого с помощью splitStr()
и replaceStr()
процедур с привязкой к типу, приведенных ниже, протестированных на предоставленной вами строке содержимого файла примера 5;56,67;123.456,78
module String_mod
use, intrinsic :: iso_fortran_env, only: IK=>int32, RK=>real64
implicit none
public
character(*), parameter :: MODULE_NAME = "@String_mod"
type :: CharVec_type
character (:), allocatable :: record
end type CharVec_type
type :: String_type
character(:) , allocatable :: value
type(CharVec_type), allocatable :: Parts(:)
integer(IK) :: nPart = 0
contains
procedure, nopass :: replaceStr, splitStr, str2num
end type String_type
!***********************************************************************************************************************************
!***********************************************************************************************************************************
contains
!***********************************************************************************************************************************
!***********************************************************************************************************************************
recursive function replaceStr(string,search,substitute) result(modifiedString)
implicit none
character(len=*), intent(in) :: string, search, substitute
character(len=:), allocatable :: modifiedString
integer(IK) :: i, stringLen, searchLen
stringLen = len(string)
searchLen = len(search)
if (stringLen==0 .or. searchLen==0) then
modifiedString = ""
return
elseif (stringLen<searchLen) then
modifiedString = string
return
end if
i = 1
do
if (string(i:i+searchLen-1)==search) then
modifiedString = string(1:i-1) // substitute // replaceStr(string(i+searchLen:stringLen),search,substitute)
exit
end if
if (i+searchLen>stringLen) then
modifiedString = string
exit
end if
i = i + 1
cycle
end do
end function replaceStr
!***********************************************************************************************************************************
!***********************************************************************************************************************************
function splitStr(string,delimiter)
implicit none
character(len=*) , intent(in) :: string,delimiter
character(len=:) , allocatable :: dummyStr
type(CharVec_type), allocatable :: splitStr(:)
integer(IK) :: maxNumSplit
integer(IK) :: stringLen, delimLen, splitCounter, currentPos
dummyStr = string
delimLen = len(delimiter)
stringLen = len(dummyStr)
if (delimLen==0) then
allocate(splitStr(1))
splitStr(1)%record = string
return
end if
maxNumSplit = 1 + stringLen / delimLen
allocate(splitStr(maxNumSplit))
splitCounter = 1
loopParseString: do
if (stringLen<delimLen) then
splitStr(splitCounter)%record = dummyStr
exit loopParseString
elseif (stringLen==delimLen) then
if (dummyStr==delimiter) then
splitStr(splitCounter)%record = ""
end if
exit loopParseString
elseif (dummyStr(1:delimLen)==delimiter) then
dummyStr = dummyStr(delimLen+1:stringLen)
stringLen = len(dummyStr)
cycle loopParseString
else
currentPos = 2
loopSearchString: do
if (dummyStr(currentPos:currentPos+delimLen-1)==delimiter) then
splitStr(splitCounter)%record = dummyStr(1:currentPos-1)
if (currentPos+delimLen>stringLen) then
exit loopParseString
else
splitCounter = splitCounter + 1
dummyStr = dummyStr(currentPos+delimLen:stringLen)
stringLen = len(dummyStr)
cycle loopParseString
end if
else
currentPos = currentPos + 1
if (stringLen<currentPos+delimLen-1) then
splitStr(splitCounter)%record = dummyStr
exit loopParseString
end if
cycle loopSearchString
end if
end do loopSearchString
end if
end do loopParseString
splitStr = splitStr(1:splitCounter)
end function splitStr
!***********************************************************************************************************************************
!***********************************************************************************************************************************
pure elemental function str2num(str)
implicit none
character(len=*), intent(in) :: str
real(RK) :: str2num
read(str,*) str2num
end function str2num
!***********************************************************************************************************************************
!***********************************************************************************************************************************
end module String_mod
program readFile_prog
use String_mod, only: String_type
implicit none
! Rules: comma means decimal point. Dot means thousands separator. delimiter is ;.
character(*), parameter :: FileToRead = "5;56,67;123.456,78"
type(String_type) :: String
integer :: i
! read file
String%value = FileToRead
! split file contents into individual numbers
String%Parts = String%splitStr(String%value,";")
! count the number of integers in the file
String%nPart = size(String%Parts)
do i = 1, String%nPart
! For each number, remove the thousands separator, by replacing "." with ""
String%Parts(i)%record = String%replaceStr(String%Parts(i)%record,".","")
! now replace comma decimal symbols with regular . decimal notation
String%Parts(i)%record = String%replaceStr(String%Parts(i)%record,",",".")
! Covert the integer number from character type to integer and print it on screen
write(*,"(*(g0,:,' '))") "Number(",i,") = ", String%str2num(String%Parts(i)%record)
end do
end program readFile_prog
Вот вывод:
$gfortran -std=f2008 *.f95 -o main
$main
Number( 1 ) = 5.0000000000000000
Number( 2 ) = 56.670000000000002
Number( 3 ) = 123456.78000000000