From f42c390594c03d45fcc2665ed80fea35108c4b19 Mon Sep 17 00:00:00 2001 From: Chris Boesch <48591413+chrboesch@users.noreply.github.com> Date: Wed, 19 Apr 2023 21:57:37 +0200 Subject: [PATCH] added first formatting exercise --- README.md | 2 +- build.zig | 4 + exercises/099_formatting.zig | 115 +++++++++++++++++++++++++++ patches/patches/099_formatting.patch | 5 ++ 4 files changed, 125 insertions(+), 1 deletion(-) create mode 100644 exercises/099_formatting.zig create mode 100644 patches/patches/099_formatting.patch diff --git a/README.md b/README.md index 24d57f4..4d3f4a7 100644 --- a/README.md +++ b/README.md @@ -179,7 +179,7 @@ Core Language * [ ] Async <--- IN PROGRESS! * [X] Interfaces * [X] Working with C -* [ ] String formatting +* [X] String formatting * [X] Bit manipulation ## Contributing diff --git a/build.zig b/build.zig index c8d8f35..63fe5e5 100644 --- a/build.zig +++ b/build.zig @@ -513,6 +513,10 @@ const exercises = [_]Exercise{ .main_file = "098_bit_manipulation2.zig", .output = "Is this a pangram? true!", }, + .{ + .main_file = "099_formatting.zig", + .output = "\n X | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 \n---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+\n 1 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 \n\n 2 | 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 \n\n 3 | 3 6 9 12 15 18 21 24 27 30 33 36 39 42 45 \n\n 4 | 4 8 12 16 20 24 28 32 36 40 44 48 52 56 60 \n\n 5 | 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 \n\n 6 | 6 12 18 24 30 36 42 48 54 60 66 72 78 84 90 \n\n 7 | 7 14 21 28 35 42 49 56 63 70 77 84 91 98 105 \n\n 8 | 8 16 24 32 40 48 56 64 72 80 88 96 104 112 120 \n\n 9 | 9 18 27 36 45 54 63 72 81 90 99 108 117 126 135 \n\n10 | 10 20 30 40 50 60 70 80 90 100 110 120 130 140 150 \n\n11 | 11 22 33 44 55 66 77 88 99 110 121 132 143 154 165 \n\n12 | 12 24 36 48 60 72 84 96 108 120 132 144 156 168 180 \n\n13 | 13 26 39 52 65 78 91 104 117 130 143 156 169 182 195 \n\n14 | 14 28 42 56 70 84 98 112 126 140 154 168 182 196 210 \n\n15 | 15 30 45 60 75 90 105 120 135 150 165 180 195 210 225 \n\n", + }, .{ .main_file = "999_the_end.zig", .output = "\nThis is the end for now!\nWe hope you had fun and were able to learn a lot, so visit us again when the next exercises are available.", diff --git a/exercises/099_formatting.zig b/exercises/099_formatting.zig new file mode 100644 index 0000000..788584f --- /dev/null +++ b/exercises/099_formatting.zig @@ -0,0 +1,115 @@ +// +// The output on the console looks a bit rudimentary at first glance. +// However, if you look at the development of modern computers, you can +// see the enormous progress that has been made over the years. +// Starting with monochrome lines on flickering CRT monitors, modern +// terminal emulators offer a razor-sharp image with true color and +// nearly infinite font size thanks to modern hardware. +// +// In addition, they have mastered ligatures and can represent almost +// any character in any language. This also makes the output of programs +// on the console more atractive than ever in recent years. +// +// This makes it all the more important to format the presentation of +// results in an appealing way, because that is what users appreciate, +// quick visual comprehension of the information. +// +// C has set standards here over the years, and Zig is preparing to +// follow suit. Currently, however, it still lags a bit behind the model, +// but the Zig community is working diligently behind the scenes on +// further options. +// +// Nevertheless, it is time to take a closer look at the possibilities +// that already exist. And of course we will continue this series loosely, +// because Zig continues to grow almost daily. +// +// Since there is no proper documentation on the formatting yet, the most +// important source here is the source code: +// +// https://github.com/ziglang/zig/blob/master/lib/std/fmt.zig#L29 +// +// +// And in fact, you already discover quite a lot of useful formatting. +// These can be used in different ways, e.g. to convert numerical values +// into text and for direct output to the console or to a file. The latter +// is useful when large amounts of data are to be processed by other programs. +// +// However, we are concerned here exclusively with the output to the console. +// But since the formatting instructions for files are the same, what you +// learn applies universally. +// +// Since we basically write to debug output in Ziglings, our output usually +// looks like this: +// +// std.debug.print("Text {placeholder} another text \n", .{variable}); +// +// But how is the statement just shown formatted? +// +// This actually happens in several stages. On the one hand, escape +// sequences are evaluated, there is the "\n" which means "line feed" +// in the example. Whenever this statement is found, a new line is started +// in the output. Escpape sequences can also be written one after the +// other, e.g. "\n\n" will cause two line feeds. +// +// By the way, these formattings are passed directly to the terminal +// program, i.e. escape sequences have nothing to do with Zig in this +// respect. The formatting that Zig actually performs is found in the +// curly bracket, the "placeholder", and affects the coresponding variable. +// +// And this is where it gets exciting, because numbers can have different +// sizes, be positive or negative, with a decimal point or without, +// and so on. +// +// In order to bring these then into a uniform format for the output, +// instructions can be given to the placeholder: +// +// print("=> {x:0>4}", .{var}); +// +// This instruction outputs a hexadecimal number with leading zeros. +// +// => 0x0017 +// +// Let's move on to our exercise: we want to create a table that shows us +// the multiplication of all numbers together from 1-15. So if you search +// for the number '5' in the row and '4' in the column (or vice versa), +// the result of '5 x 4 = 20' should be displayed there. +// +// +const std = @import("std"); +const print = std.debug.print; + +pub fn main() !void { + // the max. size of the table + const size = 15; + + // print the header: + // + // we start with a single 'X' for the diagonal, + // that means there is no result + print("\n X |", .{}); + + // header row with all numbers from 1 to size + for (0..size) |n| { + print("{d:>3} ", .{n + 1}); + } + print("\n", .{}); + + // row line + var n: u8 = 0; + while (n <= size) : (n += 1) { + print("---+", .{}); + } + print("\n", .{}); + + // now the actual table + for (0..size) |a| { + print("{d:>2} |", .{a + 1}); + for (0..size) |b| { + // what formatting is needed here? + print("{???} ", .{(a + 1) * (b + 1)}); + } + + // after each row we use double line feed + print("\n\n", .{}); + } +} diff --git a/patches/patches/099_formatting.patch b/patches/patches/099_formatting.patch new file mode 100644 index 0000000..bb25059 --- /dev/null +++ b/patches/patches/099_formatting.patch @@ -0,0 +1,5 @@ +108,109c108 +< // what formatting is needed here? +< print("{???} ", .{(a + 1) * (b + 1)}); +--- +> print("{d:>3} ", .{(a + 1) * (b + 1)});