从书中复制的旧代码的语法错误

Syntax errors from an old code copied from a book

这是一本80年代的书,作者是法国人,C. Jablon和J. C. Simon。我有这本书的俄语译本。标题“Применение ЭВМ для численного моделирования в физике”的意思是 "Applying ECM for numeric modelling in physics",其中 ECM 代表电子计算器(不知道它是如何翻译成英语的,但在俄语中他们曾经用这个名字来称呼计算机)。我试图 google 这本书的俄语、英语或法语数字形式,但我没有找到任何东西。如果它有帮助,这里是它的俄语照片:

https://drive.google.com/open?id=0B2MCX8tD_-VNLTh3dWx0ejJIZW8

这里是书上打印的代码

    parameter nn = 100
    dimension a(nn), b(nn), c(nn), d(nn), x(nn), u(nn)
    dimension xex(nn), test(nn)
    common /thomas/ bet(nn), gam(nn)
    common /perm/ ip(10)

    call iniper(10, -1)
    call inhuni(-1)
    read 222, iter, ifin
    print 1000, iter, ifin
    fifin = 1./float(ifin)
    fiter = 1./float(iter)
    pi = 3.14159265
    pi2 = pi * pi
    xa = 1.
    xc = 1.
    read 111, rb
1   continue
    read 222, n
    print 5000, n
    if(n .gt. nn) stop "alerte"
    xb = 2. - rb * p12 / (float(n + 1) ** 2)
    print 2000, xa, xb, xc
    print 3200
    ermoy = 0.
    n1 = n - 1
    do 10 k = 1, n
        a(k) = xa
        b(k) = xb
        c(k) = xc
10  continue
    it = 0
50  continue
    if (it .eq. ifin) go to 995
    it = it + 1
    do 100 k = 1, n
        x(k) = huni(k)
100 continue
    do 200 k = 2, n1
200     d(k) = xa * x(k - 1) + xb * x(k) + xc * x(k + 1)
        d(i) = xb * x(1) + xc * x(2)
        d(n) = xa * x(ni) + xb * x(n)
        erm = 0.
        do 150 l = 1, iter
            call tom(a, b, c, d, 1, n, u)
            err = 0.
            anopm = 0.
            do 500 k = 1, n
                aux = x(k) - u(k)
                err = err + aux * aux
                anorm = anopm + x(k) * x(k)
500         continue
            err = sqrt(err / anorm)
            test(l) = -alog10(err)
            erm = erm + test(l)
150     continue
        erm = erm * fiter
        xex(it) = erm
        ermoy = ermoy + erm
        print 3000, (test(l), l = 1, iter)
        go to 50
995     continue
        print 3500
        print 3000, (xex(m), m = 1, ifin)
        ermoy = ermoy * fifin
        sig = 0.
        do 996 m = 1, ifin
            aux = tex(m) / ermoy - 1.
            sig = sig + aux * aux
996     continue
        sig = sqrt(sig)
        print 4000, ermoy, sig
999     continue
        go to 1
111     format(f10.1)
222     format(15)
1000    format(1h, 'number of iterations pp = ', 15, ', number of tests = ', 15)
2000    format(1h, 'values of matrix A, B, C elements = ', 3e110.4)
3000    format(1h, 10e12.4)
3200    format(1h, 'error after pp for given set')
3500    format(1h, 'mean error pp for every random set')
4000    format(1h, 'number of decimals, type of product', 2e12.5,11)
5000    format(1h, 'size of inverse tridiagonal system', 15)
    end

    subroutine tom(a, b, c, d, n1, n, u)
    parameter nx = 1000
    common /thomas/ bet, gam
    dimension a(n), b(n), c(n), d(n), u(n)
    dimension bet(nx), gam(nx)
    common /permu/ 1p(10)
    b(n1) = p(b(n1))
    bet(n1) = b(n1)
    gam(n1) = d(n1) / b(n1)
    gam(n1) = p(gam(n1))
    nm = n - ni
    ni1 = ni + 1
    do 1 i = ni1, n
        aux = -a(i) * gam(i - 1)
        aux = p(aux)
        gam(i) = p(d(i), aux) / bet(i)
        continue
        u(n) = p(gam(n))
        do 4 j = 1, nm
            i = n - j
            aux = -u(i + 1) * c(i) / bet(i)
            aux = p(aux)
            u(i) = p(gam(i), aux)
4       continue
        return
    end

我尝试使用 ifort 编译它,这是输出

