This commit is contained in:
sunface
2025-04-25 12:48:03 +08:00
commit 987c59ed75
143 changed files with 44104 additions and 0 deletions

459
compound-types/string.html Normal file
View File

@@ -0,0 +1,459 @@
<!DOCTYPE HTML>
<html lang="en" class="light sidebar-visible" dir="ltr">
<head>
<!-- Book generated using mdBook -->
<meta charset="UTF-8">
<title>string - Rust By Practice</title>
<!-- Custom HTML head -->
<meta name="description" content="Learn Rust with Example, Exercise and real Practice, written with ❤️ by https://course.rs team">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#ffffff">
<link rel="icon" href="../favicon.svg">
<link rel="shortcut icon" href="../favicon.png">
<link rel="stylesheet" href="../css/variables.css">
<link rel="stylesheet" href="../css/general.css">
<link rel="stylesheet" href="../css/chrome.css">
<link rel="stylesheet" href="../css/print.css" media="print">
<!-- Fonts -->
<link rel="stylesheet" href="../FontAwesome/css/font-awesome.css">
<link rel="stylesheet" href="../fonts/fonts.css">
<!-- Highlight.js Stylesheets -->
<link rel="stylesheet" id="highlight-css" href="../highlight.css">
<link rel="stylesheet" id="tomorrow-night-css" href="../tomorrow-night.css">
<link rel="stylesheet" id="ayu-highlight-css" href="../ayu-highlight.css">
<!-- Custom theme stylesheets -->
<link rel="stylesheet" href="../theme/style1.css">
<!-- Provide site root and default themes to javascript -->
<script>
const path_to_root = "../";
const default_light_theme = "light";
const default_dark_theme = "navy";
</script>
<!-- Start loading toc.js asap -->
<script src="../toc.js"></script>
</head>
<body>
<div id="body-container">
<!-- Work around some values being stored in localStorage wrapped in quotes -->
<script>
try {
let theme = localStorage.getItem('mdbook-theme');
let sidebar = localStorage.getItem('mdbook-sidebar');
if (theme.startsWith('"') && theme.endsWith('"')) {
localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
}
if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
}
} catch (e) { }
</script>
<!-- Set the theme before any content is loaded, prevents flash -->
<script>
const default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? default_dark_theme : default_light_theme;
let theme;
try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
if (theme === null || theme === undefined) { theme = default_theme; }
const html = document.documentElement;
html.classList.remove('light')
html.classList.add(theme);
html.classList.add("js");
</script>
<input type="checkbox" id="sidebar-toggle-anchor" class="hidden">
<!-- Hide / unhide sidebar before it is displayed -->
<script>
let sidebar = null;
const sidebar_toggle = document.getElementById("sidebar-toggle-anchor");
if (document.body.clientWidth >= 1080) {
try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
sidebar = sidebar || 'visible';
} else {
sidebar = 'hidden';
}
sidebar_toggle.checked = sidebar === 'visible';
html.classList.remove('sidebar-visible');
html.classList.add("sidebar-" + sidebar);
</script>
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
<!-- populated by js -->
<mdbook-sidebar-scrollbox class="sidebar-scrollbox"></mdbook-sidebar-scrollbox>
<noscript>
<iframe class="sidebar-iframe-outer" src="../toc.html"></iframe>
</noscript>
<div id="sidebar-resize-handle" class="sidebar-resize-handle">
<div class="sidebar-resize-indicator"></div>
</div>
</nav>
<div id="page-wrapper" class="page-wrapper">
<div class="page">
<div id="menu-bar-hover-placeholder"></div>
<div id="menu-bar" class="menu-bar sticky">
<div class="left-buttons">
<label id="sidebar-toggle" class="icon-button" for="sidebar-toggle-anchor" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
<i class="fa fa-bars"></i>
</label>
<button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
<i class="fa fa-paint-brush"></i>
</button>
<ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
<li role="none"><button role="menuitem" class="theme" id="default_theme">Auto</button></li>
<li role="none"><button role="menuitem" class="theme" id="light">Light</button></li>
<li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
<li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
<li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
<li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
</ul>
<button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
<i class="fa fa-search"></i>
</button>
</div>
<h1 class="menu-title">Rust By Practice</h1>
<div class="right-buttons">
<a href="../print.html" title="Print this book" aria-label="Print this book">
<i id="print-button" class="fa fa-print"></i>
</a>
<a href="https://github.com/sunface/rust-by-practice" title="Git repository" aria-label="Git repository">
<i id="git-repository-button" class="fa fa-github"></i>
</a>
<a href="https://github.com/sunface/rust-by-practice/edit/master/en/src/compound-types/string.md" title="Suggest an edit" aria-label="Suggest an edit">
<i id="git-edit-button" class="fa fa-edit"></i>
</a>
</div>
</div>
<div id="search-wrapper" class="hidden">
<form id="searchbar-outer" class="searchbar-outer">
<input type="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
</form>
<div id="searchresults-outer" class="searchresults-outer hidden">
<div id="searchresults-header" class="searchresults-header"></div>
<ul id="searchresults">
</ul>
</div>
</div>
<!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
<script>
document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
});
</script>
<div id="content" class="content">
<main>
<h1 id="string"><a class="header" href="#string">String</a></h1>
<p>The type of string literal <code>"hello, world"</code> is <code>&amp;str</code>, e.g <code>let s: &amp;str = "hello, world"</code>.</p>
<h3 id="str-and-str"><a class="header" href="#str-and-str">Str and &amp;str</a></h3>
<ol>
<li>🌟 We can't use <code>str</code> type in normal ways, but we can use <code>&amp;str</code>.</li>
</ol>
<pre><pre class="playground"><code class="language-rust editable edition2021">
// Fix error without adding new line
fn main() {
let s: str = "hello, world";
println!("Success!");
}</code></pre></pre>
<ol start="2">
<li>🌟🌟 We can only use <code>str</code> by boxing it, <code>&amp;</code> can be used to convert <code>Box&lt;str&gt;</code> to <code>&amp;str</code></li>
</ol>
<pre><pre class="playground"><code class="language-rust editable edition2021">
// Fix the error with at least two solutions
fn main() {
let s: Box&lt;str&gt; = "hello, world".into();
greetings(s)
}
fn greetings(s: &amp;str) {
println!("{}",s)
}</code></pre></pre>
<h3 id="string-1"><a class="header" href="#string-1">String</a></h3>
<p><code>String</code> type is defined in std and stored as a vector of bytes (Vec<u8>), but guaranteed to always be a valid UTF-8 sequence. String is heap allocated, growable and not null terminated.</p>
<ol start="3">
<li>🌟</li>
</ol>
<pre><pre class="playground"><code class="language-rust editable edition2021">
// Fill the blank
fn main() {
let mut s = __;
s.push_str("hello, world");
s.push('!');
assert_eq!(s, "hello, world!");
println!("Success!");
}</code></pre></pre>
<ol start="4">
<li>🌟🌟🌟</li>
</ol>
<pre><pre class="playground"><code class="language-rust editable edition2021">
// Fix all errors without adding newline
fn main() {
let s = String::from("hello");
s.push(',');
s.push(" world");
s += "!".to_string();
println!("{}", s);
}</code></pre></pre>
<ol start="5">
<li>🌟🌟 <code>replace</code> can be used to replace substring</li>
</ol>
<pre><pre class="playground"><code class="language-rust editable edition2021">
// Fill the blank
fn main() {
let s = String::from("I like dogs");
// Allocate new memory and store the modified string there
let s1 = s.__("dogs", "cats");
assert_eq!(s1, "I like cats");
println!("Success!");
}</code></pre></pre>
<p>More <code>String</code> methods can be found under <a href="https://doc.rust-lang.org/std/string/struct.String.html">String</a> module.</p>
<ol start="6">
<li>🌟🌟 You can only concat a <code>String</code> with <code>&amp;str</code>, and <code>String</code>'s ownership can be moved to another variable.</li>
</ol>
<pre><pre class="playground"><code class="language-rust editable edition2021">
// Fix errors without removing any line
fn main() {
let s1 = String::from("hello,");
let s2 = String::from("world!");
let s3 = s1 + s2;
assert_eq!(s3, "hello,world!");
println!("{}", s1);
}</code></pre></pre>
<h3 id="str-and-string"><a class="header" href="#str-and-string">&amp;str and String</a></h3>
<p>Opposite to the seldom using of <code>str</code>, <code>&amp;str</code> and <code>String</code> are used everywhere!</p>
<ol start="7">
<li>🌟🌟 <code>&amp;str</code> can be converted to <code>String</code> in two ways</li>
</ol>
<pre><pre class="playground"><code class="language-rust editable edition2021">
// Fix error with at least two solutions
fn main() {
let s = "hello, world";
greetings(s)
}
fn greetings(s: String) {
println!("{}", s)
}</code></pre></pre>
<ol start="8">
<li>🌟🌟 We can use <code>String::from</code> or <code>to_string</code> to convert a <code>&amp;str</code> to <code>String</code></li>
</ol>
<pre><pre class="playground"><code class="language-rust editable edition2021">
// Use two approaches to fix the error and without adding a new line
fn main() {
let s = "hello, world".to_string();
let s1: &amp;str = s;
println!("Success!");
}</code></pre></pre>
<h3 id="string-escapes"><a class="header" href="#string-escapes">String escapes</a></h3>
<ol start="9">
<li>🌟</li>
</ol>
<pre><pre class="playground"><code class="language-rust editable edition2021">fn main() {
// You can use escapes to write bytes by their hexadecimal values
// Fill the blank below to show "I'm writing Rust"
let byte_escape = "I'm writing Ru\x73__!";
println!("What are you doing\x3F (\\x3F means ?) {}", byte_escape);
// ...Or Unicode code points.
let unicode_codepoint = "\u{211D}";
let character_name = "\"DOUBLE-STRUCK CAPITAL R\"";
println!("Unicode character {} (U+211D) is called {}",
unicode_codepoint, character_name );
let long_string = "String literals
can span multiple lines.
The linebreak and indentation here \
can be escaped too!";
println!("{}", long_string);
}</code></pre></pre>
<ol start="10">
<li>🌟🌟🌟 Sometimes there are just too many characters that need to be escaped or it's just much more convenient to write a string out as-is. This is where raw string literals come into play.</li>
</ol>
<pre><pre class="playground"><code class="language-rust editable edition2021">
/* Fill in the blank and fix the errors */
fn main() {
let raw_str = r"Escapes don't work here: \x3F \u{211D}";
// Modify above line to make it work
assert_eq!(raw_str, "Escapes don't work here: ? ");
// If you need quotes in a raw string, add a pair of #s
let quotes = r#"And then I said: "There is no escape!""#;
println!("{}", quotes);
// If you need "# in your string, just use more #s in the delimiter.
// You can use up to 65535 #s.
let delimiter = r###"A string with "# in it. And even "##!"###;
println!("{}", delimiter);
// Fill the blank
let long_delimiter = __;
assert_eq!(long_delimiter, "Hello, \"##\"");
println!("Success!");
}</code></pre></pre>
<h3 id="byte-string"><a class="header" href="#byte-string">Byte string</a></h3>
<p>Want a string that's not UTF-8? (Remember, str and String must be valid UTF-8). Or maybe you want an array of bytes that's mostly text? Byte strings to the rescue!</p>
<p><strong>Example</strong>:</p>
<pre><pre class="playground"><code class="language-rust editable edition2021">use std::str;
fn main() {
// Note that this is not actually a `&amp;str`
let bytestring: &amp;[u8; 21] = b"this is a byte string";
// Byte arrays don't have the `Display` trait, so printing them is a bit limited
println!("A byte string: {:?}", bytestring);
// Byte strings can have byte escapes...
let escaped = b"\x52\x75\x73\x74 as bytes";
// ...But no unicode escapes
// let escaped = b"\u{211D} Is not allowed";
println!("Some escaped bytes: {:?}", escaped);
// Raw byte strings work just like raw strings
let raw_bytestring = br"\u{211D} is not escaped here";
println!("{:?}", raw_bytestring);
// Converting a byte array to `str` can fail
if let Ok(my_str) = str::from_utf8(raw_bytestring) {
println!("And the same as text: '{}'", my_str);
}
let _quotes = br#"You can also use "fancier" formatting, \
like with normal raw strings"#;
// Byte strings don't have to be UTF-8
let shift_jis = b"\x82\xe6\x82\xa8\x82\xb1\x82\xbb"; // "ようこそ" In SHIFT-JIS
// But then they can't always be converted to `str`
match str::from_utf8(shift_jis) {
Ok(my_str) =&gt; println!("Conversion successful: '{}'", my_str),
Err(e) =&gt; println!("Conversion failed: {:?}", e),
};
}</code></pre></pre>
<p>A more detailed listing of the ways to write string literals and escape characters is given in the <a href="https://doc.rust-lang.org/reference/tokens.html">'Tokens' chapter</a> of the Rust Reference.</p>
<h3 id="string-index"><a class="header" href="#string-index">String index</a></h3>
<ol start="11">
<li>🌟🌟🌟 You can't use index to access a char in a string, but you can use slice <code>&amp;s1[start..end]</code>.</li>
</ol>
<pre><pre class="playground"><code class="language-rust editable edition2021">
fn main() {
let s1 = String::from("hi,中国");
let h = s1[0]; // Modify this line to fix the error, tips: `h` only takes 1 byte in UTF8 format
assert_eq!(h, "h");
let h1 = &amp;s1[3..5]; // Modify this line to fix the error, tips: `中` takes 3 bytes in UTF8 format
assert_eq!(h1, "中");
println!("Success!");
}</code></pre></pre>
<h3 id="operate-on-utf8-string"><a class="header" href="#operate-on-utf8-string">Operate on UTF8 string</a></h3>
<ol start="12">
<li>🌟</li>
</ol>
<pre><pre class="playground"><code class="language-rust editable edition2021">
fn main() {
// Fill the blank to print each char in "你好,世界"
for c in "你好,世界".__ {
println!("{}", c)
}
}</code></pre></pre>
<h4 id="utf8_slice"><a class="header" href="#utf8_slice">utf8_slice</a></h4>
<p>You can use <a href="https://docs.rs/utf8_slice/1.0.0/utf8_slice/fn.slice.html">utf8_slice</a> to slice UTF8 string, it can index chars instead of bytes.</p>
<p><strong>Example</strong></p>
<pre><pre class="playground"><code class="language-rust edition2021">use utf8_slice;
fn main() {
let s = "The 🚀 goes to the 🌑!";
let rocket = utf8_slice::slice(s, 4, 5);
// Will equal "🚀"
}</code></pre></pre>
<blockquote>
<p>You can find the solutions <a href="https://github.com/sunface/rust-by-practice/blob/master/solutions/compound-types/string.md">here</a>(under the solutions path), but only use it when you need it</p>
</blockquote>
</main>
<nav class="nav-wrapper" aria-label="Page navigation">
<!-- Mobile navigation buttons -->
<a rel="prev" href="../compound-types/intro.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>
<a rel="next prefetch" href="../compound-types/array.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
<div style="clear: both"></div>
</nav>
</div>
</div>
<nav class="nav-wide-wrapper" aria-label="Page navigation">
<a rel="prev" href="../compound-types/intro.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>
<a rel="next prefetch" href="../compound-types/array.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
</nav>
</div>
<script>
window.playground_copyable = true;
</script>
<script src="../ace.js"></script>
<script src="../editor.js"></script>
<script src="../mode-rust.js"></script>
<script src="../theme-dawn.js"></script>
<script src="../theme-tomorrow_night.js"></script>
<script src="../elasticlunr.min.js"></script>
<script src="../mark.min.js"></script>
<script src="../searcher.js"></script>
<script src="../clipboard.min.js"></script>
<script src="../highlight.js"></script>
<script src="../book.js"></script>
<!-- Custom JS scripts -->
<script src="../assets/custom3.js"></script>
<script src="../assets/lang1.js"></script>
</div>
</body>
</html>