Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
28384 討論

Writing to standard output with advance = 'no'

Garcia__Javier
初學者
2,618 檢視

This short program works as intended if I compile with gfortran and the option -fbackslash, i.e., it shows a line that states the step number I'm currently in and it updates it every second.

program test                                                                  
    use iso_fortran_env, only: output_unit                                    
                                                                              
    character(len = 24) :: msg                                                
                                                                              
    n = 10                                                                    
    write(msg, '(A, I3, A, I3)') 'Step', 1, ' out of', n                      
    write(output_unit, '(A)', advance = 'no') trim(msg)                       
    call sleep(1)                                                             
                                                                              
    do i = 2, 10                                                              
        write(output_unit, '(A)', advance = 'no') repeat('\b', len(trim(msg)))
        write(output_unit, '(A, I3, A, I3)', advance = 'no')  'Step', i, ' out of', n               
        call sleep(1)                                                         
    enddo                                                                     
end program test

Instead, if I compile with ifort (with the option -assume bscc), it doesn't show anything until the program finishes. How can I get the same behavior I get when compiling with gfortran?

Thanks!

0 積分
4 回應
Steve_Lionel
榮譽貢獻者 III
2,618 檢視

In order to make the output available, you need to insert a FLUSH statement, gfortran and Intel Fortran behave differently here, both are correct.

So a modified program (that doesn't require a special compile switch) would be:

program test                                                                  
    use iso_fortran_env, only: output_unit  
    use iso_c_binding, only: c_backspace
                                                                              
    character(len = 24) :: msg
                                                                             
    n = 10                                                                    
    write(msg, '(A, I3, A, I3)') 'Step', 1, ' out of', n                      
    write(output_unit, '(A)', advance = 'no') trim(msg) 
    flush(output_unit)
    call sleep(1)                                                             
                                                                              
    do i = 2, 10                                                              
        write(output_unit, '(A)', advance = 'no') repeat(c_backspace, len_trim(msg))
        write(output_unit, '(A, I3, A, I3)', advance = 'no')  'Step', i, ' out of', n      
        flush(output_unit)
        call sleep(1)                                                         
    enddo                                                                     
end program test

This partially works, in that the output appears each iteration. But the backspaces never get written to the output unit, where I think they should. To fix this, add a second flush after the first write, like so:

program test                                                                  
    use iso_fortran_env, only: output_unit  
    use iso_c_binding, only: c_backspace
                                                                              
    character(len = 24) :: msg
                                                                             
    n = 10                                                                    
    write(msg, '(A, I3, A, I3)') 'Step', 1, ' out of', n                      
    write(output_unit, '(A)', advance = 'no') trim(msg) 
    flush(output_unit)
    call sleep(1)                                                             
                                                                              
    do i = 2, 10                                                              
        write(output_unit, '(A)', advance = 'no') repeat(c_backspace, len_trim(msg))
        flush(output_unit)
        write(output_unit, '(A, I3, A, I3)', advance = 'no')  'Step', i, ' out of', n      
        flush(output_unit)
        call sleep(1)                                                         
    enddo                                                                     
end program test

I think it's a bug that the flush after writing the backspaces is needed - I'll report that to Intel. However, this version should also work in gfortran.

Garcia__Javier
初學者
2,618 檢視

This works perfectly for me, thanks Dr. Fortran!

Steve_Lionel
榮譽貢獻者 III
2,618 檢視

Issue 04436367 has been submitted on this. It is reproducible with this small program:

program test
implicit none

write (6,'(A)', advance='NO') 'ABCDE'
!flush(6)
write (6,'(A)', advance='NO') 'FGHIJ'
flush(6)
end

 

Steve_Lionel
榮譽貢獻者 III
2,619 檢視

Bug confirmed by Intel support, sent on to development for a fix.

回覆