跳轉到內容

D(程式語言)/d2/字串和動態陣列

50% developed
來自 Wikibooks,開放世界中的開放書籍

第8課:字串和動態陣列

[編輯 | 編輯原始碼]

在本章中,您將深入瞭解字串。同時,您還將學習另一種型別:動態陣列。

入門程式碼

[編輯 | 編輯原始碼]

動態陣列

[編輯 | 編輯原始碼]
import std.stdio;

void main()
{
    int[] a = [1,2,3,4];
    int[] b = [5,6];
    auto c = a ~ b;
    writeln(c); // [1,2,3,4,5,6]
    
    writeln(c.length);  // 6
    
    int* ptr_c = c.ptr;
    ptr_c[0] = 3;
    writeln(c); // [3,2,3,4,5,6]
}

不可變和字串

[編輯 | 編輯原始碼]
import std.stdio;

void main()
{
    // Concept:  Immutable
    immutable(int) a = 10;
    // a = 11;  Error:  cannot modify immutable
    immutable a = 10;
    
    // Concept:  Strings as Arrays
    immutable(char)[] str = "Hello";
    auto str1 = str ~ "1";
    writeln(str1); // Hello1
    writeln(str1.length);  // 6  
    // str1[] = 'z'; error! str1's elements are not mutable
    char[] mutablestr1 = str1.dup;
    
    // Concept: Char Literals
    mutablestr1[] = 'z';  // 'z' is not a string, but a char
    
    str1 = mutablestr1.idup;  // The str1 itself is mutable
    // only its elements are not mutable
    writeln(str1);  // zzzzzz
}

動態陣列

[編輯 | 編輯原始碼]

動態陣列與靜態陣列

[編輯 | 編輯原始碼]

在上一課中,您學習了靜態陣列。動態陣列與靜態陣列不同,因為它們沒有固定長度。本質上,動態陣列是一個具有以下資訊的結構:

  1. 指向第一個元素的指標
  2. 整個陣列的長度

您可以像這樣建立動態陣列

int[] a;

您可以建立一個以特定長度初始化的動態陣列

int[] a = new int[](5);

您將在後面學習有關 new 關鍵字的更多內容。
使用單個值填充陣列的語法對於靜態和動態陣列都相同

int[] a = [1,2,3];
a[] = 3;
writeln(a); // [3, 3, 3]

動態陣列的索引方式與靜態陣列相同。訪問特定索引處元素的語法也相同

a[2];

但是,由於動態陣列在編譯時沒有已知的長度,因此編譯器無法檢查您訪問的索引是否確實在該長度內。類似這樣的程式碼將編譯,但也會導致執行時範圍違規錯誤

int[] a = [1,2,3];
writeln(a[100]);  //Runtime error, Range violation

動態陣列的操作

[編輯 | 編輯原始碼]

動態陣列可以使用 ~ 運算子與其他動態陣列甚至靜態陣列組合。將新元素追加到陣列使用相同的運算子。

int[] a = [1,2];
auto b = a ~ [3,4];
writeln(b);  //[1, 2, 3, 4]
b ~= 5;  // same as b = b ~ 5;
writeln(b);  //[1, 2, 3, 4, 5]

除非您確定 my_dynamic_arr.length 等於 my_static_arr.length,否則您不應該將動態陣列分配給靜態陣列 (my_static_arr = my_dynamic_arr;)。否則,將發生執行時錯誤。但是,您可以始終將靜態陣列分配給動態陣列變數,因為如果靜態陣列的長度太大,動態陣列將自動調整大小。

int[] a = [9,9,9,9,9,9];
int[3] b = [1,2,3];
int[200] c;
a = b;
writeln(a);  // [1, 2, 3]
a = c;
writeln(a.length); // 200

int[] d = [5,4,3];
b = d;  // OK: lengths are both 3
// c = d;  runtime error! lengths don't match.

將動態陣列傳遞給函式

[編輯 | 編輯原始碼]

動態陣列按值傳遞給函式。這意味著,當您將動態陣列傳遞給函式時,包含指向第一個元素的指標和長度的結構會被複制並傳遞。

void tryToChangeLength(int[] arr)
{
    arr.length = 100;
}
void main()
{
    int[] a = [1,2];
    tryToChangeLength(a);
    writeln(a.length);  // still 2
}

您在上章中瞭解到,您可以透過新增 ref 修飾符使事物按引用而不是按值傳遞。

陣列和其他屬性

[編輯 | 編輯原始碼]

這些屬性適用於靜態和動態陣列

屬性 描述
.init 對於靜態陣列,它返回一個數組,其中每個元素都初始化為其預設值。
.sizeof 返回陣列在記憶體中的大小。
.length 返回陣列中元素的數量。這在靜態陣列中是固定的。
.ptr 返回指向陣列第一個元素的指標。
.dup 建立一個動態陣列,它是陣列的副本,並返回它。
.idup 類似於 .dup,但副本的元素是 immutable
.reverse 以相反順序返回陣列的元素。
.sort 對陣列中的元素進行就地排序,並返回結果。

還有其他屬性,這些屬性是所有物件或表示式的共有屬性。其中兩個屬性是 .init.sizeof 屬性。

不可變

[編輯 | 編輯原始碼]

在 D 中,immutable 就像 auto 一樣是一個儲存類。它將型別轉換為不可修改的型別。

immutable(int) fixed_value = 37;
immutable int another_value = 46;

請注意,immutable(type) 對編譯器而言與 immutable type 相同。

儲存類和auto

[編輯 | 編輯原始碼]

當您有一個像 immutable 這樣的儲存類時,您可以省略 auto 進行型別推斷。

immutable fixed_value = 55;

編譯器會推斷出不可變型別的具體型別。以下程式碼示例無效,因為編譯器無法推斷出型別。

immutable fixed_value;  //Error!

使用 immutable 變數

[編輯 | 編輯原始碼]

這是允許的,並且是完全有效的程式碼

immutable(int) a = 300;
int b = a;

它只是將 b 設定為 a 的值。 b 不必是 immutable。如果你正在獲取引用,情況就會有所不同。

immutable(int) a = 13;
immutable(int)* b = &a;
// int* c = &a;  Error.

你可以將 immutable 強制轉換為可變型別,但如果你使用這種技巧修改了不可變值,結果是未定義的。

immutable(int) a = 7;
int* b = cast(int*)&a;
// Just make sure you do not modify a
// through b, or else!

字串作為陣列

[編輯 | 編輯原始碼]

從第一課起你就在使用字串。stringimmutable(char)[] 完全相同,即不可變字元元素的動態陣列。類似地,wstring 等同於 immutable(wchar)[],而 dstring 等同於 immutable(dchar)[]

字串屬性

[編輯 | 編輯原始碼]

字串具有與動態陣列相同的內建屬性。一個有用的屬性是 .dup 屬性,用於建立字串的可變 char[] 副本,以便修改字串的各個字元。

string a = "phobos";
char[] b = a.dup;
b[1] = 'r';
b[4] = 'e';
writeln(b);  // probes

.idup 屬性用於建立現有字串的副本,或建立 char[] 的字串副本。

string a = "phobos";
string copy_a = a.idup;
char[] mutable_a = copy_a.dup;
mutable_a[3] = 't';
copy_a = mutable_a.idup;
writeln(mutable_a); // photos
writeln(a); // phobos

字元字面量

[編輯 | 編輯原始碼]

char 字面量用單引號括起來。也有 wchardchar 字面量。

auto a = "a"; // string
auto b = 'b'; // char
auto c = 'c'c; // char
auto d = 'd'w; // wchar
auto e = 'e'd; // dchar
華夏公益教科書