英文:
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
,而您不能使用@as
将usize
转换为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", .{});
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论