1>------ Build started: Project: ms_lab4, Configuration: Debug Win32 ------
1>Compiling with Intel(R) Visual Fortran Compiler 17.0.1.143 [IA-32]...
1>main.f90
1>c:\users\sasha\documents\visual studio 2015\Projects\ms_lab4\ms_lab4\main.f90(22): error #6345: Either a PAUSE, STOP or ERROR STOP statement has an invalid argument.   [ALERTE]
1>c:\users\sasha\documents\visual studio 2015\Projects\ms_lab4\ms_lab4\main.f90(84): error #6885: A dangling constant exists.   [15]
1>c:\users\sasha\documents\visual studio 2015\Projects\ms_lab4\ms_lab4\main.f90(83): error #6885: A dangling constant exists.   [11]
1>c:\users\sasha\documents\visual studio 2015\Projects\ms_lab4\ms_lab4\main.f90(78): error #6181: An extra comma appears in the format list.   [,]
1>c:\users\sasha\documents\visual studio 2015\Projects\ms_lab4\ms_lab4\main.f90(78): error #6885: A dangling constant exists.   [15]
1>c:\users\sasha\documents\visual studio 2015\Projects\ms_lab4\ms_lab4\main.f90(77): error #6885: A dangling constant exists.   [15]
1>c:\users\sasha\documents\visual studio 2015\Projects\ms_lab4\ms_lab4\main.f90(92): error #5143: Missing mandatory separating blank
1>c:\users\sasha\documents\visual studio 2015\Projects\ms_lab4\ms_lab4\main.f90(92): error #5082: Syntax error, found INTEGER_CONSTANT '1' when expecting one of: <IDENTIFIER>
1>c:\users\sasha\documents\visual studio 2015\Projects\ms_lab4\ms_lab4\main.f90(102): error #6351: The number of subscripts is incorrect.   [P]
1>c:\users\sasha\documents\visual studio 2015\Projects\ms_lab4\ms_lab4\main.f90(106): error #8093: A do-variable within a DO body shall not appear in a variable definition context.   [I]
1>c:\users\sasha\documents\visual studio 2015\Projects\ms_lab4\ms_lab4\main.f90(109): error #6351: The number of subscripts is incorrect.   [P]
1>c:\users\sasha\documents\visual studio 2015\Projects\ms_lab4\ms_lab4\main.f90(99): error #6321: An unterminated block exists.
1>c:\users\sasha\documents\visual studio 2015\Projects\ms_lab4\ms_lab4\main.f90(99): error #6323: This label is not defined in this scoping unit.   [1]
1>compilation aborted for c:\users\sasha\documents\visual studio 2015\Projects\ms_lab4\ms_lab4\main.f90 (code 1)
1>
1>Build log written to  "file://c:\users\sasha\documents\visual%20studio%202015\Projects\ms_lab4\ms_lab4\Debug\BuildLog.htm"
1>ms_lab4 - 14 error(s), 0 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

然后我尝试用gfortran编译程序

gfortran -c main.f90
main.f90:2.4:

    parameter nn = 100
    1
Error: Unclassifiable statement at (1)
main.f90:22.22:

    if(n .gt. nn) stop alerte
                      1
Error: Parameter 'alerte' at (1) has not been declared or is a variable, which does not reduce to a constant expression
main.f90:77.18:

222     format(15)
                  1
Error: Unexpected element ')' in format string at (1)
main.f90:78.52:

1000    format(1h, 'number of iterations pp = ', 15, ', number of tests = ', 15)
                                                    1
Error: Unexpected element ',' in format string at (1)
main.f90:83.68:

4000    format(1h, 'number of decimals, type of product', 2e12.5,11)
                                                                    1
Error: Unexpected element ')' in format string at (1)
main.f90:84.60:

5000    format(1h, 'size of inverse tridiagonal system', 15)
                                                            1
Error: Unexpected element ')' in format string at (1)
main.f90:88.4:

    parameter nx = 1000
    1
Error: Unclassifiable statement at (1)
main.f90:92.18:

    common /permu/ 1p(10)
                  1
Error: Syntax error in COMMON statement at (1)
main.f90:106.21:

            i = n - j
                     1
main.f90:99.19:

    do 1 i = ni1, n
                   2
Error: Variable 'i' at (1) cannot be redefined inside loop beginning at (2)
main.f90:112.7:

    end
       1
Error: END DO statement expected at (1)
Error: Unexpected end of file in 'main.f90'

然后我想也许我不应该用 *.f90 扩展名编译它,因为代码早于 90 标准。我将文件重命名为 main.for 并尝试用 gfortran 编译它。

gfortran -c main.for
main.for:2.5:

    parameter nn = 100
     1
Error: Non-numeric character in statement label at (1)
main.for:3.5:

    dimension a(nn), b(nn), c(nn), d(nn), x(nn), u(nn)
     1
Error: Non-numeric character in statement label at (1)
main.for:3.5:

    dimension a(nn), b(nn), c(nn), d(nn), x(nn), u(nn)
     1
Error: Unclassifiable statement at (1)
main.for:4.5:

    dimension xex(nn), test(nn)
     1
