mirror of
				https://codeberg.org/ziglings/exercises.git
				synced 2025-11-03 20:25:37 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			141 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			Zig
		
	
	
	
	
	
			
		
		
	
	
			141 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			Zig
		
	
	
	
	
	
//
 | 
						|
// 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://github.com/ziglang/zig/blob/master/lib/std/fmt.zig#L29
 | 
						|
//
 | 
						|
// 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 are 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-{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 vary
 | 
						|
// 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", .{});
 | 
						|
    }
 | 
						|
}
 |