Search code examples
zig

How do I compare two zero-terminated but different length strings in Zig?


For example where an external C library is returning a fixed-size buffer containing a null-terminated string.

What would be the the equivalent of strcmp() to compare these two buffers? std.mem.eql fails because they are different sizes.

var string1: [1024]u8 = undefined;
@memset(&string1, 0);
@memcpy(string1[0..3], "foo");

var string2 = "foo";

var result = std.mem.eql(u8, &string1, string2);
try std.testing.expect(result);

Solution

  • I'd suggest turning your string into a proper slice. For example, using std.mem.len:

    var buffer: [1024]u8 = undefined;
    @memset(&buffer, 0);
    @memcpy(buffer[0..3], "foo");
    
    const length = std.mem.len(@as([*:0]u8, @ptrCast(&buffer)));
    var string1 = buffer[0..length];
    var string2 = "foo";
    
    const result = std.mem.eql(u8, string1, string2);
    try std.testing.expect(result);
    

    Or better, std.mem.span:

    var string1 = std.mem.span(@as([*:0]u8, @ptrCast(&buffer)));
    

    Or std.mem.sliceTo:

    var string1 = std.mem.sliceTo(@as([*:0]u8, @ptrCast(&buffer)), 0);
    

    Or, if you know you won't need to use that string more than once and want to "optimize", then you can use std.mem.orderZ:

    var buffer: [1024]u8 = undefined;
    @memset(&buffer, 0);
    @memcpy(buffer[0..3], "foo");
    
    var string1 = @as([*:0]u8, @ptrCast(&buffer));
    var string2 = "foo";
    
    const result = std.mem.orderZ(u8, string1, string2);
    try std.testing.expect(result == .eq);