line continuation character is not working - fortran
I have been using fortran 77 for several months and line continuation character doesn't work sometimes.
if((b1(j).eq.0d0).and.(b3(j).ne.0d0))then
write(22,*) a1(j),a2(j),a3(j),a4(j),a5(j),a6(j),a7(j),a8(j),
& a9(j),a10(j),a11(j),a12(j),a13(j),a14(j),a15(j),
& b3(j),0.2
else if((b3(j).eq.0d0).and.(b1(j).ne.0d0))then
write(22,*) a1(j),a2(j),a3(j),a4(j),a5(j),a6(j),a7(j),
& a8(j),a9(j),a10(j),a11(j),a12(j),a13(j),
& a14(j),a15(j),b1(j),b2(j)
end if
This is the code and when I compile it, the compiler says that '&' is a invalid character. What I am really curious is that sometimes it works and sometimes it does not. Probably I have a basic misunderstanding in fortran syntax.
final.f:59:72: Error: Expected expression in WRITE statement at (1)
final.f:60:9:
& b3(j),0.2
1
Error: Invalid character in name at (1)
final.f:63:72: Error: Expected expression in WRITE statement at (1)
final.f:64:9:
& a14(j),a15(j),b1(j),b2(j)
1
Error: Invalid character in name at (1)
Anybody can help me?
parameter(m=813,n=616)
real*8 a5(m),a6(m),a7(m),a8(m),a9(m),a10(m),a11(m),a12(m),a13(m)
integer*8 a1(m),a2(m),a3(m),a4(m),p1(n)
real*8 p2(n),p3(n),p4(n),p5(n),p6(n),a14(m),a15(m)
real*8 b1(m),b2(m),b3(m)
character skip80*80
open(11,file='dist.dat')
open(12,file='mksa.dat')
open(13,file='mksb.dat')
open(14,file='mksc.dat')
open(15,file='mksi.dat')
open(22,file='ksaf.dat')
open(23,file='ksbf.dat')
open(24,file='kscf.dat')
open(25,file='ksif.dat')
read(12,*)skip80
do i=1,m
read(12,*) a1(i),a2(i),a3(i),a4(i),a5(i),a6(i),a7(i),
& a8(i),a9(i),a10(i),a11(i),a12(i),a13(i),a14(i),a15(i)
end do
do i=1,n
read(11,*) p1(i),p2(i),p3(i),p4(i),p5(i),p6(i)
end do
do j=1,m
do i=1,n
if(a1(j).eq.p1(i))then
b1(j)=p4(i)
b2(j)=p5(i)
b3(j)=p6(i)
end if
end do
if((b1(j).eq.0d0).and.(b3(j).ne.0d0))then
write(22,*) a1(j),a2(j),a3(j),a4(j),a5(j),a6(j),a7(j),a8(j)
& ,a9(j),a10(j),a11(j),a12(j),a13(j),a14(j),a15(j)
& ,b3(j),0.2
else if((b3(j).eq.0d0).and.(b1(j).ne.0d0))then
write(22,*) a1(j),a2(j),a3(j),a4(j),a5(j),a6(j),a7(j)
& ,a8(j),a9(j),a10(j),a11(j),a12(j),a13(j)
& ,a14(j),a15(j),b1(j),b2(j)
end if
end do
end
Related
problems with getting substrings from strings in FORTRAN [duplicate]
This question already has answers here: Extract substring of Fortran string array (3 answers) Extract a single character from a Fortran string (1 answer) Access character at specific index in a string in Fortran (1 answer) Closed 3 years ago. I would like to evaluate if the 3rd letter of variable myline is 'C' or not. I try this: program main implicit none type line integer :: count = 5 character(len=48) :: list = 'ABCDE' end type type(line) :: myline character(len=1) :: letter = 'C' write(*,*) myline%count, myline%list if(myline%list(3) == letter) then write(*,*) 'TRUE' else write(*,*) 'FALSE' end if end program But I get: $ /usr/local/bin/gfortran8 -mcmodel=medium -fcheck=all -Wl,-rpath=/usr/local/lib/gcc8 -o test test.f90 test.f90:15:15: if(myline%list(3) == letter) then 1 Error: Syntax error in IF-expression at (1) test.f90:17:5: else 1 Error: Unexpected ELSE statement at (1) test.f90:19:4: end if 1 Error: Expecting END PROGRAM statement at (1) I am using gfortran (gcc8) and the Fortran 90 standard.
In Fortran, a character substring reference always needs a start and end position. So what you want here is myline%list(3:3). You can omit the end position (retaining the colon), for example (3:), and that means the rest of the string. Similarly you can omit the start position and it means from the first character (:3). As a suggestion, letter would be better declared with the parameter attribute as it is a constant, but what you have would work.
Try to compare different types in old fortran
I'm using gfortran 7 (Ubuntu) to compile an old fortran code. I'm facing the follow error: MYOLDCODE.f90:864:13: if (star (i) .eq. ' ' .and.& 1 Error: Operands of comparison operator â.eq.â at (1) are REAL(4)/CHARACTER(1) I think I'm trying to compare a real number to a blank space char. I don't know why the original coder do this. He dead in 90's so I can only ask him when I go to same place he is now, but then it will be too late. Here are the code: DO I = 1,KJ ( some code ) WRITE(impre,7100,IOSTAT=IERRO) I,STAR(I),A2(I),B2(I),A3(I),AMPL(I),& &CIA(I),SITU(I),A4(I),A5(I),CIF(I) if (star (i) .eq. ' ' .and.& & ampl (i) .ne. 1.E20 .and.& & ampl (i) .ge. 0.5 .and.& & situ (i) .ne. 1.E20 ) then write (15,7777) a2(i), b2(i), a3(i), ampl(i), situ(i) end if 7777 format (a3,a4,f11.7,f8.2,f8.2) end do 7100 FORMAT (t25,I3,2X,A1,A3,A4,2X,F11.7,6(2X,F8.2) ) How can I compare star (i) .eq. ' ' ? I know nothing about fortran so please ask if you need more code/information
Removing whitespace in string
I have the following code: program main character (len=15) :: abc = "te st tex t" print *, trim(abc) end program main Which outputs: te st tex t I excepted all the whitespace to be removed but it wasn't. How can I remove all the whitespace from the string?
Trim will remove spaces only at the edges, not in the middle (this is common behaviour on almost all languages/libraries). If you want to remove all spaces in the string, you will have to create your own function to do this, iterating through the string. Ex.: program Test implicit none ! Variables character(len=200) :: string ! Body of Test string = 'Hello World 7 9' print *, string call StripSpaces (string) print *, string contains subroutine StripSpaces(string) character(len=*) :: string integer :: stringLen integer :: last, actual stringLen = len (string) last = 1 actual = 1 do while (actual < stringLen) if (string(last:last) == ' ') then actual = actual + 1 string(last:last) = string(actual:actual) string(actual:actual) = ' ' else last = last + 1 if (actual < last) & actual = last endif end do end subroutine end program Test This was tested on intel compiler, not on gfortran, but I think it will work.
I was able to do this using the variable string library described here ( http://schonfelder.co.uk/is1539-2-99.htm ). The source code link is found in the introduction section of the ISO document. Here is the code program Console1 use ISO_VARYING_STRING implicit none ! Body of Console1 character(LEN=50) :: text = 'Hello World John Mary ' character(LEN=50) :: res print *, trim(text) ! 'Hello World John Mary' res = REPLACE(text,' ','', every=.TRUE.) print *, trim(res) ! 'HelloWorldJohnMary' end program Console1
Here's a dirty, shameful way to eliminate the spaces. This is only likely to work if a compiler lays out a length-15 string in the same order and space as it would a 15-element array of characters. While this is likely to be true, and in my recent experience is true, it is not guaranteed to be so by the standard. That aside, this approach may be good enough. ! declarations CHARACTER (len=15) :: abc = "te st tex t" CHARACTER, DIMENSION(LEN(abc)) :: abc_array ! or CHARACTER, DIMENSION(:), ALLOCATABLE :: abc_array if your compiler supports ! automatic allocation ! transfer the string into an array of characters abc_array = TRANSFER(abc,abc_array) ! eliminate the spaces, and transfer back to the string abc = TRANSFER(PACK(abc_array,abc_array/=' '),abc) ! now all the spaces are at the end of abc so the following statement writes the ! string with no spaces WRITE(*,*) TRIM(abc) Use this approach at your own risk.
For those averse to TRANSFER perhaps a nice little recursive function would appeal. As written this depends on Fortran 2003's ability to automatically allocate character scalars, but it shouldn't be too hard to modify if your compiler doesn't support this feature yet. RECURSIVE FUNCTION stripper(string,ch) RESULT(stripped) CHARACTER(len=*), INTENT(in) :: string CHARACTER, INTENT(in) :: ch CHARACTER(:), ALLOCATABLE :: stripped IF (LEN(string)==1) THEN IF (string==ch) THEN stripped = '' ELSE stripped = string END IF ELSE IF (string(1:1)==ch) THEN stripped = stripper(string(2:),ch) ELSE stripped = string(1:1)//stripper(string(2:),ch) END IF END IF END FUNCTION stripper
You can try this: program test !erase blank space in a string !run over every character of the string and just take every non-blank in other variable. implicit none character (len=100) str1,str2 integer i str2='' !in this variable will be save non-blank spaces str1=' a b c de ' !Test string with blank spaces write(*,*)len_trim(str1), str1 do i=1,len(str1) if (str1(i:i).ne.' ')str2=trim(str2)//trim(str1(i:i)) end do write(*,*)len_trim(str2), str2 end
way Fortran handles empty spaces
I would like to have some clarifications about the way Fortran handles "empty" characters in strings. Let us assume we have this situation: program main implicit none test('AB') end program where function test(name) implicit none character(10) :: name character(3) :: cutname write(*,*) '-'//name//'-' ! Gives output "-AB -" ! Space has then been added at the end cutname(1:3) = name(1:3) write(*,*) '1-'//cutname//'-' ! Gives output "-AB -" ! It seems there is a space then at the end ! of cutname write(*,*) (cutname(1:2) == 'AB') ! Gives output T (true) write(*,*) (cutname(3:3) == ' ') ! Gives output F (false) write(*,*) (cutname == 'AB ') ! Gives output F (false) end function I am pretty curious about what is happening in this case. Thanks in advance.
Standard strings in Fortran are fixed length. If you don't use the entire string, they are padded on the end with blanks/spaces. I altered your example program to pass compiler checks of gfortran and ifort. Your function had no return, so better as a subroutine. The compilers noticed the inconsistency between the lengths of the actual and dummy argument -- because I put the procedure into a module and useed it so that the compiler could check argument consistency. They complain about passing a length 2 string to a length 10 string. How are the remaining characters supposed to be defined? module test_mod contains subroutine test(name) implicit none character(10) :: name character(3) :: cutname write(*,*) '-'//name//'-' ! Gives output "-AB -" ! Space has then been added at the end cutname(1:3) = name(1:3) write(*,*) '1-'//cutname//'-' ! Gives output "-AB -" ! It seems there is a space then at the end ! of cutname write(*,*) (cutname(1:2) == 'AB') ! Gives output T (true) write(*,*) (cutname(3:3) == ' ') ! Gives output F (false) write(*,*) (cutname == 'AB ') ! Gives output F (false) end subroutine test end module test_mod program main use test_mod implicit none call test('AB ') end program When I run this version, the outputs are T, T and T, which is what I expect. EDIT: I suggest using full warning and error checking options of your compiler. That is how I quickly found the issues with the example. With gfortran: -O2 -fimplicit-none -Wall -Wline-truncation -Wcharacter-truncation -Wsurprising -Waliasing -Wimplicit-interface -Wunused-parameter -fwhole-file -fcheck=all -std=f2008 -pedantic -fbacktrace. A string assignment statement doesn't require the two sides to have the same lengths. If the RHS is shorter than the string variable on the LHS, it will get padded on the end with blanks. Here, the arguments should be consistent, including in length.
FORTRAN how to skip a line while reading lines in a DO loop?
I'm trying to read a file line by line using a DO and read to manipulate individual lines. However, I'm trying to skip a line wherever I see something I don't want. Here's what I have so far: DO J=1,10000 READ(1,'(A150)') ROW IF (J==A(1)+1 .AND. ROW(17:17)=='|') THEN WRITE(2, '(A)') ROW(1:12) // ROW(15:150) ELSEIF (J>A(1) .AND. J<A(2) .AND. ROW(1:1)=='#') THEN ! Here's where I need to skip J and go onto J+1 and then continue the DO loop from there END IF END DO How can I do it?
Use CYCLE: DO J=1,10000 READ(1,'(A150)') ROW IF ((J==A(1)+1) .AND. (ROW(17:17).EQ.'|')) THEN WRITE(2, '(A)') ROW(1:12) // ROW(15:150) ELSEIF (J.GT.A(1) .AND. J.LT.A(2) .AND. ROW(1:1)=='#') THEN CYCLE END IF ! More statements here END DO As Hristo pointed out, CYCLE is only necessary if you have more statements following the IF ... END IF.