mirror of
https://codeberg.org/ziglings/exercises.git
synced 2026-06-11 01:20:00 +00:00
Insert space for additional async exercises
This commit is contained in:
140
exercises/102_formatting.zig
Normal file
140
exercises/102_formatting.zig
Normal file
@@ -0,0 +1,140 @@
|
||||
//
|
||||
// Terminals have come a long way over the years. Starting with
|
||||
// monochrome lines on flickering CRT monitors and continuously
|
||||
// improving to today's modern terminal emulators with sharp
|
||||
// images, true color, fonts, ligatures, and characters in every
|
||||
// known language.
|
||||
//
|
||||
// Formatting our results to be appealing and allow quick visual
|
||||
// comprehension of the information is what users desire. <3
|
||||
//
|
||||
// C set string formatting standards over the years, and Zig is
|
||||
// following suit and growing daily. Due to this growth, there is
|
||||
// no official documentation for standard library features such
|
||||
// as string formatting.
|
||||
//
|
||||
// Therefore, the comments for the format() function are the only
|
||||
// way to definitively learn how to format strings in Zig:
|
||||
//
|
||||
// https://codeberg.org/ziglang/zig/src/branch/master/lib/std/Io/Writer.zig#L537
|
||||
//
|
||||
// Zig already has a very nice selection of formatting options.
|
||||
// These can be used in different ways, but generally to convert
|
||||
// numerical values into various text representations. The results
|
||||
// can be used for direct output to a terminal or stored for
|
||||
// later use or written to a file. The latter is useful when
|
||||
// large amounts of data are to be processed by other programs.
|
||||
//
|
||||
// In Ziglings, we are concerned with the output to the console.
|
||||
// But since the formatting instructions for files are the same,
|
||||
// what you learn applies universally.
|
||||
//
|
||||
// Since we write to "debug" output in Ziglings, our answers
|
||||
// usually look something like this:
|
||||
//
|
||||
// print("Text {placeholder} another text \n", .{foo});
|
||||
//
|
||||
// In addition to being replaced with foo in this example, the
|
||||
// {placeholder} in the string can also have formatting applied.
|
||||
// How does that work?
|
||||
//
|
||||
// This actually happens in several stages. In one stage, escape
|
||||
// sequences are evaluated. The one we've seen the most
|
||||
// (including the example above) is "\n" which means "line feed".
|
||||
// Whenever this statement is found, a new line is started in the
|
||||
// output. Escape sequences can also be written one after the
|
||||
// other, e.g. "\n\n" will cause two line feeds.
|
||||
//
|
||||
// By the way, the result of these escape sequences is passed
|
||||
// directly to the terminal program. Other than translating them
|
||||
// into control codes, escape sequences have nothing to do with
|
||||
// Zig. Zig knows nothing about "line feeds" or "tabs" or
|
||||
// "bells".
|
||||
//
|
||||
// The formatting that Zig *does* perform itself is found in the
|
||||
// curly brackets: "{placeholder}". Formatting instructions in
|
||||
// the placeholder will determine how the corresponding value,
|
||||
// e.g. foo, is displayed.
|
||||
//
|
||||
// And this is where it gets exciting, because format() accepts a
|
||||
// variety of formatting instructions. It's basically a tiny
|
||||
// language of its own. Here's a numeric example:
|
||||
//
|
||||
// print("Catch-0x{x:0>4}.", .{twenty_two});
|
||||
//
|
||||
// This formatting instruction outputs a hexadecimal number with
|
||||
// leading zeros:
|
||||
//
|
||||
// Catch-0x0016.
|
||||
//
|
||||
// Or you can center-align a string like so:
|
||||
//
|
||||
// print("{s:*^20}\n", .{"Hello!"});
|
||||
//
|
||||
// Output:
|
||||
//
|
||||
// *******Hello!*******
|
||||
//
|
||||
// Let's try making use of some formatting. We've decided that
|
||||
// the one thing missing from our lives is a multiplication table
|
||||
// for all numbers from 1-15. We want the table to be nice and
|
||||
// neat, with numbers in straight columns like so:
|
||||
//
|
||||
// X | 1 2 3 4 5 ...
|
||||
// ---+---+---+---+---+---+
|
||||
// 1 | 1 2 3 4 5
|
||||
//
|
||||
// 2 | 2 4 6 8 10
|
||||
//
|
||||
// 3 | 3 6 9 12 15
|
||||
//
|
||||
// 4 | 4 8 12 16 20
|
||||
//
|
||||
// 5 | 5 10 15 20 25
|
||||
//
|
||||
// ...
|
||||
//
|
||||
// Without string formatting, this would be a more challenging
|
||||
// assignment because the number of digits in the numbers varies
|
||||
// from 1 to 3. But formatting can help us with that.
|
||||
//
|
||||
const std = @import("std");
|
||||
const print = std.debug.print;
|
||||
|
||||
pub fn main() !void {
|
||||
// Max number to multiply
|
||||
const size = 15;
|
||||
|
||||
// Print the header:
|
||||
//
|
||||
// We start with a single 'X' for the diagonal.
|
||||
print("\n X |", .{});
|
||||
|
||||
// Header row with all numbers from 1 to size.
|
||||
for (0..size) |n| {
|
||||
print("{d:>3} ", .{n + 1});
|
||||
}
|
||||
print("\n", .{});
|
||||
|
||||
// Header column rule line.
|
||||
var n: u8 = 0;
|
||||
while (n <= size) : (n += 1) {
|
||||
print("---+", .{});
|
||||
}
|
||||
print("\n", .{});
|
||||
|
||||
// Now the actual table. (Is there anything more beautiful
|
||||
// than a well-formatted table?)
|
||||
for (0..size) |a| {
|
||||
print("{d:>2} |", .{a + 1});
|
||||
|
||||
for (0..size) |b| {
|
||||
// What formatting is needed here to make our columns
|
||||
// nice and straight?
|
||||
print("{???} ", .{(a + 1) * (b + 1)});
|
||||
}
|
||||
|
||||
// After each row we use double line feed:
|
||||
print("\n\n", .{});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user