D (The Programming Language)/d2/Strings and Dynamic Arrays
Lesson 8: Strings and Dynamic Arrays
[edit | edit source]In this chapter, you will learn about strings in depth. In the meantime, you will also learn about another type: the dynamic array.
Introductory Code
[edit | edit source]Dynamic Arrays
[edit | edit source]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]
}
Immutable and Strings
[edit | edit source]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
}
Concepts
[edit | edit source]Dynamic Arrays
[edit | edit source]Dynamic Arrays versus Static Arrays
[edit | edit source]In the previous lesson, you learned about static arrays. Dynamic arrays are different from those in that they do not have a fixed length. Essentially, a dynamic array is a structure with this info:
- A pointer to the first element
- The length of the entire array
You create a dynamic array like this:
int[] a;
You can create a dynamic array initiated with a specific length:
int[] a = new int[](5);
You will learn more about the new
keyword later.
The syntax for filling an array with a single value is the same for both static and dynamic arrays:
int[] a = [1,2,3];
a[] = 3;
writeln(a); // [3, 3, 3]
Dynamic arrays are indexed in the same fashion as static arrays. The syntax for accessing an element at a certain index is the same:
a[2];
However, since dynamic arrays don't have a length known at compile-time, the compiler can't check if the index that you are accessing is really within that length. Code like this would compile but would also cause a runtime Range Violation error:
int[] a = [1,2,3];
writeln(a[100]); //Runtime error, Range violation
Manipulation of Dynamic Arrays
[edit | edit source]Dynamic arrays can be combined with other dynamic arrays or even with static arrays using the ~
operator. Appending a new element to the array uses the same operator.
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]
You shouldn't assign a dynamic array to a static array (my_static_arr = my_dynamic_arr;
) unless if you are certain that my_dynamic_arr.length
is the equal to my_static_arr.length
. Otherwise, a runtime error will occur. You can always assign a static array to a dynamic array variable, though, since the dynamic array will automatically resize if the static array's length is too big.
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.
Passing Dynamic Arrays to Functions
[edit | edit source]Dynamic Arrays are passed by value to functions. That means, when you pass a dynamic array to a function, the structure that contains the pointer to the first element and the length is copied and passed.
void tryToChangeLength(int[] arr)
{
arr.length = 100;
}
void main()
{
int[] a = [1,2];
tryToChangeLength(a);
writeln(a.length); // still 2
}
You learned in the last chapter that you can cause things to be passed by reference instead of by value by adding the ref
modifier.
Array and Other Properties
[edit | edit source]These properties apply to both static and dynamic arrays:
Property | Description |
---|---|
.init | For static arrays, it returns an array with each element initialized to its default value. |
.sizeof | Returns the size of the array in memory. |
.length | Returns the number of elements in the array. This is fixed in static arrays. |
.ptr | Returns a pointer to the first element of the array. |
.dup | Creates a dynamic array that is a copy of the array and returns it. |
.idup | Similar to .dup but the copy's elements are immutable .
|
.reverse | Returns the array with its elements in reverse order. |
.sort | Sorts in place the elements in the array and returns the result. |
There are also other properties which are common to every object or expression. Two of such properties are the .init
and .sizeof
properties.
Immutable
[edit | edit source]In D, immutable
is a storage-class just like auto
. It converts a type to a non-modifiable type.
immutable(int) fixed_value = 37;
immutable int another_value = 46;
Note that immutable(type)
means the same as immutable type
to the compiler.
Storage-Classes and auto
[edit | edit source]When you have a storage class like immutable
, you can omit auto
for type inference.
immutable fixed_value = 55;
The type of whatever is immutable is inferred from the compiler. This next code example is not valid because there is no way the compiler could infer the type:
immutable fixed_value; //Error!
Using immutable
Variables
[edit | edit source]This is allowed and perfectly fine code:
immutable(int) a = 300;
int b = a;
It only sets b
equal to the value of a
. b
does not have to be immutable
. That changes if you are taking a reference:
immutable(int) a = 13;
immutable(int)* b = &a;
// int* c = &a; Error.
You are allowed to cast the immutable
away, but if you were to modify an immutable value using that hack, the result is undefined.
immutable(int) a = 7;
int* b = cast(int*)&a;
// Just make sure you do not modify a
// through b, or else!
Strings as Arrays
[edit | edit source]You've seen strings since Lesson 1. A string
is the exact same thing as immutable(char)[]
, a dynamic array of immutable char elements. Likewise, a wstring
is the same as immutable(wchar)[]
, and a dstring
is the same as immutable(dchar)[]
.
String Properties
[edit | edit source]Strings have the same built-in properties as dynamic arrays. One useful property is the .dup
property, for creating a mutable char[]
copy of a string if you want to modify the individual characters of the string.
string a = "phobos";
char[] b = a.dup;
b[1] = 'r';
b[4] = 'e';
writeln(b); // probes
The .idup
property is useful for creating a copy of an existing string, or for creating a string copy of a 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 Literals
[edit | edit source]A char
literal is enclosed by single-quotes. There are also wchar
and dchar
literals.
auto a = "a"; // string
auto b = 'b'; // char
auto c = 'c'c; // char
auto d = 'd'w; // wchar
auto e = 'e'd; // dchar