【问题标题】:How to read a mixed text file and extract numbers only如何读取混合文本文件并仅提取数字
【发布时间】:2016-08-12 08:34:57
【问题描述】:

我需要读取我的一个模拟器的输出并存储这些值。文件名为forces.dat,包含类似以下内容:

# Forces     
# CofR       : (4.750000e-01 3.500000e-02 2.000000e-02)
# Time       forces(pressure viscous porous) moment(pressure viscous porous)
2.633022e-02    ((6.268858e-02 -1.468850e+01 1.542745e-20) (1.000906e-03 8.405854e-06 -5.657665e-17) (0.000000e+00 0.000000e+00 0.000000e+00)) ((-8.779466e-18 8.442993e-19 -3.225599e-03) (-2.082489e-18 4.435609e-18 -1.572485e-03) (0.000000e+00 0.000000e+00 0.000000e+00))
8.095238e-02    ((1.781333e-01 -1.468455e+01 -3.545427e-19) (2.362118e-03  2.014609e-05 1.691584e-16) (0.000000e+00 0.000000e+00 0.000000e+00))  ((-3.344781e-18 -5.448339e-19 2.227502e-02) (5.092628e-18 -3.538718e-18  -1.203074e-03) (0.000000e+00 0.000000e+00 0.000000e+00))
1.600000e-01    ((3.204471e-01 -1.467482e+01 -4.599174e-18) (6.936764e-03 1.303800e-04 4.836650e-17) (0.000000e+00 0.000000e+00 0.000000e+00)) ((-1.123589e-17 -4.344967e-19 5.591623e-02) (1.532415e-18 -1.345592e-18  -9.550750e-04) (0.000000e+00 0.000000e+00 0.000000e+00))

我想知道我应该如何编写一个 Fortran 子程序来忽略前 3 行,然后读取下一行的数量,然后读取每行的值。

【问题讨论】:

    标签: fortran stringreader


    【解决方案1】:

    您可以使用这个 sn-p 来跟踪行号。根据您的要求和文件的性质,您可以获取各行的值并执行所需的操作。

    string CurrentLine; 
    int LastLineNumber;   
    void NextLine() 
    {
    // using will make sure the file is closed
    using(System.IO.StreamReader file = new System.IO.StreamReader ("c:\\forces.dat"))
    {
        // Skip lines
        for (int i=0;i<LastLineNumber;++i)
            file.ReadLine();
    
        // Store your line
        CurrentLine = file.ReadLine();
        LastLineNumber++;
    }
    }
    

    在上面的代码中,在for 循环中,您可以根据要读取的行放入文件处理逻辑。

    【讨论】:

    • 谢谢劳拉。不是C代码吗?我现在在我的程序中需要一个 fortran 代码。
    • 你没有提到fortran。也许你也可以用 fortran 应用相同的逻辑
    【解决方案2】:

    虽然我认为通过一些命令行工具(例如sed -e 's/(/ /g' -e 's/)/ /g' input.dat)对文件进行预处理更容易,但我们也可以直接使用Fortran,将每一行读入一个长字符串并删除所有不必要的括号:

    program main
        implicit none
        integer, parameter :: mxline = 5000  !! choose appropriately
        integer i, ios, finp, nl
        character(500) str
        real, save :: time( mxline )
        real, dimension( 3, mxline ), save :: &
                frc_pres, frc_visc, frc_poro, &
                mom_pres, mom_visc, mom_poro
    
        finp = 10
        open( finp, file="input.dat", status="old" )
    
        nl = 0
        do
            read( finp, "(a)", iostat=ios ) str
            if ( ios /= 0 ) exit
            str = trim( adjustL( str ) )
    
            !! Skip comment or blank lines.
            if ( str(1:1) == "#" .or. str == "" ) cycle
    
            !! Replace parentheses with space.
            do i = 1, len_trim( str )
                if ( str(i:i) == "(" .or. str(i:i) == ")" ) str(i:i) = " "
            enddo
    
            !! Read data from the string.
            nl = nl + 1
            read( str, * ) time( nl ), &
                           frc_pres( :, nl ), frc_visc( :, nl ), frc_poro( :, nl ), &
                           mom_pres( :, nl ), mom_visc( :, nl ), mom_poro( :, nl )
        enddo
    
        close( finp )
    
        !! Check.
        do i = 1, nl
            print *
            print *, "time = ", time( i )
            print *, "frc_pres = ", frc_pres( :, i )
            print *, "frc_visc = ", frc_visc( :, i )
            print *, "frc_poro = ", frc_poro( :, i )
            print *, "mom_pres = ", mom_pres( :, i )
            print *, "mom_visc = ", mom_visc( :, i )
            print *, "mom_poro = ", mom_poro( :, i )
        enddo
    
    end program
    

    如果数据值可能变得非常大(例如 1.0e100),请考虑使用双精度实数,以免失去必要的精度。

    【讨论】:

    • 感谢 roygvib。它工作完美。虽然我写了另一个程序,但这个程序要快得多。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-14
    • 1970-01-01
    • 1970-01-01
    • 2020-07-07
    • 2013-08-19
    相关资源
    最近更新 更多