2013-03-06 128 views
1

RPG中的另一件事我不知道如何做對:編寫字符串操作函數/過程。由於大部分時間RPG中的字符串具有固定的長度(至少在我們的程序中),也許更重要的是它們總是有限長度的,所以當我想寫一個過程時,我總是有點失落一般字符串操作。RPG中的多功能字符串操作程序

如何編寫一個程序來處理任意長度的字符串?有沒有問題,如果我做它的功能樣式(如在text = manip_str(text);)?如果我直接操縱參數(如manip_str(text);),它會以不同的長度工作嗎?

我會發布我自己的嘗試作爲答案,但也有一些問題,我不確定。你怎麼做,因爲我確定很多有這樣的任務一次或一千次。不同的方法很好,如果你提到這些方法的問題,最好。

在問你之前:(EBCDIC)字節字符串的問題與(UTF-16)unicode字符串一樣。但我可以生活兩次,每次一次。

+0

我們稱之爲固定長度字符串。即使可變長度的字符串也有有限的限制。如果您發現實際上擁有無限存儲的系統,請告訴我。 ;-) – WarrenT 2013-03-07 14:19:36

+0

@WarrenT當然,電腦中的一切都是有限的。但在RPG中,我必須決定聲明:該字符串不會超過x個字符。在其他語言(高,像Python或低像C),我只是使用我的變量,並不在乎,如果它是2個字符或1000000(或儘可能多我可以得到一塊MEM)。對我而言,這是一個區別。也許你也可以在RPG中使用指針,但它們並不像在C或C++中那樣自然。 – kratenko 2013-03-08 09:41:38

回答

3

大多數字符變量確實是固定的長度。其中意味着有限長度。定義爲50a的字符將總是正好包含50個字符。 Eval myChar ='A';將導致myChar包含50個字符:字母A後跟49個空格。這很無聊但很重要。

第二個無聊但重要的是要明白,調用者分配內存,而不是被調用者。如果調用者聲明瞭myChar 50a並且被調用者聲明瞭myParm 65535a,則調用者只初始化了50個字節的存儲空間。如果被調用者嘗試使用myParm超過第50個字節,則它正在處理狀態未知的存儲。正如他們所說,可能會出現不可預知的結果。

然後,這是您的問題的背景,有關處理字符變量的子程序的問題,其大小並不爲子程序預先知道。處理這個問題的經典方法是不僅要傳遞字符變量,還要傳遞其長度。 eval myProcedure(myChar:%len(myChar));這有點醜陋,它會強制每個調用者計算myChar的長度。如果子過程可以詢問傳入參數以查找調用者如何定義它,那肯定會很好。

IBM通過他們稱之爲Operational Descriptors的東西提供了這樣一個設施。通過操作描述符,調用者將關於字符參數的元數據傳遞給被調用者。通過CEEDOD API檢索。有一個使用CEEDOD here的例子。

基本上,子過程需要聲明它想要運行的描述:

dddeCheck   pr    n opdesc 
d test       20a const options(*varsize) 

主叫然後進行正常的期待調出該子過程:

if ddeCheck(mtel) = *on;    // 10 bytes 
... 
endif; 
if ddeCheck(mdate: *on) = *on;   // 6 bytes 
... 
endif; 

注意,調用者傳遞不同大小固定的長度變量到子過程。

的子過程需要使用CEEDOD詢問傳入的參數的長度:

 dddeCheck   pi    n opdesc 
    d test       20a const options(*varsize) 
... 
    dCEEDOD   pr 
    d parmNum      10i 0 const 
    d descType      10i 0 
    d dataType      10i 0 
    d descInfo1      10i 0 
    d descInfo2      10i 0 
    d parmLen      10i 0 
    d ec       12a options(*omit) 

    d parmNum   s    10i 0 
    d descType  s    10i 0 
    d dataType  s    10i 0 
    d descInfo1  s    10i 0 
    d descInfo2  s    10i 0 
    d parmLen   s    10i 0 
    d ec    s    12a 
... 
     CEEDOD (1: descType: dataType: descinfo1: descinfo2: parmlen: *omit); 

此時,parmlen包含呼叫者已經定義的傳入變量爲長度。現在,我們需要用這些信息來做些事情。如果我們用字符處理字符,我們需要做的是這樣的:

for i = 1 to parmLen; 
    char_test = %subst(test: i: 1); 
    ... 
endfor; 

如果我們處理一個字符串,我們需要做的是這樣的:

returnVar = %xlate(str_lc_letters_c: str_uc_letters_c: %subst(s: 1: parmLen)); 

的重要的是永遠不要引用輸入參數,除非引用由調用者定義的實際變量長度限定。這些預防措施僅適用於固定長度變量。編譯器已經知道變長字符變量的長度。

關於編譯器通過CONST將myFixed映射到myVarying的方式的主題,瞭解它是如何工作的。編譯器會將myFixed中的所有字節複製到MyVarying中 - 所有這些字節。如果myFixed爲10a,myVarying將變爲10個字節。如果myFixed是50a,myVarying將變爲50字節長。尾隨空格總是包含在內,因爲它們是每個固定長度字符變量的一部分。那些空白對於翻譯過程來說並不重要,它忽略了空格,但它們對於以字符串爲中心的過程可能很重要。在這種情況下,您需要使用操作描述符或執行如下操作:upperVary = str_us(%trimr(myFixed));

+0

感謝您將我引向'CEEDOD',我們將在未來使用我們的服務計劃。並解釋背景,太棒了!儘管如此,仍然不滿足於從程序返回字符串。我想我們會操縱參數,而我知道會發生什麼。 – kratenko 2013-03-13 14:53:13

+0

我錯過了......也許你可以問一個關於在角色扮演遊戲中返回角色價值的新問題......有什麼讓你感到困擾的具體例子? – 2013-03-13 15:39:56

0

我發現RPG中字符串傳遞的最靈活的方式是使用64k-varlength字符串並通過*varsize(它應該只發送字符串中傳遞的字節數,所以64k不應該是一個問題–我想我發現了某處由斯科特克萊門特建議)。下面我將如何編寫一個AZ只與upcase函數(因爲它是一個最基本的例子):

* typedefs: 
Dstr_string_t  S   65535A VARYING TEMPLATE 

* constants: 
Dstr_uc_letters_c C     'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 
Dstr_lc_letters_c C     'abcdefghijklmnopqrstuvwxyz' 

* prototype: 
Dstr_uc   PR     like(str_string_t)  
D s         like(str_string_t)  
D          options(*varsize) const 

* implementation: 
Pstr_uc   B     export     
D     PI     like(str_string_t)  
D s         like(str_string_t)  
D          options(*varsize) const 
/free               
    return %xlate(str_lc_letters_c:str_uc_letters_c:s);   
/end-free              
Pstr_uc   E 

現在有,在這裏關注我許多東西:

  • 難道還有一些問題與我通過這個固定長度的字符串?
  • 請問這是否「僅傳遞所需的字節數量」也適用於返回值?我不希望有數千字節被保留,並且每當我想要提供3個字符串時傳遞。
  • 它只能靈活達到64k字節。但我認爲那更理論上的問題與我們的節目–至少現在...在RPG