2014-12-27 2 views
0

문자열을 쓰는 루틴을 작성 중입니다. 어떤 인자가 있는지 확인하려면 해야합니까, 아니면 피할 수 있습니까?Fortran 선택적 인수

Subroutine writes & 
(     & 
q1, q2, q3, q4 & 
) 

Character (len=*), Intent(in) :: q1 
Character (len=*), Intent(in), Optional :: q2, q3, q4 

Character (len=65) :: s, fmt 

fmt = "(x,4(a,x))" 
Write (s,fmt) Trim (q1), Trim (q2), Trim (q3), Trim (q4) 
Write (*,*) Trim (s) 

End Subroutine writes 
+0

답변을 안내하기 위해 어떤 점에서 현재 상태를 확인하지 못하는 이유는 무엇이라고 생각하십니까? 'trim'은 선택적 인자를 취하지 않지만, [이전 답] (http://stackoverflow.com/a/27343054/3157076)에서와 같이 많이 래핑 할 수 있습니다. – francescalus

+0

래퍼가 도움이 될지 잘 모르겠습니다. 왜냐하면 새 함수를 정의하면 반환되는 문자열의 크기가 고정되어야하기 때문입니다. – Zeus

+0

'문자 (len = :), allocatable :: result'? – francescalus

답변

3

선택적 가짜 인수의 사용에 관한 규칙은 Fortran 2008 12.5.2.12에서 명확하게 제공됩니다. 질문에 주어진대로 모든 인수가 writes에 대한 호출에 존재하면 코드는 유효하며 결과는 예상대로입니다. 그러나이를 보장 할 수는 없으며 존재하지 않는 인수가 있으면 코드가 유효하지 않게됩니다.

특히, TRIM에 전달되지 않는 q2을 전달하면 (이는 선택적 인수를 사용하지 않습니다) 잘못된 것입니다.

이 문제를 해결하는 방법은 여러 가지가 있지만 모두 존재 여부를 확인하는 것이 포함됩니다. 당신은 Fortran Fallback code for optional string argument의 주장을 따를 수 있었지만 아래는 이전에 의견에 제시된 대안입니다.

은 인수가없는 경우 길이 제로의 문자 변수를 반환 선택적 인수 걸립니까 TRIM에 대한 대안을 만들 수 있으며, 예상 손질 변수가있는 경우 :

subroutine writes(q1, q2, q3, q4) 
    character(*), intent(in) :: q1, q2, q3, q4 
    optional q2, q3, q4 
    character(len=65) s 

    write(s, '(4(a,:,x))') TRIM(q1), MY_TRIM(q2), MY_TRIM(q3), MY_TRIM(q4) 
    print*, TRIM(s) 

    contains 
    function my_trim(str) 
     character(*), intent(in), optional :: str 
     character(:), allocatable :: my_trim 

     if (PRESENT(str)) then 
     my_trim = TRIM(str) 
     else 
     my_trim = '' 
     end if 

    end function 

    end subroutine 

자동 할당과 함께 결과에 지연 길이 문자 변수를 사용합니다 (ifort가 올바르게 컴파일하기 위해 필요한 컴파일러 플래그를 기억한다면).

마지막으로 공백이 두 개의 존재하지 않는 변수 (''//' '//'') 사이에 인쇄되지 않도록하려면 추가 작업이 필요합니다. 그러나 의견은 이것이 필요하지 않음을 나타냅니다.

+0

함수에서'my_trim'에'allocate'를 호출 할 필요가 없습니다. 나는해야한다고 생각했다. – Zeus

+0

필요는 없지만 원할 경우 (자동 할당 등을 피하기 위해) 위의 주석에서 Vladimir F가 제공 한 양식을 사용해야합니다. 각각의 경우에 대해 별도의 할당. – francescalus