【问题标题】:Count Array elements in String计算字符串中的数组元素
【发布时间】:2017-03-20 13:45:52
【问题描述】:

我正在尝试将包含未知数量整数的字符串读入 Fortran 数组。

string = "2  5,7 6 0"

解析字符串本身是可行的,因为我知道数组的最大可能大小。分隔符可以变化,例如空格、制表符逗号或这些的组合 但是我如何计算我读过多少元素呢? 目前我的代码如下所示:

program count_string_elements
  implicit none
  character(len=50) :: string
  integer :: i, count, imax, ios
  integer,allocatable :: tmp_arr(:)

  imax = 20
  allocate(tmp_arr(imax))

  string = "2  5,7 6 0"
  read(unit=string, fmt=*, iostat=ios) (tmp_arr(i), i=1,imax)
  print *, tmp_arr

  deallocate(tmp_arr)
end program

输出是

2    5    7    6    0    0    0    0    0    0

将其设置为默认值(如 -1、0 或其他值)不是一个选项,因为我无法排除它们在字符串中。

有没有办法中止读取,使 i 包含元素的数量(或元素的数量+1)?

更新 我通过扩展上面的代码找到了一种方法。

program count_string_elements
  implicit none
  character(len=50) :: string
  integer :: i, cnt, imax, ios
  integer,allocatable :: tmp_arr(:)
  character(len=50) :: str_arr(:)
  imax = 20
  allocate(tmp_arr(imax), str_arr(imax))

  string = "2  5,7 6 0"
  cnt = 0
  read(unit=string, fmt=*, iostat=ios) (str_arr(i), i=1,imax)
  do i = 1, imax
    if(len_trim(str_arr(i)) == 50) cycle
    cnt = cnt + 1
    read(str_arr(i),*) tmp_arr(cnt)
  end do
  print *, tmp_arr(:cnt)

  deallocate(str_arr, tmp_arr)
end program

但可能有更好的方法来做到这一点。

【问题讨论】:

  • 你的读取命令只是一个语句,而不是一个循环,你不能在两者之间中止它,你必须做一些更复杂的事情。 (tmp_arr(i), i=1,imax)tmp_arr(1:imax) 相同,或者在这种情况下与 tmp_arr 相同。
  • 您可以先进行词法分析并将字符串划分为一个标记列表,但对于这个简单的整数应用程序来说,这将是多余的。只需在循环中遍历字符串并移动您正在阅读的窗口。
  • 您也可以在bitbucket.org/LadaF/elmm/src/… 中使用我的函数count_multispaces,我不再使用它,但几乎可以满足您的需求。只需使用更多分隔符,然后只使用空格 ` 并将结果加 1。
  • 它适用于多位整数以及负整数就好了。只有当有 50 位整数时,循环才会把事情搞砸,这不会发生。
  • 好的,我现在可以看到你做了什么。有点浪费内存,但会工作。

标签: arrays io fortran


【解决方案1】:

有很多不同的可能整数值。这应该不会太难,这取决于您必须找到一个不太可能成为数据集一​​部分的数据类型,并将该数据用作虚拟对象。

也就是说,我解决这个问题的方法(快速而肮脏)就是遍历整个字符串并计算非数字和数字之间的转换次数。

看这个例子:

program arb_array

    implicit none
    character(len=30) :: test_string
    integer :: imax
    integer :: array(10)

    test_string = "2  5,7 6 0"

    imax = count_integers(test_string)

    read(test_string, *) array(:imax)
    print*, imax, array(:imax)

contains

    function is_digit(c)
        implicit none
        character, intent(in) :: c
        logical :: is_digit
        is_digit = ((ichar(c) >= ichar('0')) .and. (ichar(c) <= ichar('9')))
        return
    end function is_digit

    function count_integers(string) result(imax)
        implicit none
        character(len=*), intent(in) :: string
        integer :: imax
        integer :: i

        imax=0
        i = 1
        counter_loop : do
            do while (.not. is_digit(string(i:i)))
                i = i + 1
                if (i > len(string)) exit counter_loop
            end do
            imax = imax+1
            do while (is_digit(string(i:i)))
                i = i + 1
                if (i > len(string)) exit counter_loop
            end do
        end do counter_loop

    end function count_integers
end program arb_array

【讨论】:

    猜你喜欢
    • 2012-08-21
    • 2020-10-23
    • 2017-02-25
    • 2011-07-04
    • 1970-01-01
    • 1970-01-01
    • 2022-10-15
    • 1970-01-01
    相关资源
    最近更新 更多