2016-02-02 12 views
5

Tôi muốn đọc trong một số chuỗi văn bản từ dòng lệnh sử dụng để chạy một chương trình. Tôi đang sử dụng chương trình con nội GET_COMMAND_ARGUMENT trong một chương trình mà về cơ bản là một cái gì đó như:Làm cách nào để lấy đối số dòng lệnh có độ dài không xác định trong Fortran?

program test 
character(len=100) :: argument 
call GET_COMMAND_ARGUMENT(1,argument) 
print*, argument 
end program test 

Vấn đề ở đây là tôi cảm thấy đó là một chút nguy hiểm để thiết lập chiều dài tối đa của chuỗi lúc biên dịch. Một số đối số thường là các tệp có đường dẫn của chúng, vì vậy chúng có thể rất dài. Một giải pháp liên quan đến việc thiết lập độ dài tĩnh đến 1000 âm thanh như một giải pháp xấu. không có

Là một cách thanh lịch hơn trong Fortran để xác định một chuỗi có thể chứa một chuỗi các ký tự có chiều dài chỉ được biết đến tại thời gian chạy?

Trả lời

4

Có thể sử dụng những gì được gọi là biến nhân vật hoãn dài. Đây không phải là của một chiều dài liên tục cố định và sử dụng của họ có thể được tìm thấy trong những câu hỏi như a related one about data input.

Tuy nhiên, ngay cả với một biến chiều dài thu nhập hoãn lại được sử dụng như (ví đây là cú pháp)

character(len=:), allocatable :: argument 
allocate(character(some_length) :: argument) ! For integer some_length 
call GET_COMMAND_ARGUMENT(1,argument) 
print*, argument 
end 

một vẫn phải lo lắng về những gì some_length nên. Nếu chúng ta chỉ chọn 100, chúng ta quay trở lại nơi chúng ta đang ở.

Chúng ta phải lo lắng về điều này bởi vì get_command_argument không lấy một đối số độ dài được trì hoãn và phân bổ nó theo chiều dài mong muốn. Đó là

character(len=:), allocatable :: argument 
call GET_COMMAND_ARGUMENT(1,argument) ! Will argument be allocated in the subroutine? 
print*, argument 
end 

cung cấp câu trả lời "không".

Đến, sau đó, để xử lý điều này, chúng tôi xem xét các đối số (tùy chọn) khác với get_command_argument. Đặc biệt, có một gọi length:

character(len=:), allocatable :: argument 
integer arglen 
call GET_COMMAND_ARGUMENT(1,length=arglen) 
allocate(character(arglen) :: argument) 
call GET_COMMAND_ARGUMENT(1,value=argument) 
print*, argument 
end 

Đương nhiên, người ta có thể tạo ra một chương trình con wrapper mà đã có một thu nhập hoãn lại biến nhân vật dài allocatable và đã làm tất cả những gì làm việc.

+0

Cách tiếp cận của bạn tốt hơn nhiều, bằng cách nào đó tôi đã quên đối số này. –

+0

Có lẽ cũng đáng chú ý rằng cách tiếp cận này cũng hoạt động cho 'get_environment_variable'. – francescalus

+0

Cảm ơn, đây là sự trợ giúp tuyệt vời và thực sự giải quyết được câu hỏi.Tôi chỉ có một câu hỏi nhỏ, tại sao cần thiết 'phân bổ' (ký tự (some_length) :: đối số) thay vì 'phân bổ đơn giản hơn (đối số (some_length))' – Onturenio

1

Tôi sẽ rời khỏi đây cho đầy đủ, nó có thể có ích cho ai đó, nhưng câu trả lời francescalus' là tốt hơn nhiều.

Về cơ bản, chỉ cần đọc nó với một số độ dài mặc định, hãy kiểm tra biến số STATUS và nếu biến đó không vừa, hãy thử lại.

Từ hướng dẫn gcc:

Nếu việc thu hồi tranh cãi không, STATUS là một số dương; nếu GIÁ TRỊ chứa một đối số dòng lệnh cắt ngắn, STATUS là -1; và nếu không thì STATUS bằng không.

Vì vậy:

character(len=:), allocatable :: argument 
integer :: stat, n 

n = 100 
allocate(character(n) :: argument) 

do 
    call GET_COMMAND_ARGUMENT(1,argument, status=stat) 
    if (stat>=0) exit 
    deallocate(argument) 
    n = n * 2 
    allocate(character(n) :: argument) 
end do 

if (stat>0) error... 

argument = trim(argument) 

print*, argument 
Các vấn đề liên quan