预期类型为’i32’,找到’usize’。

huangapple go评论74阅读模式
英文:

expected type 'i32', found 'usize'

问题

我目前正在尝试使用Zig解决一些LeetCode问题,其中包括两数之和问题。以下是我的代码的完整部分:

const std = @import("std");
const allocator = std.heap.page_allocator;

fn two_sum(nums: []i32, target: i32) []i32{
    var map = std.AutoArrayHashMap(i32, i32).init(allocator);
    defer map.deinit();
    var res = [2]i32{-1, -1};
    for (nums, 0..) |n, i| { // n是数字;i是索引
        if (map.get(target - n)) |v| {
            res[0] = v;
            res[1] = @as(i32, i);
            return &res;
        }
        try map.put(n, @as(i32, i));
    }
    return &res;
}

pub fn main() !void {
    var arr = [_]i32{1, 5, 8, 9, 6};
    var x = two_sum(&arr, 9);
    for (x) |n| {
        std.debug.print("{d}", .{n});
    }
}

然而,当我运行代码时,我得到了这个错误:

error: 期望类型 'i32',找到 'usize'
            res[1] = @as(i32, i);
                ^

为什么Zig将1解释为 usize 而不是 i32?以及如何修复这个问题?

我尝试使用显式类型转换:

res[@as(i32, 1)] = @as(i32, i);

然而,这也不起作用。

英文:

I'm currently trying to solve some leetcode problems in Zig, and I'm doing the two sum problem. Here's what the entirety of my code looks like:

const std = @import("std");
const allocator = std.heap.page_allocator;

fn two_sum(nums: []i32, target: i32) []i32{
    var map = std.AutoArrayHashMap(i32, i32).init(allocator);
    defer map.deinit();
    var res = [2]i32{-1, -1};
    for (nums, 0..) |n, i| { // n is the number; i is the index
        if (map.get(target - n)) |v| {
            res[0] = v;
            res[1] = @as(i32, i);
            return &res;
        }
        try map.put(n, @as(i32, i));
    }
    return &res;
}

pub fn main() !void {
    var arr = [_]i32{1, 5, 8, 9, 6};
    var x = two_sum(&arr, 9);
    for (x) |n| {
        std.debug.print("{d}", .{n});
    }
}

However, when I run the code, I get this error:

error: expected type 'i32', found 'usize'
            res[1] = @as(i32, i);
                ^

Why is zig interpreting 1 as a usize and not an i32? And what can be done to fix this?

I tried using an explicit type cast:
res[@as(i32, 1)] = @as(i32, i);

However, that didn't work either.

答案1

得分: 1

紧急问题是i的类型为usize,而您不能使用@asusize转换为i32,因为i32不能容纳usize可能容纳的所有值。取而代之的是,使用@intCast,该函数专为您在知道转换是安全的情况下使用。有两个使用@as的这种情况需要更改为@intCast

two_sum函数需要返回一个错误联合类型,因为它在调用map.put时使用了try。而且由于two_sum需要返回错误联合类型,对two_sum的调用需要处理这个,例如通过使用try

最后,res是一个局部变量,您不应该返回对局部变量的指针;与局部变量相关联的存储在控制离开局部作用域后就不再有效,尝试访问这种无效内存会导致未定义行为。不要返回指针,只需返回(副本)数组。

以下是已应用上述更改的OP发布的代码的版本。

const std = @import("std");
const allocator = std.heap.page_allocator;

fn two_sum(nums: []i32, target: i32) ![][2]i32 {  // 返回错误联合
    var map = std.AutoArrayHashMap(i32, i32).init(allocator);
    defer map.deinit();
    var res = [2]i32{ -1, -1 };
    for (nums, 0..) |n, i| {
        if (map.get(target - n)) |v| {
            res[0] = v;
            res[1] = @intCast(i32, i);     // 使用`@intCast`而不是`@as`
            return res;                    // 只返回数组
        }
        try map.put(n, @intCast(i32, i));  // 使用`@intCast`而不是`@as`
    }
    return res;                            // 只返回数组
}

pub fn main() !void {
    var arr = [_]i32{1, 5, 8, 9, 6};
    var x = try two_sum(&arr, 9);  // `two_sum`返回错误联合
    for (x) |n| {
        std.debug.print("{d}", .{n});
    }
    std.debug.print("\n", .{});
}
英文:

The immediate problem is that i has type usize, and you can't cast from usize to i32 using @as since an i32 can't hold all of the values that a usize might hold. Instead, use @intCast which is specifically for these situations when you know that the cast is safe. There are two such casts using @as that need to be changed to @intCast.

The two_sum function needs to return an error union since it is using try around the call to map.put. And since two_sum needs to return an error union, calls to two_sum need to handle that, e.g., by using try.

Finally, res is a local variable, and you shouldn't return a pointer to a local variable; the storage associated with local variables is not valid after control leaves the local scope, and attempting to access such invalid memory leads to undefined behavior. Instead of returning a pointer, just return (a copy of) the array.

Here is a version of OP posted code with the above changes.

const std = @import("std");
const allocator = std.heap.page_allocator;

fn two_sum(nums: []i32, target: i32) ![2]i32 {  // return error union
    var map = std.AutoArrayHashMap(i32, i32).init(allocator);
    defer map.deinit();
    var res = [2]i32{ -1, -1 };
    for (nums, 0..) |n, i| {
        if (map.get(target - n)) |v| {
            res[0] = v;
            res[1] = @intCast(i32, i);     // use `@intCast` instead of `@as`
            return res;                    // just return the array
        }
        try map.put(n, @intCast(i32, i));  // use `@intCast` instead of `@as`
    }
    return res;                            // just return the array
}

pub fn main() !void {
    var arr = [_]i32{1, 5, 8, 9, 6};
    var x = try two_sum(&arr, 9);  // `two_sum` returns an error union
    for (x) |n| {
        std.debug.print("{d}", .{n});
    }
    std.debug.print("\n", .{});
}

huangapple
  • 本文由 发表于 2023年6月2日 10:42:08
  • 转载请务必保留本文链接:https://go.coder-hub.com/76386819.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定