<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                作為我們的第一個項目,我們來實現一個經典新手編程問題:猜猜看游戲。它是這么工作的:我們的程序將會隨機生成一個1到100之間的隨機數。它接著會提示我們猜一個數。當我們猜了一個數之后,它會告訴我們是大了還是小了。當我們猜對了,它會祝賀我們。聽起來如何? ## 準備 我們準備一個新項目。進入到你的項目目錄。還記得我們曾經創建我們`hello_world`的項目目錄和`Cargo.toml`文件嗎?Cargo有一個命令來為我們做這些。讓我們試試: ~~~ $ cd ~/projects $ cargo new guessing_game --bin $ cd guessing_game ~~~ 我們將項目名字傳遞給`cargo new`,然后用了`--bin`標記,因為我們要創建一個二進制文件,而不是一個庫文件。 查看生成的`Cargo.toml`文件: ~~~ [package] name = "guessing_game" version = "0.0.1" authors = ["Your Name "] ~~~ Cargo從環境變量中獲取這些信息。如果這不對,趕緊修改它。 最后,Cargo為我們生成了應給“Hello, world!”。查看`src/main.rs`文件: ~~~ fn main() { println!("Hello, world!") } ~~~ 讓我們編譯Cargo為我們生成的項目: ~~~ $ cargo build Compiling guessing_game v0.0.1 (file:///home/you/projects/guessing_game) ~~~ 很好,再次打開你的`src/main.rs`文件。我們會將所有代碼寫在這個文件里。稍后我們會講到多文件項目。 在我們繼續之前,讓我們再告訴你一個新的Cargo命令:`run`。`cargo run`跟`cargo build`類似,并且還會運行我們剛生成的可執行文件。試試它: ~~~ $ cargo run Compiling guessing_game v0.0.1 (file:///home/you/projects/guessing_game) Running `target/guessing_game` Hello, world! ~~~ 很好!`run`命令在我們需要快速重復運行一個項目是非常方便。我們的游戲就是這么一個項目,在我們添加新內容之前我們需要經常快速測試項目。 ## 處理一次猜測 讓我們開始吧!我們需要做的第一件事是讓我們的玩家輸入一個猜測。把這些放入你的`src/main.rs`: ~~~ use std::io; fn main() { println!("Guess the number!"); println!("Please input your guess."); let mut guess = String::new(); io::stdin().read_line(&mut guess) .ok() .expect("Failed to read line"); println!("You guessed: {}", guess); } ~~~ 這有好多東西!讓我們一點一點的過一遍。 ~~~ use std::io; ~~~ 我們需要獲取用戶輸入,并接著打印結果作為輸出。為此,我們需要標準庫的`io`庫。Rust為所有程序只導入了很少一些東西,[‘prelude’](http://doc.rust-lang.org/nightly/std/prelude/)。如果它不在預先導入中,你將不得不直接`use`它。 ~~~ fn main() { ~~~ 就像你之前見過的,`main()`是你程序的入口點。`fn`語法聲明了一個新函數,`()`表明這里沒有參數,而`{`開始了函數體。因為我們不包含返回類型,它假設是`()`,一個空的[元組](http://doc.rust-lang.org/nightly/book/primitive-types.html#tuples)。 ~~~ println!("Guess the number!"); println!("Please input your guess."); ~~~ 我們之前學過`println!()`是一個在屏幕上打印[字符串](http://doc.rust-lang.org/nightly/book/strings.html)的[宏](http://doc.rust-lang.org/nightly/book/macros.html)。 ~~~ let mut guess = String::new(); ~~~ 現在我們遇到有意思的東西了!這一小行有很多內容。第一個我們需要注意到的是[let語句](http://doc.rust-lang.org/nightly/book/variable-bindings.html),它用來創建“變量綁定”。它使用這個形式: ~~~ let foo = bar; ~~~ 這回創建一個叫做`foo`的新綁定,并綁定它到`bar`這個值上。在很多語言中,這叫做一個“變量",不過Rust的變量綁定暗藏玄機。 例如,它們默認是[不可變的](http://doc.rust-lang.org/nightly/book/mutability.html)。這時為什么我們的例子使用了`mut`:它讓一個綁定可變,而不是不可變。`let`并不從左手邊獲取一個名字,事實上他接受一個[模式(pattern)](http://doc.rust-lang.org/nightly/book/patterns.html)。我們會在后面更多的使用模式。現在它使用起來非常簡單: ~~~ let foo = 5; // immutable. let mut bar = 5; // mutable ~~~ 噢,同時`//`會開始一個注釋,直到這行的末尾。Rust忽略[注釋](http://doc.rust-lang.org/nightly/book/comments.html)中的任何內容。 那么現在我們知道了`let mut guess`會引入一個叫做`guess`的可變綁定,不過我們不得不看看`=`的右側,它綁定的內容:`String::new()`。 `String`是一個字符串類型,由標準庫提供。[String](http://doc.rust-lang.org/nightly/std/string/struct.String.html)是一個可增長的,UTF-8編碼的文本。 `::new()`語法用了`::`因為它是一個特定類型的”關聯函數“。這就是說,它與`String`自身關聯,而不是與一個特定的`String`實例關聯。一些語言管這叫一個”靜態方法“。 這個函數叫做`new()`,因為它創建了一個新的,空的`String`。你會在很多類型上找到`new()`函數,因為它是創建一些類型新值的通常名稱。 讓我們繼續: ~~~ io::stdin().read_line(&mut guess) .ok() .expect("Failed to read line"); ~~~ 這稍微有點多!讓我們一點一點來。第一行有兩部分。這是第一部分: ~~~ io::stdin() ~~~ 還記得我們如何在程序的第一行`use``std::io`的嗎?現在我們調用了一個與之相關的函數。如果我們不`use std::io`,那么我們就得寫成`std::io::stdin()`。 這個特殊的函數返回一個句柄到你終端的標準輸入。更具體的,一個[std::io::Stdin](http://doc.rust-lang.org/nightly/std/io/struct.Stdin.html)。 下一部分將用這個句柄去獲取用戶輸入: ~~~ .read_line(&mut guess) ~~~ 這里,我們對我們的句柄調用了[read_line()](http://doc.rust-lang.org/nightly/std/io/struct.Stdin.html#method.read_line)方法。[方法](http://doc.rust-lang.org/nightly/book/methods.html)(404)就像關聯函數,不過只在一個類型的特定實例上可用,而不是這個類型本身。我們也向`read_line()`傳遞了一個參數:`&mut guess`。 還記得我們上面怎么綁定`guess`的嗎?我們說它是可變的。然而,`read_line`并不獲取`String`作為一個參數:它獲取一個`&mut String`。Rust有一個叫做[“引用”](http://doc.rust-lang.org/nightly/book/references-and-borrowing.html)的功能,它允許你對一片數據有多個引用,用它可以減少拷貝。引用是一個復雜的功能,因為Rust的一個主要賣點就是它如何安全和便捷的使用引用。然而,目前我們還不需要知道很多細節來完成我們的程序。現在,所有我們需要了解的是像`let`綁定,引用默認是不可變的。因此,我們需要寫成`&mut guess`,而不是`&guess`。 為什么`read_line()`會需要一個字符串的可變引用呢?它的工作是從標準輸入獲取用戶輸入,并把它放入一個字符串。所以它用字符串作為參數,為了可以增加輸入,它必須是可變的。 不過我們還未完全看完這行代碼。雖然它是單獨的一行代碼,它是只是這個單獨邏輯代碼行的開頭部分: ~~~ .ok() .expect("Failed to read line"); ~~~ 當你用`.foo()`語法調用一個函數的時候,你可能會引入一個新行符或其它空白。這幫助我們拆分長的行。我們_可以_這么干: ~~~ io::stdin().read_line(&mut guess).ok().expect("failed to read line"); ~~~ 不過這樣會難以閱讀。所以我們把它分開,3行對應3個方法調用。我們已經談論過了`read_line()`,不過`ok()`和`expect()`呢?好吧,我們已經提到過`read_line()`將用戶輸入放入我們傳遞給它的`&mut String`中。不過他也返回一個值:在這個例子中,一個[io::Result](http://doc.rust-lang.org/nightly/std/io/type.Result.html)。Rust的標準庫中有很多叫做`Result`的類型:一個泛型[Result](http://doc.rust-lang.org/nightly/std/result/enum.Result.html),然后是子庫的特殊版本,例如`io::Result`。 這個`Result`類型的作用是編碼錯誤處理信息。`Result`類型的值,像任何(其它)類型,有定義在其上的方法。在這個例子中,`io::Result`有一個`ok()`方法,它說“我們想假設這個值是一個成功的值。如果不是,就拋出錯誤信息”。為什么要拋出錯誤呢?好吧,對于一個基礎的程序,我們只想打印出一個通用錯誤,因為基本上任何問題意味著我們不能繼續。[ok()方法](http://doc.rust-lang.org/nightly/std/result/enum.Result.html#method.ok)返回一個值,有另一個方法定義在其上:`expect()`。[expect()方法](http://doc.rust-lang.org/nightly/std/option/enum.Option.html#method.expect)獲取調用它的值,而且如果它不是一個成功的值,[panic!](http://doc.rust-lang.org/nightly/book/error-handling.html)并帶有你傳遞給它的信息。這樣的`panic!`會使我們的程序崩潰,顯示(我們傳遞的)信息。 如果我們去掉這兩個函數調用,我們的程序會編譯通過,不過我們會得到一個警告: ~~~ $ cargo build Compiling guessing_game v0.1.0 (file:///home/you/projects/guessing_game) src/main.rs:10:5: 10:39 warning: unused result which must be used, #[warn(unused_must_use)] on by default src/main.rs:10 io::stdin().read_line(&mut guess); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~ Rust警告我們我們并未使用`Result`的值。這個警告來自`io::Result`的一個特殊注解。Rust嘗試告訴你你并未處理一個可能的錯誤。阻止錯誤的正確方法是老實編寫錯誤處理。幸運的是,如果我們只是想如果這有一個問題就崩潰的話,我們可以用這兩個小方法。如果我們想從錯誤中恢復什么的,我們得做點別的,不過我們會把它留給接下來的項目。 這是我們第一個例子僅剩的一行: ~~~ println!("You guessed: {}", guess); } ~~~ 這打印出我們保存輸入的字符串。`{}`是一個占位符,所以我們傳遞`guess`作為一個參數。如果我們有多個`{}`,我們應該傳遞多個參數: ~~~ let x = 5; let y = 10; println!("x and y: {} and {}", x, y); ~~~ 簡單加愉快。 不過怎么說,這只是一個觀光。我們可以用`cargo run`運行我們寫的: ~~~ $ cargo run Compiling guessing_game v0.1.0 (file:///home/you/projects/guessing_game) Running `target/debug/guessing_game` Guess the number! Please input your guess. 6 You guessed: 6 ~~~ 好的!我們的第一部分完成了:我們可以從鍵盤獲取輸入,并把它打印回去。 ## 生成一個秘密數字 接下來,我們要生成一個秘密數字。Rust標準庫中還未包含一個隨機數功能。Rust團隊確實,然而,提供了一個[`rand`?crate](https://crates.io/crates/rand)。一個“包裝箱”(crate)是一個Rust代碼的包。我們已經構建了一個”二進制包裝箱“,它是一個可執行文件。`rand`是一個”庫包裝箱“,它包含被認為應該被其它程序使用的代碼。 使用外部包裝箱是Cargo的亮點。在我們使用`rand`編寫代碼之前,我們需要修改我們的`Cargo.toml`。打開它,并在末尾增加這幾行: ~~~ [dependencies] rand="0.3.0" ~~~ `Cargo.toml`的`[dependencies]`部分就像`[package]`部分:所有之后的東西都是它的一部分,直到下一個部分開始。Cargo使用依賴部分來知曉你用的外部包裝箱的依賴,和你要求的版本。在這個例子中,我們用了`0.3.0`版本。Cargo理解[語義化版本](http://semver.org/lang/zh-CN/),它是一個編寫版本號的標準。如果我們想要使用最新版本我們可以使用`*`或者我們可以使用一個范圍的版本。[Cargo文檔](http://doc.crates.io/crates-io.html)包含更多細節。 現在,在不修改任何我們代碼的情況下,讓我們構建我們的項目: ~~~ $ cargo build Updating registry `https://github.com/rust-lang/crates.io-index` Downloading rand v0.3.8 Downloading libc v0.1.6 Compiling libc v0.1.6 Compiling rand v0.3.8 Compiling guessing_game v0.1.0 (file:///home/you/projects/guessing_game) ~~~ (當然,你可能會看到不同的版本) 很多新的輸出!現在我們有了一個外部依賴,Cargo從記錄中獲取了所有東西的最新版本,它們是來自[Crates.io](https://crates.io/)的一份拷貝。Crates.io是Rust生態系統中人們發表開源Rust項目供它人使用的地方。 在更新了記錄后,Cargo檢查我們的`[dependencies]`并下載任何我們還沒有的東西。在這個例子中,雖然我們只說了我們要依賴`rand`,我們也獲取了一份`libc`的拷貝。這是因為`rand`依賴`libc`工作。在下載了它們之后,它編譯它們,然后接著編譯我們的項目。 如果我們再次運行`cargo build`,我們會得到不同的輸出: ~~~ $ cargo build ~~~ 沒錯,木有輸出!Cargo知道我們的項目被構建了,并且所有它的依賴也被構建了,所以沒有理由再做一遍所有這一些。沒有事情做,它簡單的退出了。如果我們再打開`src/main.rs`,做一個無所謂的修改,然后接著再保存,我們就會看到一行: ~~~ $ cargo build Compiling guessing_game v0.1.0 (file:///home/you/projects/guessing_game) ~~~ 所以,我們告訴Cargo我們需要任何`0.3.x`版本的`rand`,并且因此它獲取在本文被編寫時的最新版,`v0.3.8`。不過你瞧瞧當下一周,`v0.3.9`出來了,帶有一個重要的bug修改嗎?雖然bug修改很重要,不過如果`0.3.9`版本包含破壞我們代碼的回歸呢? 這個問題的回答是現在你會在你項目目錄中找到的`Cargo.lock`。當你第一次構建你的項目的時候,Cargo查明所有符合你的要求的版本,并接著把它們寫到了`Cargo.lock`文件里。當你在未來構建你的項目的時候,Cargo會注意到`Cargo.lock`的存在,并接著使用指定的版本而不是再次去做查明版本的所有工作。這讓你有了一個可重復的自動構建。換句話說,我們會保持在`0.3.8`直到我們顯式的升級,這對任何使用我們共享的代碼的人同樣有效,感謝鎖文件。 當我們_確實_想要使用`v0.3.9`怎么辦?Cargo有另一個命令,`update`,它代表“忽略鎖,搞清楚所有我們指定的最新版本。如果這能工作,將這些版本寫入鎖文件”。不過,默認,Cargo只會尋找大于`0.3.0`小于`0.4.0`的版本。如果你想要移動到`0.4.x`,我們不得不直接更新`Cargo.toml`文件。當我們這么做,下一次我們`cargo build`,Cargo會更新索引并重新計算我們的`rand`要求。 關于[?Cargo](http://doc.crates.io/)和[它的生態系統](http://doc.crates.io/crates-io.html)有很多東西要說,不過眼下,這是我們需要知道的一切。Cargo讓重用庫變得真正的簡單,并且Rustacean們可以編寫更小的由很多子包組裝成的項目。 讓我們確實的_使用_`rand`。這是我們的下一步: ~~~ extern crate rand; use std::io; use rand::Rng; fn main() { println!("Guess the number!"); let secret_number = rand::thread_rng().gen_range(1, 101); println!("The secret number is: {}", secret_number); println!("Please input your guess."); let mut guess = String::new(); io::stdin().read_line(&mut guess) .ok() .expect("failed to read line"); println!("You guessed: {}", guess); } ~~~ 我們做的第一件事是修改第一行。現在它是`extern crate rand`。因為我們在我們的`[dependencies]`聲明了`rand`,我們可以用`extern crate`來讓Rust知道我們正在使用它。這也等同于一個`use rand;`,所以我們可以通過`rand::`前綴使用`rand`包裝箱中的一切。 下一步,我們增加了另一行`use`:`use rand::Rng`。我們一會將要使用一個方法,并且它要求`Rng`在作用域中才能工作。這個基本觀點是:方法定義在一些叫做“特性”的東西上面,而為了讓方法能夠工作,需要這個特性位于作用域中。關于更多細節,閱讀[特性](http://doc.rust-lang.org/nightly/book/traits.html)部分。 這里還有兩行我們增加的,在中間: ~~~ let secret_number = rand::thread_rng().gen_range(1, 101); println!("The secret number is: {}", secret_number); ~~~ 我們用`rand::thread_rng()`函數來獲取一個隨機數生成器的拷貝,它位于我們特定的執行[線程](http://doc.rust-lang.org/nightly/book/concurrency.html)的本地。因為我們`use rand::Rng`了,我們有一個`gen_range()`方法可用。這個函數獲取兩個參數,并產生一個位于其間的數字。它包含下限,不過不包含上限,所以我們需要`1`和`101`來生成一個`1`和`100`之間的數。 第二行僅僅打印出了秘密數字。這在我們開發我們的程序時很有用,所以我們可以簡單的測試出來。不過在最終版本中我們會刪除它。在開始就打印出結果就沒什么可玩的了! 嘗試運行我們的新程序幾次: ~~~ $ cargo run Compiling guessing_game v0.1.0 (file:///home/you/projects/guessing_game) Running `target/debug/guessing_game` Guess the number! The secret number is: 7 Please input your guess. 4 You guessed: 4 $ cargo run Running `target/debug/guessing_game` Guess the number! The secret number is: 83 Please input your guess. 5 You guessed: 5 ~~~ 好的!接下來:讓我們比較我們的猜測和秘密數字。 ## 比較猜測 現在我們得到了用戶輸入,讓我們比較我們的猜測和隨機值。這是我們的下一步,雖然它還不能正常工作: ~~~ extern crate rand; use std::io; use std::cmp::Ordering; use rand::Rng; fn main() { println!("Guess the number!"); let secret_number = rand::thread_rng().gen_range(1, 101); println!("The secret number is: {}", secret_number); println!("Please input your guess."); let mut guess = String::new(); io::stdin().read_line(&mut guess) .ok() .expect("failed to read line"); println!("You guessed: {}", guess); match guess.cmp(&secret_number) { Ordering::Less => println!("Too small!"), Ordering::Greater => println!("Too big!"), Ordering::Equal => println!("You win!"), } } ~~~ 這有一些新東西。第一個是另一個`use`。我們帶來了一個叫做`std::cmp::Ordering`類型到作用域中。接著,底部5行代碼使用了它: ~~~ match guess.cmp(&secret_number) { Ordering::Less => println!("Too small!"), Ordering::Greater => println!("Too big!"), Ordering::Equal => println!("You win!"), } ~~~ `cmp()`可以在任何能被比較的值上調用,并且它獲取你想要比較的值的引用。它返回我們之前`use`的`Ordering`類型。我們使用一個[match](http://doc.rust-lang.org/nightly/book/match.html)語句來決定具體是哪種`Ordering`。`Ordering`是一個[枚舉](http://doc.rust-lang.org/nightly/book/enums.html),“enumeration”的簡寫,它看起來像這樣: ~~~ enum Foo { Bar, Baz, } ~~~ 通過這個定義,任何`Foo`可以是`Foo::Bar`或者`Foo::Baz`。我們用`::`來表明一個特定`enum`變量的命名空間。 [Ordering](http://doc.rust-lang.org/nightly/std/cmp/enum.Ordering.html)枚舉有3個可能的變量:`Less`,`Equal`和`Greater`。`match`語句獲取類型的值,并讓你為每個可能的值創建一個“分支”。因為我們有3種類型的`Ordering`,我們有3個分支: ~~~ match guess.cmp(&secret_number) { Ordering::Less => println!("Too small!"), Ordering::Greater => println!("Too big!"), Ordering::Equal => println!("You win!"), } ~~~ 如果它是`Less`,我們打印`Too small!`,如果它是`Greater`,`Too big!`,而如果`Equal`,`You win!`。`match`真的灰常有用,并且在Rust中經常使用。 我確實提到過我們還不能正常運行,雖然。讓我們試試: ~~~ $ cargo build Compiling guessing_game v0.1.0 (file:///home/you/projects/guessing_game) src/main.rs:28:21: 28:35 error: mismatched types: expected `&collections::string::String`, found `&_` (expected struct `collections::string::String`, found integral variable) [E0308] src/main.rs:28 match guess.cmp(&secret_number) { ^~~~~~~~~~~~~~ error: aborting due to previous error Could not compile `guessing_game`. ~~~ 噢!這是一個大錯誤。它的核心是我們有“不匹配的類型”。Rust有一個強大的靜態類型系統。然而,它也有類型推斷。當我們寫`let guess = String::new()`,Rust能夠推斷出`guess`應該是一個`String`,并因此不需要我們寫出類型。而我們的`secret_number`,這有很多類型可以有從`1`到`100`的值:`i32`,一個32位數,或者`u32`,一個無符號的32位值,或者`i64`,一個64位值。或者其它什么的。目前為止,這并不重要,所以Rust默認為`i32`。然而,這里,Rust并不知道如何比較`guess`和`secret_number`。它們必須是相同的類型。最終,我們想要我們作為輸入讀到的`String`轉換為一個真正的數字類型,來進行比較。我們可以用額外3行來搞定它。這是我們的新程序: ~~~ extern crate rand; use std::io; use std::cmp::Ordering; use rand::Rng; fn main() { println!("Guess the number!"); let secret_number = rand::thread_rng().gen_range(1, 101); println!("The secret number is: {}", secret_number); println!("Please input your guess."); let mut guess = String::new(); io::stdin().read_line(&mut guess) .ok() .expect("failed to read line"); let guess: u32 = guess.trim().parse() .ok() .expect("Please type a number!"); println!("You guessed: {}", guess); match guess.cmp(&secret_number) { Ordering::Less => println!("Too small!"), Ordering::Greater => println!("Too big!"), Ordering::Equal => println!("You win!"), } } ~~~ 新的3行是: ~~~ let guess: u32 = guess.trim().parse() .ok() .expect("Please type a number!"); ~~~ 稍等,我認為我們已經用過了一個`guess`?確實,不過Rust允許我們用新值“遮蓋(shadow)”之前的`guess`。這在這種具體的情況中經常被用到,`guess`開始是一個`String`,不過我們想要把它轉換為一個`u32`。遮蓋(Shadowing)讓我們重用`guess`名字,而不是強迫我們想出兩個獨特的像`guess_str`和`guess`,或者別的什么的。 我們綁定`guess`到一個看起來像我們之前寫的表達式: ~~~ guess.trim().parse() ~~~ 后跟一個`ok().expect()`調用。這里,`guess`引用舊的`guess`,那個我們輸入用到的`String`。`String`的`trim()`方法會去掉我們字符串開頭和結尾的任何空格。這很重要,因為我們不得不按“回車”鍵來滿足`read_line()`。這意味著如果我們輸入`5`并按回車,`guess`看起來像這樣:`5\n`。`\n`代表“新行”,回車鍵。`trim()`去掉這些,保留`5`給我們的字符串。[字符串的`parse()`方法](http://doc.rust-lang.org/nightly/std/primitive.str.html#method.parse)將字符串解析為一些類型的數字。因為它可以解析多種數字,我們需要給Rust一些提醒作為我們具體想要的數字的類型。因此,`let guess: u32`。`guess`后面的分號(`:`)告訴Rust我們要標注它的類型。`u32`是一個無符號的,32位整型。Rust有[一系列內建類型](http://doc.rust-lang.org/nightly/book/primitive-types.html#numeric-types),不過我們選擇了`u32`。它是一個小的正數的好的默認選擇。 就像`read_line()`,我們調用`parse()`可能產生一個錯誤。如果我們的字符串包含`A
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看