Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/fortran/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Fortran 为什么我的程序循环两次?_Fortran_Gfortran - Fatal编程技术网

Fortran 为什么我的程序循环两次?

Fortran 为什么我的程序循环两次?,fortran,gfortran,Fortran,Gfortran,我试图用Fortran创建一个touper和toLower函数,它们在我的实现中似乎工作得很好;程序会提示用户输入字符串,然后用大写字母和小写字母打印出来 然而,在我添加了大写函数之后,程序会提示用户输入两次字符串,我不知道为什么。这似乎管用,但它能做两次 有人能告诉我为什么我的程序会提示输入两次吗?下面是代码和输出 program stringutils character :: words*1000 print*, 'Enter a string.' read(*,

我试图用Fortran创建一个touper和toLower函数,它们在我的实现中似乎工作得很好;程序会提示用户输入字符串,然后用大写字母和小写字母打印出来

然而,在我添加了大写函数之后,程序会提示用户输入两次字符串,我不知道为什么。这似乎管用,但它能做两次

有人能告诉我为什么我的程序会提示输入两次吗?下面是代码和输出

program stringutils
    character :: words*1000

    print*, 'Enter a string.'
    read(*,'(A)') words

    call toUpper(words)
    print*, 'toUpper: ', trim(words)

    call toLower(words)
    print*, 'toLower: ', trim(words)

    call capitalize(words)
    print*, 'capitalize: ', trim(words)

end program stringutils

subroutine toUpper(string)
    character :: string*1000
    integer :: i, charNum

    do i = 1, len(trim(string))
        charNum = iachar(string(i:i))
        if (charNum >= 97 .and. charNum <= 122) then
            string(i:i) = achar(charNum - 32)
        end if
    end do
end subroutine toUpper

subroutine toLower(string)
    character :: string*1000
    integer :: i, charNum

    do i = 1, len(trim(string))
        charNum = iachar(string(i:i))
        if (charNum >= 65 .and. charNum <= 90) then
            string(i:i) = achar(charNum + 32)
        end if
    end do
end subroutine toLower

subroutine capitalize(string)
    character :: string*1000
    integer :: i

    call toUpper(string(1:1))
    do i = 2, len(trim(string))
        if (iachar(string(i-1:i-1))==32) then
            call toUpper(string(i:i))
        else
            call toLower(string(i:i))
        end if
    end do
end subroutine capitalize

我在Windows中通过MinGW使用gfortran。

虽然我不确定是什么导致它循环两次,但我知道这与大写函数有关,也可能是我如何将一个字符发送到一个需要1000个字符的函数。所以我添加了charToUpper和charToLower函数,现在它可以按预期工作了。这是新代码。我觉得大写的功能会更好。。。欢迎评论

program stringutils
    character words*1000

    print*, 'Enter a string.'
    read(*,'(A)') words

    call toUpper(words)
    print*, 'toUpper: ', trim(words)

    call toLower(words)
    print*, 'toLower: ', trim(words)

    call capitalize(words)
    print*, 'capitalize: ', trim(words)

end program stringutils

subroutine toUpper(string)
    character string*1000
    integer i

    do i = 1, len(trim(string))
        call charToUpper(string(i:i))
    end do
end subroutine toUpper

subroutine toLower(string)
    character string*1000
    integer i

    do i = 1, len(trim(string))
        call charToLower(string(i:i))
    end do
end subroutine toLower

subroutine charToUpper(c)
    character c
    integer charNum

    charNum = iachar(c)
    if (charNum >= 97 .and. charNum <= 122) then
        c = achar(charNum - 32)
    end if
end subroutine charToUpper

subroutine charToLower(c)
    character c
    integer charNum

    charNum = iachar(c)
    if (charNum >= 65 .and. charNum <= 90) then
        c = achar(charNum + 32)
    end if
end subroutine charToLower

subroutine capitalize(string)
    character :: string*1000
    integer :: i

    call charToUpper(string(1:1))
    do i = 2, len(trim(string))
        if (iachar(string(i-1:i-1))==32) then
            call charToUpper(string(i:i))
        else
            call charToLower(string(i:i))
        end if
    end do
end subroutine capitalize
程序stringutils
字数*1000
打印*,“输入字符串。”
读(*,‘(A)’字
呼叫toUpper(单词)
打印*,'toUpper:',修剪(文字)
呼叫toLower(文字)
打印*,“toLower:”,修剪(文字)
呼叫大写(字)
打印*,“大写:”,修剪(文字)
结束程序stringutils
子例程toUpper(字符串)
字符串*1000
整数i
i=1,len(修剪(字符串))
调用图表组(字符串(i:i))
结束
结束子程序toUpper
子例程toLower(字符串)
字符串*1000
整数i
i=1,len(修剪(字符串))
调用charToLower(字符串(i:i))
结束
结束子程序toLower
子程序图表组(c)
字符c
整数字符数
charNum=iachar(c)

如果(charNum>=97.and.charNum=65.and.charNum这是一个扩展的注释,而不是答案

我不相信你对最初报告的问题原因的解释。我不明白为什么程序会因为一两个错误指定的例程而执行两次。尽管如此,如果对现代Fortran实践稍加注意,你的例程会得到很大改进

您已经编写了一系列例程来处理包含1000个字符的字符串。更好的做法当然是编写这些例程来处理作为参数传递的字符串的长度。Modern Fortran(从我不确定的时候起,至少90个,可能更早)允许传递假定长度的字符参数,如下所示:

subroutine toUpper(string)
    character(*) :: string
    integer :: i, charNum

    do i = 1, len(trim(string))
        charNum = iachar(string(i:i))
        if (charNum >= 97 .and. charNum <= 122) then
            string(i:i) = achar(charNum - 32)
        end if
    end do
end subroutine toUpper
子例程toUpper(字符串)
字符(*):字符串
整数::i,charNum
i=1,len(修剪(字符串))
charNum=iachar(字符串(i:i))

如果(charNum>=97.and.charNum,我已经在Linux中用
Gfortran
编译了您的代码。 我经历了以下几点: 你的“循环两次”问题确实发生了,但不是每次都发生在我身上。我随机地遇到了一个分段错误。 我试着回答:

您假设正确,问题来自
大写
子例程。我未能使用
gdb
调试您的代码,但seg错误似乎表明您试图访问未声明的字符串的组件或类似的内容,并且您正在循环中调用
toUpper
toLower
。在那里我发现了一些东西:

在循环中,您通过发送
string(i:i)
来调用
toUpper
toLower
,这是一个唯一的字符(长度1)。但是在
toUpper
中,您声明了一个长度为1000的字符,而在此例程中,您正在处理
string(i:i)
仅限长度为1的字符,这是不符合逻辑的。通过将
字符::字符串*1000
替换为
字符::字符串*1
,它似乎可以工作,而且更有意义,因为此子例程每次需要转换一个字符

我无法解释为什么你的代码崩溃或循环两次,但它可能是某种内存泄漏作为你的字符长度溢出的结果


总之,@High Performance Mark为您提供了一个关于假定长度字符参数的好建议。如果您以某种方式通过模块和接口执行参数检查,编译器可能会警告您。也许一个
INTENT
子句是明智的。这些是Fortran 90的强大功能。

I子例程调用函数并使用假定长度字符,但编译失败。传递的参数的长度仍然为1000…character()函数TOUPPER(STRING)character()字符串整数I DO I=1,LEN(TRIM(STRING))STRING(I:I)=chartupper(STRING(I:I))END DO END FUNCTION TOUPPER错误:(1)处的字符值内部函数“TOUPPER”不能被假定为长度。很抱歉,我不知道如何设置格式。不要在注释中提问,它们太难阅读。
subroutine toUpper(string)
    character(*) :: string
    integer :: i, charNum

    do i = 1, len(trim(string))
        charNum = iachar(string(i:i))
        if (charNum >= 97 .and. charNum <= 122) then
            string(i:i) = achar(charNum - 32)
        end if
    end do
end subroutine toUpper