Ada 程式設計/變數
變數是引用,代表儲存在特定記憶體地址的值。
變數被認為具有值,並且可能具有 資料型別。如果變數具有型別,則只能將此型別的值分配給它。變數並不總是具有型別。
一個值可以具有多種不同型別的多個值:整數 (7)、比率 (1/2)、(近似)實數 (10.234)、複數 (4+2i)、字元 ('a')、字串 ("hello"),等等。
不同的語言使用不同的名稱來表示它們的型別,並且可能不包含上述任何一種。
賦值語句
[編輯原始碼]賦值語句用於將變數設定為新值。
賦值語句寫為 名稱 := 值。
X := 10;
示例將變數X設定為整數10。賦值語句覆蓋變數的內容,並且之前的值將丟失。
在某些語言中,在使用變數之前,需要先宣告它,宣告指定型別。
Ada 也是如此。宣告如下
declareX : Integer := 10;beginDo_Something (X);end;
用途
[編輯原始碼]變數儲存程式中的所有內容。任何有用程式的目的都是修改變數。
如果沒有變數,我們就無法建立超出經典“Hello World!”示例的程式。Ada 中的變數必須宣告。它們不能在未宣告的情況下就神奇地出現在程式中。變數宣告看起來像這樣
Variable_Name : Variable_Type [:=Optional Value]
如果在宣告時為變數分配了一個值,則稱該變數已初始化。可以透過逗號分隔變數名稱,在一次宣告中宣告多個相同型別的變數
Variable_A, Variable_B : Variable_Type [:=Optional Value]
如您所見,將值分配給變數是可選的。編譯器只需要知道您打算讓變數儲存哪種資料(型別)。它不關心變數中是否有實際資料。當您宣告一個變數時,您實際上是在要求分配特定數量的記憶體。當然,實際的記憶體量取決於宣告的型別。一個Integer可能佔用 4 個位元組的記憶體,而一個String (1 .. 10)可能佔用 10 個位元組的記憶體。變數名稱只不過是一個符號名稱,與分配給該變數的記憶體中的任何值相關聯。
如果我們在宣告期間為變數分配一個值,它將看起來像這樣
Variable_Name : Variable_Type := Variable_Value
讓我們嘗試一些真實的 Ada 變數。如上所述,Ada 中的變數必須宣告為指向特定型別的資料
A_String_Variable : String (1 .. 10);
這裡我們將變數A_String_Variable 宣告為String 型別,其長度為 10 個字元,(1 .. 10)。讓我們看看如果我們在宣告期間為A_String_Variable 分配一個值會是什麼樣子
A_String_Variable : String (1 .. 10) := "abcdefghij";
這裡我們首先聲明瞭A_String_Variable 變數,然後對其進行了初始化。
在String 型別的情況下,可以省略長度,我們可以簡單地寫
A_String_Variable : String := "abcdefghij";
這裡,"abcdefghij" 的分配隱式地宣告A_String_Variable 的長度為(1 .. 10),因為這是分配字串的長度。
變數可以宣告為任何型別,無論是String、Integer、records、array 還是自定義型別。讓我們嘗試宣告各種變數
An_Array : array (1 .. 3) of Integer := (1, 2, 3);
A_Positive : Positive := 10;
type Colors is (Red, Blue, Green);
Color : Colors := Red;
type Person is record
Name : String (1 .. 12);
Age : Natural;
end record;
A_Person : Person;
B_Person : Person := (Name => "Thomas Løcke", Age => 37);
注意自定義Colors 型別。首先我們宣告新型別,然後宣告該型別的Color 變數。這是 Ada 最大的優勢之一:能夠宣告自己的型別和子型別。可以在 型別系統 文章中找到更多相關資訊。
現在,讓我們嘗試在實際程式中使用上面宣告的變數
with Ada.Text_IO;
procedure VarCon is
package IO renames Ada.Text_IO;
A_String : String (1 .. 8) := "A_String";
B_String : String := "B_String";
An_Array : array (1 .. 3) of Integer := (1, 2, 3);
A_Integer : Integer := 10;
type Colors is (Red, Blue, Green);
package IOENUM is new Ada.Text_IO.Enumeration_IO (Colors);
Color : Colors := Red;
type Person is record
Name : String (1 .. 12);
Age : Natural;
end record;
A_Person : Person;
begin
IO.Put_Line (Item => A_String);
IO.Put_Line (Item => B_String);
A_String := "String_A";
B_String := "String_B";
IO.Put_Line (Item => A_String);
IO.Put_Line (Item => B_String);
for i in An_Array'Range loop
IO.Put (Item => i'Img & ":" & An_Array (i)'Img);
IO.New_Line;
end loop;
An_Array := (1 => 10, 2 => 20, 3 => 30);
for i in An_Array'Range loop
IO.Put (Item => i'Img & ":" & An_Array (i)'Img);
IO.New_Line;
end loop;
IO.Put_Line (Item => A_Integer'Img);
IOENUM.Put (Item => Color);
IO.New_Line;
A_Person := (Name => "Thomas Løcke",
Age => 37);
IO.Put_Line (Item => A_Person.Name);
end VarCon;
執行後,上述程式應輸出以下內容
A_String B_String String_A String_B 1: 1 2: 2 3: 3 1: 10 2: 20 3: 30 10 RED Thomas Løcke
在這裡我們實際上可以看到為什麼變數被稱為變數:它們的值是可變的。
請注意,我們如何能夠更改包含在例如A_String 變數中的資料。當我們宣告它時,我們分配了A_String 的值(該變數被認為是已初始化的),但稍後我們為A_String 分配了另一個值:String_A。這正是每個初學者程式設計師都必須理解的變數的核心概念:變數是可變的。變數名稱只是一個指向記憶體位置的引用,該位置儲存特定型別的資料。確切的資料可能會在程式執行期間發生很多變化,但變數名稱和型別保持不變。
如果變數在程式執行期間不發生變化,那麼我們有一個更好的選擇:常量。它們是變數的堅強兄弟。
最後,讓我們簡要看一下變數範圍與塊的關係。它們在何時何地可見?這可以透過一個簡單的程式來更好地理解
with Ada.Text_IO;
procedure Scope is
package IO renames Ada.Text_IO;
Name : String := "Thomas Løcke";
begin
IO.Put_Line (Item => "1:" & Name);
declare
Name : String := "Dwight S. Miller";
begin
IO.Put_Line (Item => "2:" & Name);
end;
IO.Put_Line (Item => "3:" & Name);
declare
begin
IO.Put_Line (Item => "4:" & Name);
end;
end Scope;
我們從上面得到的輸出如下所示
1:Thomas Løcke 2:Dwight S. Miller 3:Thomas Løcke 4:Thomas Løcke
請注意,Name 在第一個塊中宣告為區域性變數。第一個塊中的宣告絕不會干擾“全域性”Name 變數。如果未為塊宣告Name 變數,則將使用“全域性”Name 變數,如最後一個塊中所示,其中列印了Thomas Løcke,即使該塊中沒有進行過此類分配。
因此,關於塊的變數範圍非常簡單明瞭:塊從其父塊繼承變數,然後可以透過重新宣告變數在塊中區域性覆蓋這些變數。
