跳轉到內容

Ada 程式設計/字串

來自華夏公益教科書,開放的書籍,開放的世界

Ada. Time-tested, safe and secure.
Ada。經久耐用,安全可靠。

Ada 支援三種不同的字串型別。每種字串型別旨在解決不同的問題。

此外,每種字串型別都針對每種可用的字元型別 (Character, Wide_Character, Wide_Wide_Character) 實現,共計九種組合。

固定長度字串處理

[編輯 | 編輯原始碼]

固定長度字串(預定義型別 String)是 字元陣列,因此長度固定。由於 String 是一個 不確定的子型別,因此長度不需要在編譯時知道 - 長度可以在執行時計算出來。在以下示例中,長度是從命令列引數 1 計算出來的

X : String := Ada.Command_Line.Argument (1);

但是,一旦長度被計算出來並且字串被建立,長度將保持不變。嘗試以下程式,它展示了一個典型的錯誤

檔案:show_commandline_1.adb (檢視純文字下載頁面瀏覽所有)
with Ada.Text_IO;
with Ada.Command_Line;

procedure Show_Commandline_1 is

   package T_IO renames Ada.Text_IO;
   package CL   renames Ada.Command_Line;

   X : String := CL.Argument (1);

begin
   T_IO.Put ("Argument 1 = ");
   T_IO.Put_Line (X);

   X := CL.Argument (2);

   T_IO.Put ("Argument 2 = ");
   T_IO.Put_Line (X);
end Show_Commandline_1;

該程式僅當第 1 個和第 2 個引數具有相同的長度時才有效。即使第 2 個引數更短,情況也是如此。沒有對較短字串的自動填充,也沒有對較長字串的自動截斷。

話雖如此,包 Ada.Strings.Fixed 包含一組用於固定長度字串處理的程式和函式,允許填充較短字串和截斷較長字串。

嘗試以下示例以檢視其工作原理

檔案:show_commandline_2.adb (檢視純文字下載頁面瀏覽所有)
with Ada.Text_IO;
with Ada.Command_Line;
with Ada.Strings.Fixed;

procedure Show_Commandline_2 is

   package T_IO renames Ada.Text_IO;
   package CL   renames Ada.Command_Line;
   package S    renames Ada.Strings;
   package SF   renames Ada.Strings.Fixed;

   X : String := CL.Argument (1);

begin
   T_IO.Put ("Argument 1 = ");
   T_IO.Put_Line (X);

   SF.Move (
     Source  => CL.Argument (2),
     Target  => X,
     Drop    => S.Right,
     Justify => S.Left,
     Pad     => S.Space);

   T_IO.Put ("Argument 2 = ");
   T_IO.Put_Line (X);
end Show_Commandline_2;

有界長度字串處理

[編輯 | 編輯原始碼]

當已知和/或限制字串的最大長度時,可以使用有界長度字串。這在資料庫應用程式中很常見,在資料庫應用程式中,只能儲存有限數量的字元。

與固定長度字串一樣,最大長度不需要在編譯時知道 - 它也可以在執行時計算出來 - 如下面的示例所示

檔案:show_commandline_3.adb (檢視純文字下載頁面瀏覽所有)
with Ada.Text_IO;
with Ada.Command_Line;
with Ada.Strings.Bounded;

procedure Show_Commandline_3 is

   package T_IO renames Ada.Text_IO;
   package CL   renames Ada.Command_Line;

   function Max_Length (
      Value_1 : Integer;
      Value_2 : Integer)
   return
      Integer
   is
      Retval : Integer;
   begin
      if Value_1 > Value_2 then
         Retval := Value_1;
      else
         Retval := Value_2;
      end if;
      return Retval;
   end Max_Length;

   pragma Inline (Max_Length);

   package SB
   is new Ada.Strings.Bounded.Generic_Bounded_Length (
       Max => Max_Length (
                  Value_1 => CL.Argument (1)'Length,
                  Value_2 => CL.Argument (2)'Length));

   X :  SB.Bounded_String
     := SB.To_Bounded_String (CL.Argument (1));

begin
   T_IO.Put ("Argument 1 = ");
   T_IO.Put_Line (SB.To_String (X));

   X := SB.To_Bounded_String (CL.Argument (2));

   T_IO.Put ("Argument 2 = ");
   T_IO.Put_Line (SB.To_String (X));
end Show_Commandline_3;

您應該知道,有界長度字串有一些明顯的缺點。最明顯的是,每個有界長度字串都是一個不同的型別,這使得轉換它們相當麻煩。此外,有界長度字串型別始終為型別允許的最大字串長度分配記憶體。有界長度字串的記憶體分配等於最大字串“字元”數加上一個實現相關的數字,其中包含字串長度(每個字元可能需要分配超過一個位元組的字元,具體取決於字串的底層字元型別,而長度數字對於 Windows GNAT Ada 編譯器 v3.15p 來說是 4 個位元組,例如)。

無界長度字串處理

[編輯 | 編輯原始碼]

最後但並非最不重要的是無界長度字串。事實上:如果您沒有進行嵌入式或資料庫程式設計,這將是您最常使用的字串型別,因為它為您提供了最大的靈活性。

顧名思義,無界長度字串可以儲存幾乎任何長度的字串 - 僅限於 Integer'Last 的值或您的可用堆記憶體。這是因為 Unbounded_String 型別在幕後使用動態記憶體分配,提供較低的效率但最大的靈活性。

檔案:show_commandline_4.adb (檢視純文字下載頁面瀏覽所有)
with Ada.Text_IO;
with Ada.Command_Line;
with Ada.Strings.Unbounded;

procedure Show_Commandline_4 is

   package T_IO renames Ada.Text_IO;
   package CL   renames Ada.Command_Line;
   package SU   renames Ada.Strings.Unbounded;

   X :  SU.Unbounded_String 
     := SU.To_Unbounded_String (CL.Argument (1));

begin
   T_IO.Put ("Argument 1 = ");
   T_IO.Put_Line (SU.To_String (X));

   X := SU.To_Unbounded_String (CL.Argument (2));

   T_IO.Put ("Argument 2 = ");
   T_IO.Put_Line (SU.To_String (X));
end Show_Commandline_4;

如您所見,無界長度字串示例也是最短的 (不考慮有錯誤的第一個示例) - 這使得使用無界長度字串非常吸引人。

另請參閱

[編輯 | 編輯原始碼]

華夏公益教科書

[編輯 | 編輯原始碼]

Ada 95 參考手冊

[編輯 | 編輯原始碼]

Ada 2005 參考手冊

[編輯 | 編輯原始碼]
華夏公益教科書