I’m revisiting Zig by trying to update some very simple programs. I had originally tried it out in 2023 using version 0.10.1, but now I’m using 0.15.2. The base code, in C++, excluding prompting and other not relevant output, was this:
std::string name;
std::cin >> name;
std::cout >> name >> '\n';
An analogous C version would be something like this (excluding any error checking, of course):
char name[30];
scanf("%s", name);
printf("%s\n", name);
The Zig 0.10 version, which I believe worked fine back then, was somewhat as follows:
var name: [30]u8 = undefined;
const size = try stdin.read(&name);
if (size < name.len) {
const line = std.mem.trimRight(u8, name[0..size], "\n\r");
std.mem.copy(u8, &name, line);
}
try stdout.print("{}\n", .{name[0 .. size - 1]});
My current 0.15.2 version, is as follows:
var stdout_buffer: [1024]u8 = undefined;
var stdout_writer = std.fs.File.stdout().writer(&stdout_buffer);
const stdout = &stdout_writer.interface;
var stdin_buffer: [80]u8 = undefined;
var stdin_reader = std.fs.File.stdin().reader(&stdin_buffer);
const stdin = &stdin_reader.interface;
var name: [30:0]u8 = undefined;
const line = try stdin.takeDelimiterExclusive('\n');
const str = std.mem.trim(u8, line, " \n\r");
for (str, 0..) |c, i| {
name[i] = c;
}
try stdout.print("{s}\n", .{name[0..str.len]});
try stdout.flush();
I understand the new I/O requirements and I’ve watched Andrew’s “Don’t forget to flush!”, but all the extra code is not my issue. What I struggled with was with copying from str to name. At first, it looked at std.membut there is no longer a copy() function there. It does have a copyForward() but it suggests using @memmovebecause the former is deprecated. Using @memcpy(name[0..str.len], str)does compile, but it gives a runtime error because “source and destination arguments have non-equal lengths”. So that’s why I ended up implementing a strncpy()-like loop by hand. I would think there must be an easier way, but I wasn’t able to find it.
A secondary issue, which was present in the 0.10 version also, is that to print just the nameand not any garbage leftover in the buffer, the variable has to be sliced using str.len (or size in the earlier code). In the actual test program, the name is printed a few times, so that’s also inconvenient (I sort of “fixed it” by declaring a constfor that slice).