我們?nèi)绾巫x取用戶的鍵盤(控制臺(tái))輸入呢?從鍵盤和標(biāo)準(zhǔn)輸入 os.Stdin 讀取輸入,最簡單的辦法是使用 fmt 包提供的 Scan 和 Sscan 開頭的函數(shù)。請看以下程序:
示例 12.1 readinput1.go:
// 從控制臺(tái)讀取輸入:
package main
import "fmt"
var (
firstName, lastName, s string
i int
f float32
input = "56.12 / 5212 / Go"
format = "%f / %d / %s"
)
func main() {
fmt.Println("Please enter your full name: ")
fmt.Scanln(&firstName, &lastName)
// fmt.Scanf("%s %s", &firstName, &lastName)
fmt.Printf("Hi %s %s!\n", firstName, lastName) // Hi Chris Naegels
fmt.Sscanf(input, format, &f, &i, &s)
fmt.Println("From the string we read: ", f, i, s)
// 輸出結(jié)果: From the string we read: 56.12 5212 Go
}
Scanln 掃描來自標(biāo)準(zhǔn)輸入的文本,將空格分隔的值依次存放到后續(xù)的參數(shù)內(nèi),直到碰到換行。Scanf 與其類似,除了 Scanf 的第一個(gè)參數(shù)用作格式字符串,用來決定如何讀取。Sscan 和以 Sscan 開頭的函數(shù)則是從字符串讀取,除此之外,與 Scanf 相同。如果這些函數(shù)讀取到的結(jié)果與您預(yù)想的不同,您可以檢查成功讀入數(shù)據(jù)的個(gè)數(shù)和返回的錯(cuò)誤。
您也可以使用 bufio 包提供的緩沖讀?。╞uffered reader)來讀取數(shù)據(jù),正如以下例子所示:
示例 12.2 readinput2.go:
package main
import (
"fmt"
"bufio"
"os"
)
var inputReader *bufio.Reader
var input string
var err error
func main() {
inputReader = bufio.NewReader(os.Stdin)
fmt.Println("Please enter some input: ")
input, err = inputReader.ReadString('\n')
if err == nil {
fmt.Printf("The input was: %s\n", input)
}
}
inputReader 是一個(gè)指向 bufio.Reader 的指針。inputReader := bufio.NewReader(os.Stdin) 這行代碼,將會(huì)創(chuàng)建一個(gè)讀取器,并將其與標(biāo)準(zhǔn)輸入綁定。
bufio.NewReader() 構(gòu)造函數(shù)的簽名為:func NewReader(rd io.Reader) *Reader
該函數(shù)的實(shí)參可以是滿足 io.Reader 接口的任意對象(任意包含有適當(dāng)?shù)?Read() 方法的對象,請參考章節(jié)11.8),函數(shù)返回一個(gè)新的帶緩沖的 io.Reader 對象,它將從指定讀取器(例如 os.Stdin)讀取內(nèi)容。
返回的讀取器對象提供一個(gè)方法 ReadString(delim byte),該方法從輸入中讀取內(nèi)容,直到碰到 delim 指定的字符,然后將讀取到的內(nèi)容連同 delim 字符一起放到緩沖區(qū)。
ReadString 返回讀取到的字符串,如果碰到錯(cuò)誤則返回 nil。如果它一直讀到文件結(jié)束,則返回讀取到的字符串和 io.EOF。如果讀取過程中沒有碰到 delim 字符,將返回錯(cuò)誤 err != nil。
在上面的例子中,我們會(huì)讀取鍵盤輸入,直到回車鍵(\n)被按下。
屏幕是標(biāo)準(zhǔn)輸出 os.Stdout;os.Stderr 用于顯示錯(cuò)誤信息,大多數(shù)情況下等同于 os.Stdout。
一般情況下,我們會(huì)省略變量聲明,而使用 :=,例如:
inputReader := bufio.NewReader(os.Stdin)
input, err := inputReader.ReadString('\n')
我們將從現(xiàn)在開始使用這種寫法。
第二個(gè)例子從鍵盤讀取輸入,使用了 switch 語句:
示例 12.3 switch_input.go:
package main
import (
"fmt"
"os"
"bufio"
)
func main() {
inputReader := bufio.NewReader(os.Stdin)
fmt.Println("Please enter your name:")
input, err := inputReader.ReadString('\n')
if err != nil {
fmt.Println("There were errors reading, exiting program.")
return
}
fmt.Printf("Your name is %s", input)
// For Unix: test with delimiter "\n", for Windows: test with "\r\n"
switch input {
case "Philip\r\n": fmt.Println("Welcome Philip!")
case "Chris\r\n": fmt.Println("Welcome Chris!")
case "Ivo\r\n": fmt.Println("Welcome Ivo!")
default: fmt.Printf("You are not welcome here! Goodbye!")
}
// version 2:
switch input {
case "Philip\r\n": fallthrough
case "Ivo\r\n": fallthrough
case "Chris\r\n": fmt.Printf("Welcome %s\n", input)
default: fmt.Printf("You are not welcome here! Goodbye!\n")
}
// version 3:
switch input {
case "Philip\r\n", "Ivo\r\n": fmt.Printf("Welcome %s\n", input)
default: fmt.Printf("You are not welcome here! Goodbye!\n")
}
}
注意:Unix和Windows的行結(jié)束符是不同的!
練習(xí)
練習(xí) 12.1: word_letter_count.go
編寫一個(gè)程序,從鍵盤讀取輸入。當(dāng)用戶輸入 'S' 的時(shí)候表示輸入結(jié)束,這時(shí)程序輸出 3 個(gè)數(shù)字:
i) 輸入的字符的個(gè)數(shù),包括空格,但不包括 '\r' 和 '\n'
ii) 輸入的單詞的個(gè)數(shù)
iii) 輸入的行數(shù)
練習(xí) 12.2: calculator.go
編寫一個(gè)簡單的逆波蘭式計(jì)算器,它接受用戶輸入的整型數(shù)(最大值 999999)和運(yùn)算符 +、-、*、/。
輸入的格式為:number1 ENTER number2 ENTER operator ENTER --> 顯示結(jié)果
當(dāng)用戶輸入字符 'q' 時(shí),程序結(jié)束。請使用您在練習(xí)11.3中開發(fā)的 stack 包。