Files
rust-by-practice/compound-types/string.html
sunface 987c59ed75 deploy
2025-04-25 12:48:03 +08:00

460 lines
20 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!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>