生锈是一种新语言,已经有了很好的教科书。但有时它的教科书很难,因为它们是为以英语为母语的人准备的。现在很多公司和个人都在学习“生锈”,用一本有简单英语的书可以学得更快。这本教材是为这些公司和个人用简单的英语学习的。
也许您还不想安装铁锈,这也没关系。你可以去https://play.rust-lang.org/开始写“锈”。您可以在那里编写代码,然后单击Run查看结果。
如果希望代码更快,请将Debug更改为Release。调试:编译速度较快,运行速度较慢,包含调试信息。版本:编译速度较慢,运行速度较快,删除调试信息。
单击共享以获取URL。如果需要帮助,您可以使用它来共享您的代码。
如果您想安装铁锈,请访问此处https://www.rust-lang.org/tools/install并按照说明操作。通常,您将使用Rustup来安装和更新Rust。
Ruust具有称为基元类型的简单类型。我们将从整数开始。整数是没有小数点的整数。有两种类型的整数:
符号表示+(加号)和-(减号),因此带符号的整数可以是正的,也可以是负的(例如+8,-8)。但无符号整数只能为正,因为它们没有符号。
有符号整数是:i8、i16、i32、i64、i128和isize。无符号整数是:u8、u16、u32、u64、u128和usize。
I或u后面的数字表示该数字的位数,因此位数越多的数字可能越大。8位=一个字节,所以i8是一个字节,i64是8个字节,依此类推。大小较大的数字类型可以容纳较大的数字。例如,U8最多可以容纳255个人,而U16最多可以容纳65535个人。U128最多可容纳340282366920938463463374607431768211455。
那么什么是isize和usize呢?这意味着您的计算机类型上的位数。(这称为计算机的体系结构。)。因此,32位计算机上的isize和usize类似于i32和u32,而64位计算机上的isize和usize类似于i64和u64。
造成不同类型整数的原因有很多。其中一个原因是计算机性能:字节数越少,处理速度越快。但这里还有其他一些用途:
铁锈中的字符称为字符。U8数字只会上升到255,Unicode和ASCII对这些数字使用相同的数字。这意味着Rust可以使用AS安全地将U8转换为char。(将U8转换为字符意味着";假设U8是字符";)。
使用AS进行强制转换非常有用,因为Rust始终需要知道整数的类型。例如,这将不会编译:
Fn main(){让my_number=100;//我们没有编写整数类型,//所以Rust选择I32。Rust Always//如果您不告诉它使用不同类型的println!(";{}&34;,my_number as char);}。
错误[E0604]:只能将`u8`转换为`char`,不能转换为`i32`-->;src\main.rs:3:20|3|println!(";{}";,my_number为char);|^。
解决此问题的一个简单方法是使用AS。首先,我们使用As将my_number设置为U8,然后再使用一个AS将其设置为char。现在它将编译:
所有字符均为4个字节。它们是4个字节,因为字符串中的某些字符多于一个字节。例如:
Fn Main(){let Slice=";Hello!";;println!(";Slice为{:?}字节。";,std::Mem::Size_of_val(Slice));//std::Mem::Size_of_val提供以字节为单位的大小LetSlice2=";안녕!";;//韩语for";hi";println!(";,std::mem::size_of_val(Slice2));}。
Slice的长度为6个字符和6个字节,而Slice2的长度为3个字符和7个字节。Char需要适合任何语言的任何字符,所以它是4字节长。
类型推断意味着,如果您不告诉编译器类型,但是编译器可以自己决定,那么它就会决定。编译器总是需要知道变量的类型,但您并不总是需要告诉它。例如,如果MY_NUMBER=8,则MY_NUMBER将是I32。这是因为如果您不告诉它,编译器会选择I32作为整数。但是如果您说让my_number:u8=8,它会使my_number变成U8,因为您告诉它U8。
所以通常编译器可以猜到。但有时你需要说出来,原因有两个:
您正在做一件非常复杂的事情,而编译器并不知道您想要的类型。
对于数字,你可以在数字后面说类型。您不需要空格,只需在数字后面键入即可。
如果您想使数字易于阅读,还可以添加_。
Fn main(){LET Small_Number=10_U8;//这个更容易读,让BIG_Number=100_000_000_I32;//1亿用_}容易读。
_不会更改数字。只是为了方便您阅读。不管你使用了多少,这都无关紧要:
Fn main(){let number=0_U8;let number 2=1_6_2_4_I32;println!(";{},{}";,number,number 2);}。
浮点数是带小数点的数字。5.5是浮点数,6是整数。5.0也是浮点数,甚至5.也是浮点数。
Fn main(){设MY_FLOAT=5。;//Rust参见。并且知道它是一个浮点数}。
但是这些类型不被称为浮点,它们被称为F32和F64。它与整数相同:f后面的数字表示位数。如果你不写字体,拉斯特会选择F64。
当然,只有相同类型的浮点才能一起使用。因此,您不能将F32添加到F64。
Fn main(){让MY_FLOAT:F64=5.0;//这是F64让MY_OTHER_FLOAT:F32=8.5;//这是F32让Third_Float=My_Float+My_Other_Float;}
错误[E0308]:类型不匹配-->;src\main.rs:5:34|5|let Third_Float=MY_FLOAT+MY_OTHER_FLOAT;|^需要`f64`,找到的是`f32`。
当您使用错误的类型时,编译器会写入';';';';';';';';';期望的(Type),发现(Type)';。它按如下方式读取您的代码:
让MY_FLOAT:F64=5.0;//编译器看到F64,让MY_OTHER_FLOAT:F32=8.5;//编译器看到F32。它是一种不同的类型。让Third_Float=MY_FLOAT+//编译器看到一个新变量。它必须是一个F64加另一个F64。现在它预计会有一架F64型的.。让Third_Float=MY_FLOAT+MY_OTHER_FLOAT;//但是找到了F32。它不能添加它们。
因此,当您看到";Expect(Type)、Found(Type)";时,您必须找出编译器为什么需要不同的类型。
当然,简单的数字很容易修正。您可以使用AS将F32转换为F64:
Fn main(){让My_Other_Float:F64=5.0;让My_Other_Float:F32=8.5;让Third_Float=My_Float+My_Other_Float As F64;//My_Other_Float As F64=像F64一样使用My_Other_Float}。
或者更简单地,删除类型声明。铁锈将选择可以相加的类型。
Fn main(){让MY_FLOAT=5.0;//Rust将选择F64让MY_OTHER_FLOAT=8.5;//这里再次选择F64,让Third_Float=My_Float+My_Other_Float;}
Fn main(){让MY_FLOAT:F32=5.0;让MY_OTHER_FLOAT=8.5;//Rust会选择F32,让Third_Float=My_Float+My_Other_Float;//因为它知道您需要将其添加到F32}。
普林特恩!是打印到控制台的宏。宏就像一个为您编写代码的函数。宏有一个!跟在他们后面。我们稍后将学习如何制作宏。现在,请记住这一点!表示它是宏。
要了解;,我们将创建另一个函数。首先,在Main中,我们将打印数字8:
Println中的{}!意思是将变量放在这里。这将打印Hello world编号8。
这还会打印您好,世界编号8!当Rust查看number()时,它看到了一个函数。此函数用于:
函数内部只有8。因为没有;,所以这是它返回的值。如果它有;,则不会返回任何内容。如果Rust包含;,则不会编译此代码,因为返回的是I32和;return(),而不是I32:
5|fn number()->;I32{|-^预期`i32`,找到`()`|隐式返回`()`,因为其正文没有尾部或`rereturn`表达式6|8;|-help:考虑删除此分号。
这意味着您告诉我number()返回一个I32,但是您添加了一个;,所以它不会返回任何";。因此编译器建议删除分号。
您也可以编写Return 8;但在Rust中,只删除;返回是正常的。
当您想要为函数提供变量时,请将它们放在()中。您必须给它们一个名称并写出类型。
Fn main(){Multiply(8,9);//我们可以直接给出数字,让SOME_NUMBER=10;//也可以声明两个变量,让SOME_OTHER_NUMBER=2;Multiply(SOME_NUMBER,SOME_OTHER_NUMBER);//将它们放入函数}FN Multiply(NUMBER_ONE:I32,NUMBER_2:I32){//两个i32将进入函数。我们称他们为一号和二号。设result=number_one*number_Two;println!(";{}次{}is{}";,number_one,number_Two,result);}。
Fn main(){let multiply_result=Multiply(8,9);//我们使用Multiply()打印并将结果交给Multiply_Result}fn Multiply(number_one:I32,number_Two:I32)->;I32{let result=number_one*number_Two;println!(";{}次{}is{}";,number_one,number_2,result);result//这是I32。
使用let声明一个变量(声明一个变量=告诉Rust生成一个变量)。
变量在代码块{}内开始和结束。在本例中,my_number在我们调用println!之前结束,因为它在自己的代码块中。
Fn main(){{let my_number=8;//my_number从这里开始//my_number在这里结束!}println!(";Hello,number{}";,my_number);//没有my_number,//println!()找不到}。
Fn main(){let my_number={let Second_number=8;Second_number+9//没有分号,因此代码块返回8+9。//它的工作方式与函数一样};println!(";我的编号是:{}";,my_number);}
Fn main(){let my_number={let Second_number=8;//声明Second_Number,Second_Number+9;//将9加到Second_Number//但我们没有返回它!//Second_Number Now};println!(";My Number is:{:?}";,My_Number);//My_Number is()}。
那么为什么我们写的是{:?}而不是{}?我们现在就来谈谈这个问题。
Rust中的简单变量可以在println!()中打印{}。但是有些变量不能,您需要调试打印。调试打印是为程序员打印的,因为它通常会显示更多信息。DEBUG有时看起来并不美观,因为它有额外的信息可以帮助您。
您如何知道您是否需要{:?}而不需要{}?编译器会告诉您。例如:
错误[E0277]:`()`没有实现`std::fmt::Display`-->;src\main.rs:3:41|3|println!(";这不会打印:{}";,dots_print);|^FMT::FMT::Help:特性`std::fmt::Display`没有为`()`。
这是大量的信息。但重要的是:您可以使用`{:?}`(或者{:#?}来表示漂亮的打印效果)。这意味着您可以尝试{:?},也可以尝试{:#?}({:#?}以不同的格式打印)。
还有一件事:如果您不想换一行,也可以不带ln使用print!()。
Fn main(){print!(";这不会打印新行";);println!(";所以这将在同一行";);}
此操作将打印此命令,而不会打印新行,因此此命令将在同一行上。
如果您想查看最小和最大的数字,可以使用MIN和MAX。
Fn main(){println!(";最小的i8是{},最大的i8是{}。";,std::i8::min,std::i8::max);println!(";最小的U8是{},最大的U8是{}。";,std:u8:min,std::u8::max);println!(";最小的i8。,std::i16::min,std::i16::max);println!(";最小的u16为{},最大的u16为{}。";,std::u16::min,std::u16::max);println!(";最小的I32为{},最大的I32为{}。";,STD::I32:MIN,STD:I32:最小的u32为{},最大的u32为{}。";,std::u32::min,std::u32::max);println!(";最小的i64为{},最大的i64为{}。";,std::i64::min,std::i64::max);println!(";最小的u64为{},最大的u64为{}。。Println!(";最小的i128为{},最大的i128为{}。";,std::i128::min,std::i128::max);println!(";最小的u128为{},最大的u128为{}。";,std::u128::min,std::u128::max);}。
最小的i16为-32768,最大的i16为32767;最小的i16为0,最大的i16为65535;最小的i32为-2147483648,最大的i32为2147483647;最小的u32为0,最大的u32为4294967295。最小的i64为-9223372036854775808。最小的u128为0,最大的u128为340282366920938463463374607431768211455。
编译器显示:错误[E0384]:不能将两次赋值给不可变变量`MY_NUMBER。这是因为如果只编写let,变量是不可变的。
您将看到来自编译器的相同";预期&34;消息:期望的整数,找到`&;str````。&;str```是我们将很快学习的字符串类型。
隐藏意味着使用let声明一个与另一个变量同名的新变量。它看起来像是变化无常,但它是完全不同的。阴影如下所示:
Fn main(){设my_number=8;//这是I32 println!(";{}";,my_number);//打印8设my_number=9.2;//这是F64。它不是my_number-它是完全不同的!Println!(";{}";,my_number)//打印9.2}
那么第一个my_number被销毁了吗?不是,但是当我们调用my_number时,我们现在得到的my_number是F64。因为它们在同一个作用域块中,所以我们再也看不到第一个my_number了。
Fn main(){let my_number=8;//这是I32 println!(";{}";,my_number);//打印8{let my_number=9.2;//这是F64。它不是my_number-它是完全不同的!Println!(";{}";,my_number)//打印9.2//但是阴影的my_number只存在到这里。//第一个my_number还活着!}println!(";{}";,my_number);//打印8}。
那么,跟踪的好处是什么呢?当您需要大量更改变量时,隐藏是很好的。
Fn main(){let inal_number={let y=10;let x=9;//x从9let x=Times_Two(X);//Shadow with new x:18 let x=x+y;//Shadow with new x:28 x//return x:inal_number现在是x的值};println!(";现在数字是:{}";,inal_number)}fn Times_Two(number:I32)->;I32{编号*2}。
如果没有影子,您将不得不考虑不同的名称,即使您并不关心x:
Fn main(){//假装我们使用的是无阴影的铁锈let Final_Number={设y=10;设x=9;//x从9let x_Two=Times_Two(X);//x的第二个名称let x_Two_and_y=x+y;//x_Two_and_y//糟糕的是我们没有阴影-我们本可以只使用x};println!(";,Final_Number)}Fn次_Two(编号:I32)->;I32{编号*2}。
堆栈和堆是保存内存的两个位置。重要区别在于:
堆栈需要知道编译时变量的大小。所以像I32这样的简单变量会被放入堆栈,因为我们知道它们的确切大小。
有些类型在编译时不知道大小。但是堆栈需要知道确切的大小。你的工作是什么?。您将数据放入堆中,因为堆可以有任意大小的数据。为了找到它,指针放在堆栈上,因为我们总是知道指针的大小。
我的BOOK第一章:我的生活第一章:我的生活第二章:我的猫15第三章:我的工作23第四章:我的家庭30第5章:未来计划43。
所以这就像是五个点。“我的生活”这一章在哪里?它在第1页(它指向第1页)。我的工作在哪里?在第23页。
铁锈中的指针通常称为引用。引用意味着你借用了价值,但你并不拥有它。在Rust中,引用有&;。所以:
这意味着MY_REFERENCE仅查看MY_VARIABLE的数据。MY_VARIABLE仍然拥有其数据。
我们认识那个王子!可以使用{}(用于显示)和{:?}(用于调试)进行打印,再加上{:#?}进行美观打印。但是还有许多其他的打印方式。
例如,如果有引用,可以使用{:p}打印指针地址。
Fn main(){let number=555;println!(";二进制:{:B},十六进制:{:x},八进制:{:O}";,number,number,number);}
Fn Main(){let Parent_Name=";Vlad&34;;let Son_Name=";Adrian Fahrenheit";;let Family_Name=";ȚEPEș";;println!(";这是{1}{2},{0}{2}的儿子。";,父亲名称,儿子名称,家庭名称);}。
父亲名称在位置0,儿子名称在位置1,家庭名称在位置2。所以它会打印这是Adrian FahrenheitȚepeș,VladȚepeș的儿子。
可能您有一个非常复杂的字符串要打印,并且想要将名称添加到{}。您可以这样做:
Fn main(){println!(";{City1}位于{Country},{City2}也位于{Country},但{City3}不在{Country}。";,City1=";首尔&34;,City2=";釜山";,City3=";东京";,Country=";Korea";);}。
非常复杂的印刷在“铁锈”中用得不多。但这里是如何做到这一点的。
例如,如果我要编写左侧有5个ㅎ字符,右侧有5个ㅎ字符的";a";:
这将打印ㅎaㅎ。让我们从1)到5)来看看这一点。
是否需要变量名?{:ㅎ^11}无变量名:位于:之前。
是否需要填充字符?{:ㅎ^11}是。ㅎ在:之后,有一个^。<;表示左侧填充字符,>;表示右侧填充,^表示中间填充。
是否需要最小长度?{:ㅎ^11}是:后面有一个11。
是否需要最大长度?{:ㅎ^11}否:没有带.的数字。在此之前。
Fn main(){let title=";Today';S news";;println!(";{:-^30}";,title);//没有变量名称,垫上-,居中,30个字符长度的字母栏=";|";;println!(";{:<;15}{:>;15}";,bar,bar);//无变量名称,填充空格,每个15个字符,左1个,右1个字母a=";首尔";;让b=";Tokyo";;println!(";{City1:-<;15}{City2:->;15}";,City1=a,City2=b);//变量名称City1和City2,用-填充,左1个。
&;str是一个简单字符串。当您编写let my_Variable=";Hello,world!";时,您将创建一个&;字符串。A&A;STR非常快。
字符串是一个更复杂的字符串。速度有点慢,功能也比较多。字符串是指针,数据位于堆上。
Fn Main(){let Name=";서태지";;//这是韩文名称。没问题,因为a&;str是UTF-8。让其他人。
.