7

I'm following this blog post on 'comptime' in Zig.

The following line no longer compiles in Zig 0.6.0.

const user_input = try io.readLineSlice(buf[0..]);

Below is the full function:

fn ask_user() !i64 {
    var buf: [10]u8 = undefined;
    std.debug.warn("A number please: ");
    const user_input = try io.readLineSlice(buf[0..]);
    return fmt.parseInt(i64, user_input, 10);
}

What is the equivalent in the current version (of getting user input)?

Mike Doe
  • 16,349
  • 11
  • 65
  • 88
user3475861
  • 73
  • 1
  • 4

2 Answers2

13

You can use the method readUntilDelimiterOrEof of stdin instead:

const stdin = std.io.getStdIn().reader();
pub fn readUntilDelimiterOrEof(self: @TypeOf(stdin), buf: []u8, delimiter: u8) !?[]u8

So, the code can be:

fn ask_user() !i64 {
    const stdin = std.io.getStdIn().reader();
    const stdout = std.io.getStdOut().writer();

    var buf: [10]u8 = undefined;
    
    try stdout.print("A number please: ", .{});

    if (try stdin.readUntilDelimiterOrEof(buf[0..], '\n')) |user_input| {
        return std.fmt.parseInt(i64, user_input, 10);
    } else {
        return @as(i64, 0);
    }
}

See also: Zig 0.7.0 documentation.

daurnimator
  • 4,091
  • 18
  • 34
  • this is really complicated for a simple use such as reading console input. Is there a better way of doing this keeping in mind Zig is a drop in replacement for C which has Scanf? – John Nyingi Jan 12 '23 at 13:35
  • There's no `scanf` at the moment, see [issue 12161](https://github.com/ziglang/zig/issues/12161). I would also recommend taking a look at [Q: Disadvantages of scanf](https://stackoverflow.com/q/2430303/944911). – sigod Mar 31 '23 at 20:51
1

Even though Cristobal Montecino's answer might work, because windows uses CR/LF line endings, you might also need to trim the end of the string:

// We can read any arbitrary number type with number_type
fn get_number(comptime number_type: type) !number_type {
    const stdin = std.io.getStdIn().reader();

    // Adjust the buffer size depending on what length the input
    // will be or use "readUntilDelimiterOrEofAlloc"
    var buffer: [8]u8 = undefined;

    // Read until the '\n' char and capture the value if there's no error
    if (try stdin.readUntilDelimiterOrEof(buffer[0..], '\n')) |value| {
        // We trim the line's contents to remove any trailing '\r' chars 
        const line = std.mem.trimRight(u8, value[0..value.len - 1], "\r");
        return try std.fmt.parseInt(number_type, line, 10);
    } else {
        return @as(number_type, 0);
    }
}
Sawcce
  • 46
  • 3