文章目录

Rust 数据类型:i32、String、Vec<T>

发布于 2026-04-04 08:37:36 · 浏览 2 次 · 评论 0 条

Rust 数据类型:i32、String、Vec<T>

Rust 语言通过其严格但友好的类型系统,在保证内存安全的同时提供高性能。掌握核心数据类型是编写可靠 Rust 程序的第一步。本文聚焦三种最常用类型:i32(有符号整数)、String(可变字符串)和 Vec<T>(动态数组),手把手教你如何声明、初始化、修改和使用它们。


使用 i32 表示整数

i32 是 Rust 中默认的有符号 32 位整数类型,取值范围为 -2,147,483,648 到 2,147,483,647。它适用于大多数需要整数的场景,比如计数、索引或数学计算。

声明并初始化一个 i32 变量

  1. 输入 let age: i32 = 25; —— 这里显式标注类型为 i32
  2. 或者省略类型,直接写 let score = 100i32; —— 通过字面量后缀 i32 推断类型。
  3. 也可以让编译器自动推断let count = 42;,只要后续使用中能确定是整数,Rust 会默认选 i32

对 i32 执行基本运算

  1. 加法let total = 10i32 + 20;
  2. 减法let diff = 50 - 30i32;
  3. 乘法与除法let result = (100i32 * 2) / 5;
  4. 注意:Rust 不会自动转换类型。若混合不同类型(如 i32u32),必须显式转换,例如 a as i32

检查溢出行为(开发时):

  • 在 debug 模式下,整数溢出会 panic(程序崩溃)。
  • 在 release 模式下,默认采用“环绕”行为(如 i32::MAX + 1 变成 i32::MIN)。
  • 若需显式处理溢出,使用 checked_add() 等安全方法:
    let a = i32::MAX;
    let b = 1i32;
    match a.checked_add(b) {
        Some(sum) => println!("Sum: {}", sum),
        None => println!("Overflow!"),
    }

使用 String 存储文本

Rust 的 String 类型是堆分配的、可增长的、UTF-8 编码的字符串。它与不可变的字符串字面量 &str 不同,专用于需要修改或动态构建文本的场景。

创建一个 String

  1. 从空字符串开始let mut s = String::new();
  2. 从字符串字面量转换let s = "hello".to_string();
  3. 或使用 from 方法let s = String::from("world");

向 String 添加内容

  1. 追加另一个字符串调用 push_str 方法:
    let mut s = String::from("Hello");
    s.push_str(", Rust!");
    // s 现在是 "Hello, Rust!"
  2. 追加单个字符使用 push 方法:
    let mut s = String::from("Hi");
    s.push('!');
    // s 现在是 "Hi!"
  3. 拼接两个 String使用 + 运算符(注意所有权转移):
    let s1 = String::from("Hello");
    let s2 = String::from("World");
    let s3 = s1 + &s2; // s1 被 move,不能再用;s2 仅被借用

重要规则

  • String 是可变的,但必须显式声明为 mut 才能修改。
  • Rust 的字符串始终是合法的 UTF-8,任何操作都不会破坏编码。
  • 避免频繁拼接大量字符串,性能较差;可改用 format! 宏或 String::with_capacity 预分配空间。

使用 Vec<T> 管理动态数组

Vec<T>(读作“vector of T”)是 Rust 的标准动态数组类型,可在运行时增长或缩小,存储任意相同类型的元素。

创建一个 Vec<T>

  1. 创建空向量(需指定类型):
    let mut numbers: Vec<i32> = Vec::new();
  2. 使用宏快速初始化
    let colors = vec!["red", "green", "blue"]; // 类型自动推断为 Vec<&str>
  3. 预分配容量以提升性能
    let mut v = Vec::with_capacity(10); // 预留空间,避免频繁重分配

向 Vec 添加和访问元素

  1. 在末尾添加元素调用 push
    let mut nums = vec![1, 2, 3];
    nums.push(4); // nums 现在是 [1, 2, 3, 4]
  2. 通过索引读取元素使用方括号
    let first = nums[0]; // 获取第一个元素(索引从 0 开始)
  3. 安全访问(避免 panic)使用 get 方法返回 Option
    match nums.get(10) {
        Some(value) => println!("Value: {}", value),
        None => println!("Index out of bounds"),
    }

修改和删除元素

  1. 修改指定位置的值
    nums[0] = 100; // 将第一个元素改为 100
  2. 移除最后一个元素调用 pop
    let last = nums.pop(); // 返回 Option<i32>
  3. 移除中间元素(代价较高,因需移动后续元素):
    let removed = nums.remove(1); // 移除索引 1 处的元素

遍历 Vec

  • 只读遍历
    for num in &nums {
        println!("{}", num);
    }
  • 可变遍历(修改每个元素):
    for num in &mut nums {
        *num += 1; // 解引用后加 1
    }

类型之间的典型协作场景

在实际程序中,这三种类型经常一起使用。例如,解析用户输入的一串数字并存储:

use std::io;

fn main() {
    let mut input = String::new();
    io::stdin().read_line(&mut input).expect("Failed to read line");

    let numbers: Vec<i32> = input
        .trim()
        .split_whitespace()
        .map(|s| s.parse().expect("Not a number"))
        .collect();

    println!("You entered: {:?}", numbers);
}

执行流程如下:

  1. 创建 String 存储用户输入。
  2. 读取一行文本到该 String
  3. 分割字符串为单词,并将每个单词 解析为 i32
  4. 收集结果Vec<i32> 中。

此例展示了 String 作为输入缓冲区、i32 作为数值载体、Vec<i32> 作为容器的协同工作方式。


常见错误与规避方法

下表总结新手在使用这三种类型时常犯的错误及解决方案:

错误现象 原因 正确做法
编译报错 “cannot find method push_str on type &str 试图在字符串字面量(&str)上调用 push_str 先转换为 Stringlet mut s = "hello".to_string();
“mismatched types” when adding numbers 混用了 i32u32 等不同整数类型 统一类型,或显式转换:a as i32
程序 panic:“index out of bounds” vec[index] 访问不存在的索引 改用 vec.get(index) 并处理 None
“cannot borrow as mutable” 忘记将变量声明为 mut let mut v = Vec::new(); 而非 let v = ...

记住:Rust 的编译器错误信息非常精准。遇到问题时,仔细阅读错误提示,通常能直接定位到类型不匹配或可变性缺失的问题。


评论 (0)

暂无评论,快来抢沙发吧!

扫一扫,手机查看

扫描上方二维码,在手机上查看本文