mirror of
https://github.com/sunface/rust-by-practice.git
synced 2025-08-13 06:54:44 +00:00
460 lines
20 KiB
HTML
460 lines
20 KiB
HTML
<!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>&str</code>, e.g <code>let s: &str = "hello, world"</code>.</p>
|
||
<h3 id="str-and-str"><a class="header" href="#str-and-str">Str and &str</a></h3>
|
||
<ol>
|
||
<li>🌟 We can't use <code>str</code> type in normal ways, but we can use <code>&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>&</code> can be used to convert <code>Box<str></code> to <code>&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<str> = "hello, world".into();
|
||
greetings(s)
|
||
}
|
||
|
||
fn greetings(s: &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>&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">&str and String</a></h3>
|
||
<p>Opposite to the seldom using of <code>str</code>, <code>&str</code> and <code>String</code> are used everywhere!</p>
|
||
<ol start="7">
|
||
<li>🌟🌟 <code>&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>&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: &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 `&str`
|
||
let bytestring: &[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) => println!("Conversion successful: '{}'", my_str),
|
||
Err(e) => 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>&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 = &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>
|