【问题标题】:How to create an array within a constructor in Rust如何在 Rust 的构造函数中创建数组
【发布时间】:2016-03-16 06:11:42
【问题描述】:

出于学习目的,我想将一些代码从 C 迁移到 Rust,并使我的学习库更加多语言。

问题是我知道有一种方法可以将 C 库集成到 Rust。这样我可以在 Rust 中使用 calloc 来允许创建我的数组,并在运行时指定范围。

但是我不想在这里使用calloc - 我想看看 Rust 的方式。但我也真的不想使用vec!;我之前遇到过一些愚蠢的问题,所以我还不想使用它。

代码如下:

pub struct Canvas {
    width: usize,
    height: usize,
    array: [char], // I want to declare its type but not its size yet
}

impl Canvas{
    pub fn new (&self, width: usize, height: usize) -> Canvas {
        Canvas {
            width: width,
            height: height,
            array: calloc(width, height), // alternative to calloc ?            }
    }
}

我希望我的问题对于 Rust 的代码方式仍然是惯用的。

【问题讨论】:

    标签: arrays rust calloc


    【解决方案1】:

    我想用坐标样式访问那个数组

    这样的?

    pub struct Canvas {
        width: usize,
        height: usize,
        data: Vec<u8>,
    }
    
    impl Canvas {
        pub fn new(width: usize, height: usize) -> Canvas {
            Canvas {
                width: width,
                height: height,
                data: vec![0; width*height],
            }
        }
    
        fn coords_to_index(&self, x: usize, y: usize) -> Result<usize, &'static str> {
            if x<self.width && y<self.height {
                Ok(x+y*self.width)
            } else {
                Err("Coordinates are out of bounds")
            }
        }
    
        pub fn get(&self, x: usize, y: usize) -> Result<u8, &'static str> {
            self.coords_to_index(x, y).map(|index| self.data[index])
        }
    
        pub fn set(&mut self, x: usize, y: usize, new_value: u8) -> Result<(), &'static str>{
            self.coords_to_index(x, y).map(|index| {self.data[index]=new_value;})
        }
    }
    
    fn main() {
        let mut canvas = Canvas::new(100, 100);
        println!("{:?}", canvas.get(50, 50)); // Ok(0)
        println!("{:?}", canvas.get(101, 50)); // Err("Coordinates are out of bounds")
        println!("{:?}", canvas.set(50, 50, 128)); // Ok(())
        println!("{:?}", canvas.set(101, 50, 128)); // Err("Coordinates are out of bounds")
        println!("{:?}", canvas.get(50, 50)); // Ok(128)
    }
    

    【讨论】:

    • 正是我想要的!!
    • 对于“内置”的感觉,请注意IndexIndexMut 的存在,这可以实现(usize, usize)。他们不能报告错误,所以他们会补充你在这里写的方法,然后你可以使用canvas[(50,50)] = 128
    【解决方案2】:

    首先,我深深地怀疑你不想要char;我假设你想要一个“字节数组”,在这种情况下你想要u8

    其次,你不能真的像这样使用[u8]。我不打算讨论为什么,因为那只会破坏答案。现在:如果您看到[T] 没有在某种引用或指针后面,那可能是个错误。

    最后,这就是Vec 的用途;用它。您说您不想使用它,但没有说明原因。 Vec 在 Rust 中如何分配动态大小的数组。如果您尝试分配与 C 中完全相同的结构兼容的结构,那么问题会发生很大变化,您应该明确这一点。

    假设你想要的是在 C 中做的“Rust 等价物”:

    pub struct Canvas {
        width: usize,
        height: usize,
        array: Vec<u8>,
    }
    
    impl Canvas {
        pub fn new(width: usize, height: usize) -> Canvas {
            Canvas {
                width: width,
                height: height,
                array: vec![0; width*height],
            }
        }
    }
    

    【讨论】:

    • 好的,那么我将使用 vec!宏。但我和他们相处得不是很好。当我构造宽度为 10、高度为 10 的画布时,“数组”绑定将保存一个长度为 100(索引范围 0-99)的 vec。使用此 API 后,我想使用 array[99] 访问数组的第 99 个索引 - 到目前为止没问题。但是,当我想使用多维数组的坐标样式访问该数组时,我必须执行 array[9][9] 这是不可能的,并且 array[9*9] 将导致 array[81] 而不是 9 in宽度和高度 9 ......这就是我在这里遇到的问题 tbh
    • @xetra11 将平面数组视为二维数组可以通过简单的算术来完成(例如,x + y*width,以行优先顺序(我认为这就是它的名称))。
    • 修复 pub fn new(&amp;self, width: usize, height: usize)pub fn new(width: usize, height: usize)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-21
    • 2013-08-24
    相关资源
    最近更新 更多