不同长度的Fortran子字符串比较存在问题

时间:2018-11-11 21:49:31

标签: fortran gfortran

我正在循环阅读stdin,并与一堆“ if”进行比较,以根据输入内容决定要做什么。

这是这段代码的简短片段:

CHARACTER (len= :), allocatable :: input
CHARACTER (len=4096) :: inbuffer            ! frustrating but... well, fortran :3

DO

    ! get input
    READ(*, '(a)') inbuffer     ! because apparently you can't have allocation on read so you can't just read "input". meh.
    input = TRIM(inbuffer)
    CALL debug_log(input)

    IF(input .EQ. 'uci') THEN
        CALL debug_log("   printing uci info")

    !isready
    ELSE IF(input .EQ. 'isready') THEN
        CALL debug_log("   isready -> readyok")
        WRITE(*, '(a)') "readyok"

    !ucinewgame
    ELSE IF(input .EQ. 'ucinewgame') THEN
        CALL debug_log("not implemented : reset board and start a new game")

    !position
    ELSE IF(input(1:8) .EQ. 'position') THEN
        CALL debug_log("not implemented : set position")

    !quit -> exit main loop
    ELSE IF(input .EQ. 'quit') THEN
        CALL debug_log("   quit command issued, exiting main loop")
        EXIT

    !non uci command
        !nothing yet

    !unknown command
    ELSE
        CALL debug_log("   ignoring invalid command")
    END IF

end do

输入将期望输入类似“位置123 23415等...”的命令

如果我键入“ posi”,则表示这是预期的无效命令。

如果我键入“ position”,则表示它也没有按预期实现。

但是

  • 如果我输入“ position”:我没有实现
  • 后跟“ posi”:它表示“未实现”,而不是“无效命令”

我的猜测是,即使输入只有4个字符,它也会读取8个字符,并且由于上一个命令是“ position”,因此它的位置为+位置= p

以下是一些日志来演示:

** opening debug file : 20181111 / 223418.127
223418.127 : Initializing Fortiche engine
223418.129 : Entering main loop
223420.859 : posi
223420.859 :    ignoring invalid command
223426.467 : xxxxtion
223426.467 :    ignoring invalid command
223430.498 : posi
223430.498 : not implemented : set position
223437.323 : xxxxxxxxx
223437.323 :    ignoring invalid command
223439.418 : posi
223439.418 :    ignoring invalid command
223443.979 : position
223443.979 : not implemented : set position
223447.122 : quit
223447.122 :    quit command issued, exiting main loop
223447.122 : closing, bye

xxxxtion + posi =位置

这显然是错误的,但是我可以理解它是如何最终结束的。

我应该使用.EQ以外的其他名称吗? 当我打印输入时,显然不会打印输入+内存中留下的任何垃圾。但是在比较长度可能不同的字符串时会这样做。

我该怎么做才能解决此问题?

我什至没有开始进行核心解析,我已经遇到了问题。

我在Windows上使用GNU Fortran。

是的,它是UCI的通用国际象棋界面。

编辑:完整源代码:https://github.com/ker2x/fortiche(注释第107和108行的肮脏黑客以重现该问题)

1 个答案:

答案 0 :(得分:4)

子字符串引用的开始和结束位置必须在字符串的范围内。

对于在子字符串引用input(1:8) .eq. 'position'之前长度小于八的字符串,您不会采取任何措施。

如果输入的字符少于八个字符,则您的程序将不符合要求,则任何事情都可能发生,其中很合理的任何事情都包含您所看到的行为。

运行时调试选项可能有助于捕获此编程错误,具体取决于编译器的功能。