#Converting string to arbitrary length array
1 messages · Page 1 of 1 (latest)
Using ArrayList could be bit nicer and wouldn't be much different considering it's for test purposes
std.io.fixedBufferStream may be what you're looking for.
var fbs = std.io.fixedBufferStream(input);
const reader = fbs.reader(); // expoes all the methods that `std.io.getStdIn().reader()` does
Thanks - will look into both
Also worth noting that your loop is just std.mem.copy(u8, buf, input)
Looks like you want a sentinel terminated array? Like c uses?
I'd say you need to make a slice of var slice = buf[0..input.len]
and then assign string to it
or just var slice = input[0..]???
and my_parsing_funciton(slice);
I'm a bit confused. I think I want a slice that actually has the zero as the final value. But now that I saw what you wrote I am looking back at my_parsing_func and wondering if I should implement it differently though.
const stdin = std.io.getStdIn().reader();
var buf: [10]u8 = undefined;
if (try stdin.readUntilDelimiterOrEof(buf[0..], '\n')) |user_input| {
my_parsing_func(&buf);
}
This is what I had. Which meant my_parsing_func expects an array with 10 bytes with a zero indicating where input stopped.
But now I'm realizing user_input is probably slice of exactly the relevant characters and nothing else. So I should just use that...
Ok this seems to work (with some changes inside the parse function)
var buf: [5]u8 = "hello".*;
const cmd = try parse_cmd(&buf);
I don't quite understand what .* does here - found it in the ziglings exercises on sentinels
It seems to discard the sentinel and just become a normal slice.
Doesn't seem like I can replace [5] with [_]
to explain what's happening here:
strings literals are of type *const [_:0]u8, so e.g. @TypeOf("foo") == *const [3:0]u8. In english, we'd call that a "Pointer to a constant array of 3 elements and a sentinel of 0, with a child type of u8".
The thing about pointers to arrays in zig is that they are treated a bit specially, in that you can treat them almost identically to a slice, which is a useful property that allows easily going between using slices and pointers to arrays. But, besides that, they are ultimately just regular single-item pointers, and like all others, support dereferencing to either write to the memory location, or get a copy of it.
In this case, you dereference it, and get a copy of it, which has a type [_:0]u8. The reason it "loses" the sentinel is coercion. The relevant bytes are copied from the [_:0]u8 to the [_]u8, without the sentinel. This basically just happens because it's convenient, and it doesn't lose any information that can't be easily regained, or that is strictly necessary.
And thus, it doesn't "become a normal slice", the array has just been coerced.
Besides that, the reason you can't do var buf: [_]u8 is because [_]T is syntax that is only for inferring the length of a literal, like [_]u32{ 1, 2, 3 } - zig doesn't really infer patterns.
Also, another place you'll have been using pointers to arrays without realising it is the slicing operation: if you do array[0..], where array is of a type like [n]T, the type of the result you'll actually get is *[n]T, and ditto for anything like ptr[n..m] where n and m are comptime-known.
Ok - I think I am following this (thank you for the amazing explanation). So "hello" is implicitly creating a pointer to sentinel terminated array. "hello".* is dereferencing that pointer to get the underlying 5 bytes of h e l l o and then assigning that to a new variable of type [5]u8.
A pointer to an array (including one made implicitly in declaring a string a literal) does not have length information so zig can't do any magic there.
that last bit isn't quite on the mark. The string literal does in fact have length information, and you could just do e.g. var buf = "hello".*;, with the only caveat being that @TypeOf(buf) == [5:0]u8. What I was trying to explain was that zig doesn't do any sort of type pattern inference - meaning a variable type is either written explicitly, or it is inferred from the type of the value used to initialise it
So inference is all or nothing essentially - you can't assign a specific type but expect it to still infer the length. Is that a better statement?
aye, spot on