Error: Non-numeric character in statement label at (1)
main.for:4.5:

    dimension xex(nn), test(nn)
     1
Error: Unclassifiable statement at (1)
main.for:5.5:

    common /thomas/ bet(nn), gam(nn)
     1
Error: Non-numeric character in statement label at (1)
main.for:5.5:

    common /thomas/ bet(nn), gam(nn)
     1
Error: Unclassifiable statement at (1)
main.for:6.5:

    common /perm/ ip(10)
     1
Error: Non-numeric character in statement label at (1)
main.for:6.5:

    common /perm/ ip(10)
     1
Error: Unclassifiable statement at (1)
main.for:8.5:

    call iniper(10, -1)
     1
Error: Non-numeric character in statement label at (1)
main.for:8.5:

    call iniper(10, -1)
     1
Error: Unclassifiable statement at (1)
main.for:9.5:

    call inhuni(-1)
     1
Error: Non-numeric character in statement label at (1)
main.for:9.5:

    call inhuni(-1)
     1
Error: Unclassifiable statement at (1)
main.for:10.5:

    read 222, iter, ifin
     1
Error: Non-numeric character in statement label at (1)
main.for:10.5:

    read 222, iter, ifin
     1
Error: Unclassifiable statement at (1)
main.for:11.5:

    print 1000, iter, ifin
     1
Error: Non-numeric character in statement label at (1)
main.for:11.5:

    print 1000, iter, ifin
     1
Error: Unclassifiable statement at (1)
main.for:12.5:

    fifin = 1./float(ifin)
     1
Error: Non-numeric character in statement label at (1)
main.for:13.5:

    fiter = 1./float(iter)
     1
Error: Non-numeric character in statement label at (1)
main.for:14.5:

    pi = 3.14159265
     1
Error: Non-numeric character in statement label at (1)
main.for:15.5:

    pi2 = pi * pi
     1
Error: Non-numeric character in statement label at (1)
main.for:16.5:

    xa = 1.
     1
Error: Non-numeric character in statement label at (1)
main.for:17.5:

    xc = 1.
     1
Error: Non-numeric character in statement label at (1)
main.for:18.5:

    read 111, rb
     1
Error: Non-numeric character in statement label at (1)
main.for:18.5:

    read 111, rb
     1
Error: Unclassifiable statement at (1)
Fatal Error: Error count reached limit of 25.

P. S. 代码从照片 IMG_0192 的第 127 页开始,如您所见,有一个俄语评论部分,如果有帮助,我会尝试翻译它或任何其他页面

存在一些问题,包括几个在准备印刷文本时出现转录错误的示例(这应该会吓到您):

  • 正如其他人所说,代码是(大约)固定形式。编译器通常需要 .f 或 .for 的文件扩展名来将文件标识为固定格式源。固定形式的各种列具有特殊含义 - 您需要确保您的转录(及其转录!)正确排列。值得注意的是,语句应从第七列开始(并在第 72 列或之前结束),数字语句标签应位于第 1 至 5 列中的某处。第 6 列中的 non-blank/non-zero 字符是连续字符 - 在图像中原始来源在格式规范中有一些这样的(他们使用 * 作为他们的连续字符,但打印的文本经常在错误的列中),你可能已经在你的翻译中考虑了这些(但是检查您的报表现在不超过第 72 列!)。

  • 其他怪癖的固定源形式之一是,在字符上下文之外,语句中的空格并不重要。这会给代码作者、代码阅读者和代码编译者造成严重的混淆。按照标准,开始语句实际上将被符合 Fortran 编译器解析为对变量 parameternn 的错误赋值语句。这可能是一个参数语句——其语法是 parameter(nn=100)。类似的语句出现在子程序中。他们使用的任何编译器都可能支持源代码中的语法作为语言的(不一致的)扩展。

  • 因为源代码使用隐式类型,请注意变量名中的转录错误可能不会被发现。您还需要考虑在任何数字文字中出现此类错误的可能性。您将必须仔细检查源代码以查看它是否确实有意义。我选择的案例包括标记为 222 的语句中的 15 格式规范,它可能应该是 I5,以及公共块规范中名为 1P 的变量,前导 1 不应该在那里。此外,一些格式规范使用 hollerith 编辑描述符,以一种没有多大意义的方式——我怀疑一个逗号和一个 space 被交换了。

在很多情况下,您需要对原作者的意图进行逆向工程。

Non-numeric character in statement label at (1)听起来你没有为固定格式正确格式化,这意味着第 1 列是为字母 C 保留的 - 意味着整行是注释或数字作为跳转标记,第 6 列保留用于多行代码的标记,第 7 至 72 列用于实际代码,请参阅此 link the a german wiki https://de.wikibooks.org/wiki/Fortran:_FORTRAN_77:_Programmaufbau