正版rust30005_Rust语言开发基础(五)语言数据类型

一. 基本介绍虽然是静态类型语言,但是定义变量,不用定义类型,只用关键字声明即可,即用关键字 let ,Rust 有类型推断,用以平衡强大的静态类型和冗长标注类型。

let x = "hello, world!";

let a="foobar";

let b="foo\

bar";

let mut x = vec!["Hello", "world"];  使用名字叫“vec”的宏(感叹号表示宏),将这个宏绑定到一个叫“x”的变量上。

Rust 更倾向于堆栈分配而不是堆分配:x 被直接放置在堆栈中。然而,Vec 类型是在堆上分配的向量元素的空间。

这个let体现的是Rust中的“所有权”概念。

我们将Rust语言类型分为两种来说明,即基本类型和集合。

二. 基本类型

1.字符和字符串

字符类型     :let a = 'b';

字符串类型  : let a = "abcdef";

行类型        : let a = r#abcdef#;

字节字符类型   :let a = b'a';

字节字符串类型:let a = b"abcdef";

字节行类型      : let a = br#abcdef#;

前缀b=bite字节, r=row行

\字符串换行符,也是转义字符的标识。

let a = "foobar";

let b = "foo\

bar";

a和b是相等的字符串。

Rust包含2个字符串类型:String 和 &str

A. &str称为“字符串切片”,固定大小,并且不可改变(string slice )。

比如: let a = "hello world"  //那么a就是一个字符串切片

"hello world" 是一个“本义字符串”(string literal,即直接双引号内拼写出来的字符串)并且是静态的字符串,一个“本义字符串”属于是一个字符串切片,是静态分配的,它被保存在编译的程序中,在整个程序运行过程都存在,类似java中的静态变量,那么a呢,就是一个绑定,换个说法,就是一个引用,引用那个静态分配的字符串,所有功能想要得到一个字符串切片的,都会得到一个“本义字符串”。

为什么作者要称这个为字符串切片(slice)呢?是因为这种字符是随时可以切成一个一个字符的!

B. String堆分配,可增长,保证是UTF-8编码,通常是由一个字符串切片通过to_string方法强制转换过来的。

let mut s = "Hello".to_string();  // mut s: String

println!("{}", s);

s.push_str(", world."); //增加值,即可增长

println!("{}", s);

使用一个&符号可以将Strings类型强制转换为&str类型

fn takes_slice(slice: &str) {

println!("Got: {}", slice);

}

fn main() {

let s = "Hello".to_string();

takes_slice(&s);

}

关键点:记住String类型分配内存控制它的数据, &str是一个指向另一个字符串的引用,知道这些就可以了。

String 转换成 &str内存成本是比较低的,但是 &str 转换成 String 因为涉及到内存分配,转换成本比较高,所以如果没有必要不要去转换。

usestd::net::TcpStream;

TcpStream::connect("192.168.0.1:3000"); // &str parameterletaddr_string="192.168.0.1:3000".to_string();

TcpStream::connect(&*addr_string); // 转换 addr_string 到 &str

总结:str 是不可变的字符串;

std::String 是可变的字符串;

std::ffi::CStr 用于表示由C分配、rust借用的C字符串;

std::ffi::CString 用于表示由rust分配、可以传递给C函数使用的C字符串;

std::ffi::OsStr 平台相关的字符串,具体看 rust/os_str.rs at master · rust-lang/rust · GitHub;

std::ffi::OsString 这个是上面的可变版本;

std::path::Path 用来表示路径,方法和普通字符串不一样,当然独立出来;

std::path::PathBuf 这是Path的可变版本;

总之普通字符串就用str和String,路径就用Path和PathBuf,其他是ffi才需要用到的。

OsStr/OsString 这两个都是为 Path 而存在

2. 数值

十进制整型(Decimal integer):98_222

十六进制整型(Hex integer)   :0xff

八进制整型(Octal integer)    :0o77

二进制整型(Binary integer)   :0b1111_0000

浮点型(Floating-point)         :123.0E+77

数值的后缀

Integer Floating-point

u8, i8, u16, i16, u32, i32, u64, i64, isize, usize f32, f64

数值后缀标明该数值的存储空间

比如整型的数值

123i32;                            // type i32

123u32;                            // type u32

123_u32;                           // type u32

0xff_u8;                           // type u8

0o70_i16;                          // type i16

0b1111_1111_1001_0000_i32;         // type i32

0usize;                            // type usize

默认是i32

浮点型的后缀

123.0f64;        // type f64

0.1f64;          // type f64

0.1f32;          // type f32

12E+99_f64;      // type f64

let x:f64=2.;    // type f64

默认是f64

3. 布尔值

true and false

三、集合

1. 数组特性:固定大小,存放同类型元素,不可变。

let a = [1, 2, 3];     //数组类型是 a: [i32; 3]

let mut m = [1, 2, 3];    //数组类型是 mut m: [i32; 3]

A. 数组类型的表达--[T;N] 其中T指泛型。

B. 数组简单初始化方法:let a = [0; 20]; // a: [i32; 20],即初始化20个元素,每个元素为0。

C. 数组长度:a.len()。

D. 数组遍历:

let a = [1, 2, 3];

println!("a has {} elements", a.len());

for e in a.iter() {

println!("{}", e);

}

E. 数组特定访问:

let names = ["Graydon", "Brian", "Niko"];   // names: [&str; 3]

println!("The second name is: {}", names[1]);  // 注意下标也是从0开始

2. 向量特性:可增长的数组, 可变并且自动增长,内存堆分配,类似字符串当中 与&str对应的String,可用宏vec!创建。

let v = vec![1, 2, 3]; // v: Veclet mut nums = vec![1, 2, 3]; // mut nums: Vec

nums.push(4);

println!("The length of nums is now {}", nums.len()); // Prints 4

3. 切片特性:是引用(查看)一个数组部分数据,对于需要安全,高效访问数组的部分数据十分有用,并且不需 要拷贝。例如,你只想将一个文件的一行数据读进内存。

切片不是凭空创建的,而是来自一个存在的变量,切 片有长度,可变或者不可变都可以,使用的方式类似数组:

let a = [0, 1, 2, 3, 4];

let middle = &a[1..4];      // a的切片。包含元素1,2,3  范围是[ )  实-虚

for e in middle.iter() {

println!("{}", e); // Prints 1, 2, 3

}

4. 元组元组是一个有固定大小的有序列表,里面可以存放任何数据类型的值

let x = (1,"hello") //简单元组

let x: (i32,&str) = (1,"hello");   // 有说明数据类型的元组

let (x,y,z)=(1,2,3);   //模糊匹配,同时初始化3个变量

println!("x is {}",x);

A. 元组的分配引用let mut x = (1, 2); // x: (i32, i32)

let y = (2, 3); // y: (i32, i32)

x = y;

B. 元组的判断let x = (1, 2, 3);

let y = (2, 2, 4);

if x == y {

println!("yes");

} else {

println!("no");

}

C. 用于函数返回多个值fn next_two(x: i32) -> (i32, i32) { (x + 1, x + 2) }

fn main() {

let (x, y) = next_two(5);

println!("x, y = {}, {}", x, y);

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值