From 22ac3628a15737af8f59d1e3b1d38b74edc7f1b9 Mon Sep 17 00:00:00 2001 From: Dave Gauer Date: Sat, 8 May 2021 18:51:08 -0400 Subject: Fix 076, add 077,078 sentinels and many-item pointers --- exercises/077_sentinels2.zig | 66 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 exercises/077_sentinels2.zig (limited to 'exercises/077_sentinels2.zig') diff --git a/exercises/077_sentinels2.zig b/exercises/077_sentinels2.zig new file mode 100644 index 0000000..7a03dcd --- /dev/null +++ b/exercises/077_sentinels2.zig @@ -0,0 +1,66 @@ +// +// ------------------------------------------------------------ +// TOP SECRET TOP SECRET TOP SECRET TOP SECRET TOP SECRET +// ------------------------------------------------------------ +// +// Are you ready for the THE TRUTH about Zig string literals? +// +// Here it is: +// +// @TypeOf("foo") == *const [3:0]u8 +// +// Which means a string literal is a "constant pointer to a +// zero-terminated (null-terminated) fixed-size array of u8". +// +// Now you know. You've earned it. Welcome to the secret club! +// +// ------------------------------------------------------------ +// +// Why do we bother using a zero/null sentinel to terminate +// strings in Zig when we already have a known length? +// +// Versatility! Zig strings are compatible with C strings (which +// are null-terminated) AND can be coerced to a variety of other +// Zig types: +// +// const a: [5]u8 = "array".*; +// const b: *const [16]u8 = "pointer to array"; +// const c: []const u8 = "slice"; +// const d: [:0]const u8 = "slice with sentinel"; +// const e: [*:0]const u8 = "many-item pointer with sentinel"; +// const f: [*]const u8 = "many-item pointer"; +// +// All but 'f' may be printed. (A many-item pointer without a +// sentinel is not safe to print because we don't know where it +// ends!) +// +const print = @import("std").debug.print; + +const WeirdContainer = struct { + data: [*]const u8, + length: usize, +}; + +pub fn main() void { + // WeirdContainer is an awkward way to house a string. + // + // Being a many-item pointer (with no sentinel termination), + // the 'data' field "loses" the length information AND the + // sentinel termination of the string literal "Weird Data!". + // + // Luckily, the 'length' field makes it possible to still + // work with this value. + const foo = WeirdContainer { + .data = "Weird Data!", + .length = 11, + }; + + // How do we get a printable value from 'foo'? One way is to + // turn it into something with a known length. We do have a + // length... You've actually solved this problem before! + // + // Here's a big hint: do you remember how to take a slice? + const printable = ???; + + print("{s}\n", .{printable}); +} -- cgit v1.2.3-ZIG