mirror of
https://codeberg.org/ziglings/exercises.git
synced 2024-12-25 09:10:26 +00:00
add ex076 sentinels
This commit is contained in:
parent
c1371f5659
commit
e9547cf808
4 changed files with 134 additions and 1 deletions
|
@ -146,8 +146,8 @@ Core Language
|
|||
* [x] Builtins
|
||||
* [x] Inline loops
|
||||
* [x] Comptime
|
||||
* [x] Sentinel termination
|
||||
* [ ] Anonymous structs
|
||||
* [ ] Sentinel termination
|
||||
* [ ] Suspend / Resume
|
||||
* [ ] Async / Await
|
||||
* [ ] Nosuspend
|
||||
|
|
|
@ -379,6 +379,10 @@ const exercises = [_]Exercise{
|
|||
.output = "Archer's Point--2->Bridge--1->Dogwood Grove--3->Cottage--2->East Pond--1->Fox Pond",
|
||||
.hint = "Roll up those sleeves. You get to WRITE some code for this one.",
|
||||
},
|
||||
.{
|
||||
.main_file = "076_sentinels.zig",
|
||||
.output = "Array:123056. Many-pointer:123.",
|
||||
},
|
||||
};
|
||||
|
||||
/// Check the zig version to make sure it can compile the examples properly.
|
||||
|
|
121
exercises/076_sentinels.zig
Normal file
121
exercises/076_sentinels.zig
Normal file
|
@ -0,0 +1,121 @@
|
|||
//
|
||||
// A sentinel value indicates the end of data. Let's imagine a
|
||||
// sequence of lowercase letters where uppercase 'S' is the
|
||||
// sentinel, indicating the end of the sequence:
|
||||
//
|
||||
// abcdefS
|
||||
//
|
||||
// If our sequence also allows for uppercase letters, 'S' would
|
||||
// make a terrible sentinel since it could no longer be a regular
|
||||
// value in the sequence:
|
||||
//
|
||||
// abcdQRST
|
||||
// ^-- Oops! The last letter in the sequence is R!
|
||||
//
|
||||
// A popular choice for indicating the end of a string is the
|
||||
// value 0. ASCII and Unicode call this the "Null Character".
|
||||
//
|
||||
// Zig supports sentinel-terminated arrays, slices, and pointers:
|
||||
//
|
||||
// const a: [4:0]u32 = [4:0]u32{1, 2, 3, 4};
|
||||
// const b: [:0]const u32 = &[4:0]u32{1, 2, 3, 4};
|
||||
// const c: [*:0]const u32 = &[4:0]u32{1, 2, 3, 4};
|
||||
//
|
||||
// Array 'a' stores 5 u32 values, the last of which is 0.
|
||||
// However the compiler takes care of this housekeeping detail
|
||||
// for you. You can treat 'a' as a normal array with just 4
|
||||
// items.
|
||||
//
|
||||
// Slice 'b' is only allowed to point to zero-terminated arrays
|
||||
// but otherwise works just like a normal slice.
|
||||
//
|
||||
// Pointer 'c' is exactly like the many-pointers we learned about
|
||||
// in exercise 054, but it is guaranteed to end in 0. Because of
|
||||
// this guarantee, we can safely find the end of this
|
||||
// many-pointer without knowing its length. (We CAN'T do that
|
||||
// with regular many-pointers!).
|
||||
//
|
||||
const print = @import("std").debug.print;
|
||||
|
||||
pub fn main() void {
|
||||
// Here's a zero-terminated array of u32 values:
|
||||
var nums = [_:0]u32{ 1, 2, 3, 4, 5, 6 };
|
||||
|
||||
// And here's a zero-terminated many-pointer:
|
||||
var ptr: [*:0]u32 = &nums;
|
||||
|
||||
// For fun, let's replace the value at position 3 with the
|
||||
// sentinel value 0. This seems kind of naughty.
|
||||
nums[3] = 0;
|
||||
|
||||
// So now we have a zero-terminated array and a many-pointer
|
||||
// that reference the same data: a sequence of numbers that
|
||||
// both ends in and CONTAINS the sentinal value.
|
||||
//
|
||||
// Attempting to loop through and print both of these should
|
||||
// demonstrate how they are similar and different.
|
||||
//
|
||||
// (It turns out that the array prints completely, including
|
||||
// the sentinel 0 in the middle. The many-pointer must stop
|
||||
// at the first sentinel value. The difference is simply that
|
||||
// arrays have a known length and many-pointers don't.)
|
||||
printSequence(nums);
|
||||
printSequence(ptr);
|
||||
|
||||
print("\n", .{});
|
||||
}
|
||||
|
||||
// Here's our generic sequence printing function. It's nearly
|
||||
// complete, but there are a couple missing bits. Please fix
|
||||
// them!
|
||||
fn printSequence(my_seq: anytype) void {
|
||||
const my_type = @typeInfo(@TypeOf(my_seq));
|
||||
|
||||
// The TypeInfo contained in my_type is a union. We use a
|
||||
// switch to handle printing the Array or Pointer fields,
|
||||
// depending on which type of my_seq was passed in:
|
||||
switch (my_type) {
|
||||
.Array => {
|
||||
print("Array:", .{});
|
||||
|
||||
// Loop through the items in my_seq.
|
||||
for (???) |s| {
|
||||
print("{}", .{s});
|
||||
}
|
||||
},
|
||||
.Pointer => {
|
||||
// Check this out - it's pretty cool:
|
||||
const my_sentinel = my_type.Pointer.sentinel;
|
||||
print("Many-pointer:", .{});
|
||||
|
||||
// Loop through the items in my_seq until we hit the
|
||||
// sentinel value.
|
||||
var i: usize = 0;
|
||||
while (??? != my_sentinel) {
|
||||
print("{}", .{my_seq[i]});
|
||||
i += 1;
|
||||
}
|
||||
},
|
||||
else => unreachable,
|
||||
}
|
||||
print(". ", .{});
|
||||
}
|
||||
//
|
||||
// ------------------------------------------------------------
|
||||
// TOP SECRET TOP SECRET TOP SECRET TOP SECRET TOP SECRET
|
||||
// ------------------------------------------------------------
|
||||
//
|
||||
// Are you ready for the THE TRUTH about Zig string literals?
|
||||
//
|
||||
// You've earned it. Here it is:
|
||||
//
|
||||
// @TypeOf("foo") == *const [3:0]u8
|
||||
//
|
||||
// Zig's string literals are constant pointers to zero-terminated
|
||||
// (or "null-terminated") arrays of u8.
|
||||
//
|
||||
// Now you know. Welcome to the secret club!
|
||||
//
|
||||
// ------------------------------------------------------------
|
||||
// TOP SECRET TOP SECRET TOP SECRET TOP SECRET TOP SECRET
|
||||
// ------------------------------------------------------------
|
8
patches/patches/076_sentinels.patch
Normal file
8
patches/patches/076_sentinels.patch
Normal file
|
@ -0,0 +1,8 @@
|
|||
82c82
|
||||
< for (???) |s| {
|
||||
---
|
||||
> for (my_seq) |s| {
|
||||
94c94
|
||||
< while (??? != my_sentinel) {
|
||||
---
|
||||
> while (my_seq[i] != my_sentinel) {
|
Loading…
Reference in a new issue