continue在Fortran中是空语句(null statement):执行它不会计算、不会修改变量,也不会自动进入下一轮循环。它最容易和上一篇介绍的cycle混淆。
现代Fortran通常使用do … end do组织循环,因此continue很少是首选语句。阅读旧式Fortran程序时,它仍然值得认识,因为旧式标签循环经常把continue作为循环终点。
先区分三个语句
| 语句 | 本身做什么 | 循环之后发生什么 |
|---|---|---|
continue | 什么都不做 | 执行下一条语句 |
cycle | 跳过当前轮次剩余的循环体 | 进入下一轮循环 |
exit | 结束当前所在的循环 | 执行循环之后的语句 |
因此,continue不是“继续下一轮”的意思。需要跳过当前轮次时使用cycle,需要提前结束循环时使用exit。
本文代码
! continue是空语句,不跳过循环也不执行计算。
program continueStatementDemo
implicit none
integer :: number
integer :: total
total = 0
write (*,"(A)") "现代结构化循环中的continue:"
do number = 1, 3
if (number == 2) then
write (*,"(A,I0,A)") "number=", number, ",执行continue;不跳过。"
continue
end if
total = total + number
write (*,"(A,I0,A,I0)") "number=", number, ",sum=", total
end do
write (*,"(A,I0)") "sum:", total
write (*,"(A)") "如果目标是跳过当前轮次,应使用cycle,而不是continue。"
end program continueStatementDemo
编译运行
(base) hong@hongdeMacBook-Pro 028.continueStatement % gfortran -Wall -Wextra -std=f2018 exampleContinueStatement.f90
(base) hong@hongdeMacBook-Pro 028.continueStatement % ./a.out
现代结构化循环中的continue:
number=1,sum=1
number=2,执行continue;不跳过。
number=2,sum=3
number=3,sum=6
sum:6
如果目标是跳过当前轮次,应使用cycle,而不是continue。
结果分析
- number为1时没有特殊处理,执行累计,total变为1。
- number为2时执行continue,但continue之后仍然会离开if并执行下面的累计语句,因此total变为3。
- number为3时正常累计,最终得到1+2+3=6。
如果把代码中的continue替换为cycle,数字2之后的累计语句就不会执行,最终结果会变成4。这正好说明两者不能混用。
旧式标签循环
在旧式Fortran中,continue常作为带标签do循环的终点。旧式代码通常使用固定格式文件,例如.f文件;语句标签位于每行前部,代码从固定列开始。
C 旧式固定格式Fortran:CONTINUE作为带标签DO循环的终点。
PROGRAM LEGACYCONTINUEDEMO
INTEGER NUMBER
INTEGER TOTAL
TOTAL = 0
WRITE (*,'(A)') '旧式标签循环:'
DO 100 NUMBER = 1, 3
TOTAL = TOTAL + NUMBER
WRITE (*,'(A,I1,A,I1)') 'NUMBER=', NUMBER,
1 ',当前累计值=', TOTAL
100 CONTINUE
WRITE (*,'(A,I1)') '最终累计值:', TOTAL
WRITE (*,'(A)') '标签100标记了旧式DO循环的终点。'
END
这里的100是语句标签,CONTINUE是标签所在的空语句。DO 100 NUMBER = 1, 3把100指定为循环终点:NUMBER从1变化到3,每轮执行循环体,到达100 CONTINUE后进入下一轮或结束循环。
旧式代码的编译运行
(base) hong@hongdeMacBook-Pro 028.continueStatement % gfortran exampleContinueStatementF77.f -ob
(base) hong@hongdeMacBook-Pro 028.continueStatement % ./b
旧式标签循环:
NUMBER=1,当前累计值=1
NUMBER=2,当前累计值=3
NUMBER=3,当前累计值=6
最终累计值:6
标签100标记了旧式DO循环的终点。
旧式写法与现代写法都得到1+2+3=6,只是循环终点的表达方式不同。
从旧式到现代与知识点总结
- 旧式写法把循环终点写成数字标签,例如DO 100 NUMBER = 1, 3。
- 100 CONTINUE本身仍然是空语句,真正的循环控制关系来自DO 100和标签100。continue不会跳过当前轮次。
- 迁移旧代码时,不能只删除100 CONTINUE,还要把DO 100改写为完整的do … end do结构。
- 现代写法使用do number = 1, 3 … end do,循环边界和结构更容易从代码缩进中看出来。
- 在现代(新式、f90、自由格式的)do … end do中不应随意添加数字标签。没有跳转或旧式循环用途时,标签只会增加阅读与维护负担。
- 看到continue不应本能认为其控制了循环。应先查看它是否是旧式DO label的终点,或是否是GOTO的目标。
- continue在新旧体系中都是合法的空语句,本身不执行计算。
- f90应使用结构清晰的do … end do,避免无必要的标签和跳转。