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

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

expected type 'i32', found 'usize'

问题

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

  1. const std = @import("std");
  2. const allocator = std.heap.page_allocator;
  3. fn two_sum(nums: []i32, target: i32) []i32{
  4. var map = std.AutoArrayHashMap(i32, i32).init(allocator);
  5. defer map.deinit();
  6. var res = [2]i32{-1, -1};
  7. for (nums, 0..) |n, i| { // n是数字;i是索引
  8. if (map.get(target - n)) |v| {
  9. res[0] = v;
  10. res[1] = @as(i32, i);
  11. return &res;
  12. }
  13. try map.put(n, @as(i32, i));
  14. }
  15. return &res;
  16. }
  17. pub fn main() !void {
  18. var arr = [_]i32{1, 5, 8, 9, 6};
  19. var x = two_sum(&arr, 9);
  20. for (x) |n| {
  21. std.debug.print("{d}", .{n});
  22. }
  23. }

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

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

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

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

  1. 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:

  1. const std = @import("std");
  2. const allocator = std.heap.page_allocator;
  3. fn two_sum(nums: []i32, target: i32) []i32{
  4. var map = std.AutoArrayHashMap(i32, i32).init(allocator);
  5. defer map.deinit();
  6. var res = [2]i32{-1, -1};
  7. for (nums, 0..) |n, i| { // n is the number; i is the index
  8. if (map.get(target - n)) |v| {
  9. res[0] = v;
  10. res[1] = @as(i32, i);
  11. return &res;
  12. }
  13. try map.put(n, @as(i32, i));
  14. }
  15. return &res;
  16. }
  17. pub fn main() !void {
  18. var arr = [_]i32{1, 5, 8, 9, 6};
  19. var x = two_sum(&arr, 9);
  20. for (x) |n| {
  21. std.debug.print("{d}", .{n});
  22. }
  23. }

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

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

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发布的代码的版本。

  1. const std = @import("std");
  2. const allocator = std.heap.page_allocator;
  3. fn two_sum(nums: []i32, target: i32) ![][2]i32 { // 返回错误联合
  4. var map = std.AutoArrayHashMap(i32, i32).init(allocator);
  5. defer map.deinit();
  6. var res = [2]i32{ -1, -1 };
  7. for (nums, 0..) |n, i| {
  8. if (map.get(target - n)) |v| {
  9. res[0] = v;
  10. res[1] = @intCast(i32, i); // 使用`@intCast`而不是`@as`
  11. return res; // 只返回数组
  12. }
  13. try map.put(n, @intCast(i32, i)); // 使用`@intCast`而不是`@as`
  14. }
  15. return res; // 只返回数组
  16. }
  17. pub fn main() !void {
  18. var arr = [_]i32{1, 5, 8, 9, 6};
  19. var x = try two_sum(&arr, 9); // `two_sum`返回错误联合
  20. for (x) |n| {
  21. std.debug.print("{d}", .{n});
  22. }
  23. std.debug.print("\n", .{});
  24. }
英文:

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.

  1. const std = @import("std");
  2. const allocator = std.heap.page_allocator;
  3. fn two_sum(nums: []i32, target: i32) ![2]i32 { // return error union
  4. var map = std.AutoArrayHashMap(i32, i32).init(allocator);
  5. defer map.deinit();
  6. var res = [2]i32{ -1, -1 };
  7. for (nums, 0..) |n, i| {
  8. if (map.get(target - n)) |v| {
  9. res[0] = v;
  10. res[1] = @intCast(i32, i); // use `@intCast` instead of `@as`
  11. return res; // just return the array
  12. }
  13. try map.put(n, @intCast(i32, i)); // use `@intCast` instead of `@as`
  14. }
  15. return res; // just return the array
  16. }
  17. pub fn main() !void {
  18. var arr = [_]i32{1, 5, 8, 9, 6};
  19. var x = try two_sum(&arr, 9); // `two_sum` returns an error union
  20. for (x) |n| {
  21. std.debug.print("{d}", .{n});
  22. }
  23. std.debug.print("\n", .{});
  24. }

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:

确定