Как прочитать число в фортран с точкой с разделителем тысяч и запятой с разделителем, например, 123.456.891.234,56

Скорее всего, ваше имя БД неверно, вы увидите имя сервера в VS, как «DESKTOP-0I14BKI», но если вы откроете SSMS, вы увидите DESKTOP-0I14BKI \ SQLBLAHBLAH , просто добавьте « \ SQLBLAHBLAH » (имя экземпляра) к вашему «имени сервера» в свойствах VS-соединения.

Вы увидите:

To Fix:

1
задан talonmies 25 February 2019 в 19:11
поделиться

3 ответа

Если вы действительно хотите сделать это в Фортране, это не так уж сложно. Во-первых, давайте возьмем функцию для удаления всех вхождений . из строки:

  FUNCTION drop_stops(instr) RESULT(outstr)
    CHARACTER(len=*), INTENT(in) :: instr
    CHARACTER(len=:), ALLOCATABLE :: outstr
    CHARACTER(len=1), DIMENSION(:), ALLOCATABLE :: str_array

    ALLOCATE(str_array(LEN_TRIM(instr)))
    str_array = TRANSFER(instr,str_array)
    str_array = PACK(str_array,str_array /= '.')
    ALLOCATE(CHARACTER(len=SIZE(str_array))::outstr)
    outstr = TRANSFER(str_array,outstr)
  END FUNCTION drop_stops

Я верю, что это достаточно очевидно, чтобы не нуждаться в объяснении, кроме документации каких-либо функций или утверждений, которые вы не знаком с.

Затем, придерживаясь своего исходного кода и объявив другую строковую переменную, вы можете прочитать dummy, как вы уже это делаете, затем написать что-то вроде

 dummy_without_stops = drop_stops(dummy)

, и теперь вы можете выполнить внутреннее чтение этого чтобы получить интересующие вас числа, что-то вроде

read(dummy_without_stops,*,decimal='comma') a, b, c

Обратите внимание, что подход, реализованный в drop_stops, зависит от символов в строке, последовательно размещаемых в памяти и соответствующих одному и тому же хранилищу для символы в массиве. Я уверен, что это будет работать для символов ASCII, но не уверен насчет символов ISO_10646.

0
ответ дан High Performance Mark 25 February 2019 в 19:11
поделиться
program prjRead
  implicit none

  integer:: a
  real(8) :: b
  real(8) :: c
  character(18) :: header
  character(18) :: cAsString
  character(18) :: cWithOutStops

  open (123,file = "test.csv", DECIMAL='COMMA')

  read(123,*) header
  read(123,*) a, &
              b, &
              cAsString

  cWithOutStops = drop_stops(cAsString)

  read(cWithOutStops,*,decimal='comma')  c

  write(*,*) "gives c without decimal places"
  write(*,*) a,b,c

  write(*,*) "********************"
  write(*,*) "second try, the function drop_stops does what it 
promisses. If have to feed it with the right string"
  cAsString ="123.456,78"
  cWithOutStops = drop_stops(cAsString)
  read(cWithOutStops,*,decimal='comma')  c

  write(*,*) a,b,c

contains

FUNCTION drop_stops(instr) RESULT(outstr)
    CHARACTER(len=*), INTENT(in) :: instr
    CHARACTER(len=:), ALLOCATABLE :: outstr
    CHARACTER(len=1), DIMENSION(:), ALLOCATABLE :: str_array

    ALLOCATE(str_array(LEN_TRIM(instr)))
    str_array = TRANSFER(instr,str_array)
    str_array = PACK(str_array,str_array /= '.')
    ALLOCATE(CHARACTER(len=SIZE(str_array))::outstr)
    outstr = TRANSFER(str_array,outstr)
  END FUNCTION drop_stops
end program prjRead

Выходные данные

дают c без десятичных разрядов 5 56.670000000000002 123456.00000000000 ********************************************************* drop_stops делает то, что обещает. Если нужно указать правильную строку 5 56.670000000000002 123456.78000000000

Решение HighPerformanceMarks почти готово. Мне не хватает только умения проглотить число с одним куском при чтении. или я читаю 2 строки и объединяю их.

0
ответ дан Ratilius 25 February 2019 в 19:11
поделиться

Вы не предоставили достаточно большой сэмпл из вашего входного файла. Но, по сути, вам нужно сначала разделить содержимое файла по разделителю ;. Затем для каждого полученного вами номера строки замените все разделители тысяч . на «» (ничего). Затем замените десятичный символ , нормальным десятичным обозначением .. Вот попытка добиться этого с помощью 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
0
ответ дан King 25 February 2019 в 19:11
поделиться
Другие вопросы по тегам:

Похожие вопросы: