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

How to overprint in a console application?

dboggs
New Contributor I
3,561 Views

I want my console application to display a varying number at the same location in the current output line, i.e. overprint it. Example:

DO I = 1, n
     ! do something
     WRITE (*, '(A, I3)') 'Loop count = ', n
END DO

IOW I don't want each loop count report to create a new line (thus scrolling out of the window when n is large)--I want it to keep updating the same line. I know how to do this using Quickwin or API routines, but I desire standard Fortran.

Once upon a time I could accomplish this using carriage control: the output string would be '+Loop count = ', n. But this awkwardly requires the compiler switch '/ccdefault:fortran'. Worse, I understand that carriage control has been eliminated from standard Fortran.

So, how can I do this now?

0 Kudos
23 Replies
reidar
New User
2,987 Views

If you just try:

WRITE (*, '(\,A, I3)') 'Loop count = ', n

Or check documentation ->FORMAT

 

0 Kudos
mecej4
Honored Contributor III
2,987 Views

Try this:

program overwrite
implicit none
integer :: i,j 
character :: bsp = char(8)
!
write(*,10,advance='no')10000
do i=10001,99999
   write(*,20,advance='no')(bsp,j=1,5),i
end do
10 format('Counter: ',I5)
20 format(5A1,I5)
end program

 

0 Kudos
Steven_L_Intel1
Employee
2,987 Views

You could also open the unit with CARRIAGECONTROL='FORTRAN', but you're right that Fortran carriage control is not part of the current standard.  mecej4's approach will generally work, though. If you don't require keeping the text at the beginning you could output a single CR (char(13)). 

 

0 Kudos
dboggs
New Contributor I
2,987 Views

Thanks for these suggestions.

reidar: This doesn't do what I want. the backslash simply causes the output to continue on the same line without a CR/LF; the line simply grows longer and longer.

mecej4: This "sort of" works, and the backspace character is a good idea. However, with your code as written the output does not appear until the program completes. If I replace "advance='no'" with "\" or "$" (the older styles of doing the same thing) then it works OK, i.e. the output line is actually displayed each time through the loop. I do not understand this, I always thought that backslash editing, dollar editing, and advance=no were equivalent. I have tried several variations on these formats and conclude they are not. (Perhaps there is some obscure issue lingering in my test program?)

Here's my code snipped that works:

WRITE (*, '(A, $)') ' Loop count = '
bsp = CHAR (8)
DO i = 1, n
     WRITE (*, '(3A1, I3, $)') (bsp, j=1,3), i
END DO
! Note that constants '3' must agree in number and be sufficiently large to accommodate the size of i

So, I am still faced with resorting to non-standard IVF extensions to solve this problem. 

0 Kudos
Steven_L_Intel1
Employee
2,987 Views

Which compiler version are you using? I ran mecej4's code and it definitely updated while the program was running. Several versions ago it might not have.

An alternative would be to use nonadvancing output to create a sort of "progress bar".

0 Kudos
dboggs
New Contributor I
2,987 Views

I have two computers. One uses 2013 sp1.3.202. One uses 2011.11.344.

The setting ADVANCE='NO' doesn't work correctly on either one--the output doesn't appear until a subsequent write to the window occurs. A correct result appears on the final screen, but it is no good for real-time tracking. 

0 Kudos
LRaim
New Contributor I
2,987 Views

Try by inserting a FLUSH statement after the WRITE statement.

0 Kudos
dboggs
New Contributor I
2,987 Views

A good suggestion, but it doesn't help.

Moreover, it's a little awkward. This being a console application, I have all the WRITE's going to unit *. FLUSH () requires a unit argument, it doesn't accept FLUSH (*). I tried opening a window to unit 1 and directing all of the writing to that. The program runs the same and appears the same as the original version using unit (*). Then, adding FLUSH (1) was observed to have no effect.

0 Kudos
mecej4
Honored Contributor III
2,987 Views

Are you using something other than the default buffering on output to the console? Is the counter display being done on the standard command line console or in a Windows program?

The program in #3 works even with CVF6.6 and Gfortran 4.9.

0 Kudos
reidar
New User
2,987 Views

I checked some old stuff, what used to work with CVF was a "+" sign in column 1, so you should try:

  WRITE (*, '('+',A, I3)') 'Loop count = ', n

0 Kudos
Arjen_Markus
Honored Contributor II
2,987 Views

I think that requires cooperation from the console/DOS-box: it is an ancient type of carriage control, dating from the time of printers with endless papersheets.It may or may not still work - you simply have no way of ensuring it just from the Fortran program.

0 Kudos
Steven_L_Intel1
Employee
2,987 Views

No, that simply requires opening the file with CARRIAGECONTROL='FORTRAN'. Even in CVF that was not the default.

0 Kudos
dboggs
New Contributor I
2,987 Views

The solution based on carriage control has already been covered in this thread, starting with the very first message. It remains the most convenient way to do it. The complaint is that it was removed from the standard (in 2003) and hence only works through sympathisers of compilers (like Intel) who continue to offer it through extensions. In Intel's case, that would be using a non-standard compiler switch or a non-standard file open option, both as described above.

In the past, when the standards people removed a feature, a work-around or modern replacement was described. Not so in this case. It is awkward to do using strictly standard features. The feature appears to have been removed because of the demise of line printers. I think this was a bad assumption, that "carriage control" was not useful for anything else.

0 Kudos
jimdempseyatthecove
Honored Contributor III
2,987 Views

In kernel32.f90 you will find SetConsoleCursorPosition and GetConsoleScreenBufferInfo.

You might want to write generic wrappers, perhaps GOTOXY and WHEREXY that use these functions on Windows, and uses similar functions on Linux or other operating system.

Jim Dempsey

0 Kudos
mecej4
Honored Contributor III
2,987 Views

If you have a console driver that supports ANSI cursor positioning sequences, such as the one that comes with Cygwin+Gfortran on Windows, or one of the many console programs such as Konsole on Linus, you can try the following:

program overwrite
implicit none
integer :: i,j
character :: esc = char(27)
!
write(*,10,advance='no') esc,10000
do i=10001,100000
   write(*,20,advance='no') esc,i
end do
10 format(A1,'[13;30HCounter : ',I6)
20 format(A1,'[13;40H',I6)

end program

 

0 Kudos
nichols__john
Beginner
2,987 Views

https://github.com/adoxa/ansicon

It appears this is a good method

0 Kudos
Steven_L_Intel1
Employee
2,987 Views

I'm unsure of that - isn't this a separate program you have to load? 

0 Kudos
nichols__john
Beginner
2,987 Views

Yes it is - it is one method that does not look that bad -- there are no good solutions.

It is listed as the currently preferred solution at a number of major help sites and then you run your program in the window.

 

0 Kudos
reidar
New User
2,987 Views

My proposal #11 works well if you set project -> Properties ->Compability -> VMS = Yes.

 

 

integer i,j,n

character*1 bsp

 

n=1000

 

WRITE (*, '(A)') ' Loop count = '

WRITE (*, '(A)') ' '

 

bsp = CHAR (8)

DO i = 1, n

! WRITE (*, '(3A1, I3, $)') (bsp, j=1,3), i

WRITE (*, "('+',3A1, I4)") (bsp, j=1,3), i

END DO

 

pause

end

0 Kudos
dboggs
New Contributor I
2,851 Views

Reidar, thanks for the continued attention but as mentioned several times above I reject your solution because it is not standard Fortran. The whole point of this thread is that I know that using carriage control ('+' in column 1) is a good way to perform the overstrike--and a damn good way at that--I was requesting a way that conforms to the standard. I have been using the "+" method for many, many years. But they have now removed it from the standard without providing a replacement or even discussing a reasonable workaround. Such a discussion is what I was looking for.

The many responses kindly provided by several users address that discussion. I conclude that there is not a good standard way to do it.

0 Kudos
Reply