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