標籤:
一. Fortran 字串與 C 字串的區別
Fortran的字串處理能力其實很弱,關於字串的文法還很落後。它與 C 字串最大的區別就是:Fortran字串是固定長度的,沒有 \0 結束符。另外,Fortran 也不區分字元和字串。即 ‘abc‘ 與 "abc" 是沒有差別的。
二. Fortran 字串的定義。
Fortran字串是固定長度的。因此,在聲明時,就必須指定長度。(如不指定,大多數編譯器認為是長度為 1 的字串)
聲明時,可以按照這些格式進行:
1 integer , parameter :: L = 202 character :: s1*20 = "fcode.cn"3 character*20 :: s2 = "fcode.cn"4 character(20) :: s3 = "fcode.cn"5 character( len = 20 ) :: s4 = "fcode.cn"6 character( len = L ) :: s5 = "fcode.cn"
目前,筆者不建議使用第2行和第3行的方式。第4行的方式還算湊合。建議最好是使用第5行的方式,第6行示範了長度可以使用 parameter 常數,這樣適合於需要大量定義相同長度的字串。
三. Fortran字串的長度問題
需要注意的是,字串的長度一旦確定了,就無法改變。這一點筆者也感到文法應該改進,很不方便。
例如上例。character( Len = 20 ) :: s4 = "fcode.cn" 儘管後面的值 "fcode.cn" 只有 8 個字元,但是定義了變數是 20 長度,所以,實際 s4 的內容為 "fcode.cn "(後面有12個空格)
如果我們要輸出或使用字串,往往需要去掉後面的空格,此時可使用 trim 函數。
write(*,*) trim(s4)
這樣,就只會輸出有內容的 8 個字元,後面的 12 個空格就不會輸出。
特別需要注意的是,s4 = trim(s4) 這樣的句子是沒有任何意義的。因為雖然這個式子的右側,trim(s4) 的結果是 8 個字元,但賦值給式子左側的字串,它依然是 20 長度。它等效於 s4 = "fcode.cn",所以 s4 的內容依然是 “fcode.cn ”(讀者可回去看上面的綠色文字)
這讓我們很犯難。因此,trim 語句必須出現在每一次使用這個字串的時候。
四. Fortran 字串的串連(append)
我們經常會掛靠字串,比如 "fcode.cn" 在後面掛靠一個 "/bbs",很多初學者就會使用這樣的代碼:
character( Len = 20 ) :: s4 = "fcode.cn"
s4 = s4 // "/bbs"
輸出以後,發現 s4 的內容依然沒有改變。並沒有變成期望中的 "fcode.cn/bbs"。究其原因,其實就是第三個問題導致的。我們來觀察上面的等式:s4 = s4 // "/bbs",等號左邊 s4 有 20 長度,等號右邊 s4 的 20 長度加上 "/bbs" 的 4 長度,一共 24 個長度。左邊20個長度根本容納不下右邊的24個長度,於是,s4 依然是 s4,後面掛靠的 "/bbs" 由於儲存不下而被丟棄。
正確的掛靠方式是: s4 = trim(s4) // "/bbs"
而反之,s4 = "http://" // s4 就不需要寫 trim,請讀者朋友自己思考為什嗎?
五. 字串的左靠右對齊(AdjustL,AdjustR)
我們經常會遇到這樣的問題,除了後面的空格外,有時候字串前面也有空格。例如 s4 = " FortranCoder ",單一的 trim 結果會是 " FortranCoder"。
此時我們就需要 AdjustL 函數,我們可以這樣寫: trim(AdjustL(s4)) , 或者 AdjustL(trim(s4)) 這兩者的順序無所謂,結果都是一樣的。
AdjustR 函數使用的情況非常少,通常不用。它可以把 " abc " 變為 " abc"
六. 字串與整型,實型的相互轉換
Fortran 的字串與整型實現轉換,是個很有意思的事情。它不像其他語言那樣,提供一個函數來進行。而使用 read 和 write 讀寫來實現。
看下面的例子:
1 Program www_fcode_cn 2 Implicit None 3 Real :: r 4 Integer :: i 5 Character( Len = 20 ) :: c 6 c = "3.1415926" 7 read( c , * ) r !// 將 字串c 轉換為實數 r 8 write( * , * ) r + 1.0 9 i = int( r - 2.0 ) !// 給 i 一個值10 write( c , ‘(i0)‘ ) i !// 把整型i 轉換為字串 c11 c = AdjustL(trim(c)) // "st"12 write( * , * ) Trim( c )13 End Program www_fcode_cn
這裡的第 7 行,看起來是一個 read 語句,它其實是轉換。意思是:從字串 c 中讀取 r 的值。讀者可以把此時的字串 c 想成是一個虛擬檔案。
這裡的第 10 行,看起來是一個 write 語句,其實它還是轉換。意思是:把 i 的值,寫入字串 c 中,讀者依然可以想象成 c 是一個虛擬檔案。
簡單的說,就是 read 和 write 語句,可以直接對字串進行操作。字串可以被認為是虛擬檔案,從字串中獲得數值,就是read;把值寫入到字串中,就是write。
七. 一個執行個體
這裡,我們列舉一個實際字串使用的例子。
假設現在有一個檔案,其內容如下:
// This is a sample file
// There may be some comment text
Time:13:23:42 RecordID:18 Weather:Sunny
Fcode.cn Date:2014-02-38
前兩行是注釋,而且有可能不是兩行,不確定有多少行。
然後是一些資料群組合在一起。我們需要找到 RecordID: 後面的數字,即,18。我們事先不能確定 RecordID 在第幾行的什麼位置裡。
找到之後,我們需要給它加上 2014,即,2014+18=2032。
最後我們開啟 File2031.dat 檔案,開始讀取其中的資料。
上面的一系列操作,如果不使用字串,恐怕會很難。下面我們來看看如何書寫代碼來完成。利用本文所提到的各種內容。
代碼中有一部分注釋,相信讀者朋友能夠理解
1 Program www_fcode_cn 2 Implicit None 3 Integer , parameter :: MAX_PATH = 512 4 Character( Len = MAX_PATH ) :: c 5 Character( Len = * ) , parameter :: STR_FIND = "RecordID:" 6 integer :: ID , i , iErr 7 Open( 12 , File = "fcode.txt" ) 8 Do 9 Read( 12 , ‘(a512)‘ , ioStat = iErr ) c !必須a512格式,否則遇到空格會終止10 if ( iErr /= 0 ) Exit !// 如果讀錯了,比如遇到檔案結束,則退出迴圈11 if ( c(1:2) == "//" ) cycle !// 如果讀取的是注釋行,則直接讀下一行12 i = index( c , STR_FIND ) !// 在 c 中搜尋 RecordID: 的位置13 if ( i > 0 ) then !// 如果找到14 i = i + Len(STR_FIND) !// 將位置移到RecordID:後面15 c = c(i:) !// 使得 c 的內容為 i 位置之後的內容,即放棄i位置之前的內容16 read( c , * ) ID !// 讀取 ID 編號17 write( c , * ) ID + 2014 !// ID 編號加上2014,再寫回c中18 c = "File" // Trim(AdjustL(c)) // ".dat" !組合成File2032.dat,注意trim19 write( * , * ) Trim( c ) !// 輸出看看對不對20 !// Open( 13 , File = Trim( c ) )21 Exit22 end if23 End Do24 Close( 12 )25 End Program www_fcode_cn
轉自:http://fcode.cn/guide-48-1.html
[轉載]:Fortran字串的故事