[Fortran 2018] 포트란의 문법적 특징과 포트란 프로그램의 구조
program quadratic_equation implicit none real :: a, b, c ! coefficients real :: d ! discriminant ! read a, b, c read(*, *) a, b, c ! calculate discriminant d = b**2 - 4*a*c if (d > 0) then ! two distinct solutions write(*, *) (-b + sqrt(d)) / (2*a), & (-b - sqrt(d)) / (2*a) else if (d == 0) then ! one solution write(*, *) -b / (2*a) else ! no real solution write(*, *) 'no real solution' end if end program quadratic_equation
포트란의 문법적 특징
포트란이 꽤나 옛날 언어다 보니 다른 언어와 구분되는 문법적 특징이 많습니다.
대소문자 구분
옛날 컴퓨터(1950년대…)에는 대문자만 있었기 때문에 포트란도 자연스럽게 대문자만 지원했습니다. 포트란 90으로 넘어오면서 소문자도 쓸 수 있게 바뀌었지만, 하위 호환성을 위해 대소문자를 구분하지 않습니다. (물론 문자열은 예외입니다.)
일부 키워드의 띄어쓰기 무시
포트란은 원래 띄어쓰기도 무시했습니다. 포트란 77은 띄어쓰기를 다 삭제해도 정상적으로 돌아갔죠. 그래서 변수나 함수 이름에 띄어쓰기를 넣는 상상도 못 할 일이 가능했습니다. 포트란 90에서는 사라졌지만 그 때의 흔적으로 여전히 단어 여러 개로 이루어진 몇몇 키워드는 띄어쓰기를 무시해도 됩니다.
block data
else where
end block data
end enum
end function
end module
end select
end type
in out
double precision
end associate
end critical
end file
end if
end procedure
end submodule
end where
select case
else if
end block
end do
end forall
end interface
end program
end subroutine
go to
select type
세미콜론
기본적으론 쓰지 않습니다만, 한 줄에 여러 문장(statement)을 욱여넣고 싶을 땐 문장을 세미콜론으로 구분합니다.
여러 줄에 걸친 문장
C/C++에서는 줄바꿈이 일반 공백과 똑같이 처리되어 의미를 가지지 않습니다. 반면에 파이썬의 경우 한 문장은 무조건 한 줄에만 적어야 하죠. 문장의 끝을 세미콜론이 아니라 줄바꿈으로 인식하기 때문에 그렇습니다. 포트란도 역시 세미콜론을 쓰지 않기 때문에 파이썬처럼 한 문장은 한 줄에만 적어야 합니다. 문장이 길어서 여러 줄에 걸쳐 적고 싶다면 문장 마지막에 &
를 붙여서 다음 줄에서 이어짐을 표시해주어야 합니다. 가끔 그 다음 줄 이어지는 문장 제일 첫 머리에 한 번 더 &
를 붙이기도 하는데, 이건 선택 사항입니다.
레이블
C/C++ 프로그래밍을 하다 보면 레이블을 지정한 뒤 goto
문에서 해당 레이블로 점프하라고 지정하는 경우가 있습니다. 포트란에도 이런 레이블이 있지만 특이하게도 1부터 99,999까지의 정수만을 사용합니다. 이것 또한 포트란 77의 흔적입니다. 당연히 레이블 번호는 중복될 수 없으며 항상 문장이 있는 줄의 제일 처음에 와야 합니다.
주석
포트란의 주석은 !
로 시작합니다. 주석의 범위는 !
부터 그 줄의 끝까지입니다.
포트란 프로그램의 구조
포트란 프로그램은 크게 순서대로 선언 영역, 실행 영역, 종료 영역으로 나뉩니다.
선언 영역
program문
C에 main
함수가 있듯이 포트란에는 program
문이 있습니다. 모든 포트란 프로그램은 program
문에서 시작합니다. program
다음에는 프로그램의 이름이 옵니다. 이름은 변수명 규칙을 벗어나지 않는 선에서 마음대로 지을 수 있습니다. 변수명 규칙은 아래 변수의 선언에서 설명하겠습니다.
변수의 선언
변수 선언은 type :: name
과 같은 형식으로 선언됩니다. 포트란은 기본 타입으로 정수형(integer
), 실수형(real
및 double precision
), 문자(character
), 논리형(logical
), 복소수(complex
)를 지원하고 여기에 추가로 클래스를 만들어 쓸 수 있습니다. 변수의 이름은 변수명 규칙을 따라야 하는데, 상식적입니다.
- 변수 이름은 알파벳
a
–z
, 언더스코어_
, 숫자0
–9
만을 포함할 수 있습니다. - 변수 이름은 숫자로 시작할 수 없습니다.
- 변수 이름은 최대 63자입니다.
타입과 변수 이름 사이에 들어가는 :
두 개는 생략할 수 있으나 매우 권장하지 않습니다. 그리고 프로그램 이름과 변수 이름은 겹칠 수 없습니다. (나중에 설명할 함수의 이름도 마찬가지고요.)
implicit문
사실 포트란은 파이썬과 매트랩처럼 변수를 선언하지 않아도 되는 언어입니다. 따로 선언되지 않은 변수는 첫 글자에 따라 타입을 정하여 자동으로 선언됩니다. 기본적으로 첫 글자가 i
– n
인 변수는 정수형, 그 외는 실수형으로 정해집니다.
program implicit_test integer :: xyz abc = 0 ! 첫 글자가 a이므로 실수형으로 자동 선언 ijk = 0 ! 첫 글자가 i이므로 정수형으로 자동 선언 xyz = 0 ! 첫 글자가 x이지만 정수형으로 이미 선언됨 (실수형으로 자동 선언되지 않음) write(*, *) abc, ijk, xyz end program implicit_test
실행해보면 abc
는 실수형이라서 0.00000000
이, ijk
와 xyz
는 정수형이라서 0
이 출력됩니다.
이 첫 글자 규칙은 implicit
문을 써서 바꿀 수 있습니다. implicit
다음에 타입을 적고, 그 다음 괄호 속에 알파벳을 적으면 해당 알파벳으로 시작하는 변수들은 해당 타입으로 자동 선언됩니다. -
을 쓰면 일일이 적지 않고 범위로 나타낼 수 있습니다.
! 모든 변수가 정수형 implicit integer (a-z) ! u, v, w로 시작하면 복소수, c로 시작하면 문자 ! 나머지는 기본 설정을 따름 implicit complex (u, v, w) implicit character (c) ! 컴파일 에러: i-n에 대해 설정 중복 implicit real (a-n) implicit integer (i-z)
여기에 특수한 구문 하나가 추가됩니다. implicit none
은 자동 선언 자체를 꺼버립니다. 이때 모든 변수는 프로그래머가 명시적으로 선언해야 합니다. 자동 선언이 일으키는 혼란을 막기 위해 포트란 프로그래밍에서는 반드시 implicit none
을 사용할 것을 강력히 권장합니다.
실행 영역
그냥 열심히 계산하는 부분입니다.
종료 영역
end program문
포트란 프로그램은 프로그램 정의의 마지막 줄 end program
을 만나면 종료합니다. 이때 종료 상태(exit status)로 0이 반환됩니다. C/C++에서 main
함수의 닫는 중괄호와 같다고 보시면 됩니다. end program
뒤에 프로그램 이름을 적어도 되고 안 적어도 되는데 프로그램의 끝임을 명확하게 표시해주기 위해 적는 걸 추천합니다.
stop문
end program
에 도달하기 전에 프로그램을 끝내는 방법으로 stop
문이 있습니다. stop
뒤에는 메시지를 적을 수 있습니다. 메시지가 없으면 end program
과 동일하게 0을 반환하고 프로그램이 끝납니다. 메시지가 정수면 해당 정수를 반환하고 프로그램이 끝납니다. 메시지가 문자열이면 0을 반환하고 프로그램이 끝납니다. 메시지가 있다면 프로그램 종료 시 메시지가 콘솔에 출력됩니다.
error stop문 (Fortran 2008)
error stop
문은 단순히 프로그램을 종료하는 것이 아니라 의도적으로 런타임 에러를 띄웁니다. error stop
뒤에는 에러 메시지를 적을 수 있습니다.
혹시 이 문제 답변 가능하신가요 ???
1+2+3+4+……+10000까지 합을 계산하고, 1000항마다 중간결과를 인쇄하는 프로그램을 작성하시오
1000 =
2000 =
.
.
.
10000 =
부탁드리겠습니다 ㅠㅠㅠ
포트란 과제로 이 블로그에서 잘 배우고 있는데 이런 문제를 받아서 어떻게 풀어야 하는지 궁금해서 문의드렸습니다…
if (mod(k,1000).eq.0)