我們?nèi)绾巫x取用戶的鍵盤(控制臺)輸入呢?從鍵盤和標準輸入 os.Stdin
讀取輸入,最簡單的辦法是使用 fmt
包提供的 Scan 和 Sscan 開頭的函數(shù)。請看以下程序:
示例 12.1 readinput1.go:
// 從控制臺讀取輸入:
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)
// 輸出結果: From the string we read: 56.12 5212 Go
}
Scanln
掃描來自標準輸入的文本,將空格分隔的值依次存放到后續(xù)的參數(shù)內(nèi),直到碰到換行。Scanf
與其類似,除了 Scanf
的第一個參數(shù)用作格式字符串,用來決定如何讀取。Sscan
和以 Sscan
開頭的函數(shù)則是從字符串讀取,除此之外,與 Scanf
相同。如果這些函數(shù)讀取到的結果與您預想的不同,您可以檢查成功讀入數(shù)據(jù)的個數(shù)和返回的錯誤。
您也可以使用 bufio
包提供的緩沖讀取(buffered 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
是一個指向 bufio.Reader
的指針。inputReader := bufio.NewReader(os.Stdin)
這行代碼,將會創(chuàng)建一個讀取器,并將其與標準輸入綁定。
bufio.NewReader()
構造函數(shù)的簽名為:func NewReader(rd io.Reader) *Reader
該函數(shù)的實參可以是滿足 io.Reader
接口的任意對象(任意包含有適當?shù)?Read()
方法的對象,請參考章節(jié)11.8),函數(shù)返回一個新的帶緩沖的 io.Reader
對象,它將從指定讀取器(例如 os.Stdin
)讀取內(nèi)容。
返回的讀取器對象提供一個方法 ReadString(delim byte)
,該方法從輸入中讀取內(nèi)容,直到碰到 delim
指定的字符,然后將讀取到的內(nèi)容連同 delim
字符一起放到緩沖區(qū)。
ReadString
返回讀取到的字符串,如果碰到錯誤則返回 nil
。如果它一直讀到文件結束,則返回讀取到的字符串和 io.EOF
。如果讀取過程中沒有碰到 delim
字符,將返回錯誤 err != nil
。
在上面的例子中,我們會讀取鍵盤輸入,直到回車鍵(\n)被按下。
屏幕是標準輸出 os.Stdout
;os.Stderr
用于顯示錯誤信息,大多數(shù)情況下等同于 os.Stdout
。
一般情況下,我們會省略變量聲明,而使用 :=
,例如:
inputReader := bufio.NewReader(os.Stdin)
input, err := inputReader.ReadString('\n')
我們將從現(xiàn)在開始使用這種寫法。
第二個例子從鍵盤讀取輸入,使用了 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的行結束符是不同的!
練習
練習 12.1: word_letter_count.go
編寫一個程序,從鍵盤讀取輸入。當用戶輸入 'S' 的時候表示輸入結束,這時程序輸出 3 個數(shù)字:
i) 輸入的字符的個數(shù),包括空格,但不包括 '\r' 和 '\n'
ii) 輸入的單詞的個數(shù)
iii) 輸入的行數(shù)
練習 12.2: calculator.go
編寫一個簡單的逆波蘭式計算器,它接受用戶輸入的整型數(shù)(最大值 999999)和運算符 +、-、*、/。
輸入的格式為:number1 ENTER number2 ENTER operator ENTER --> 顯示結果
當用戶輸入字符 'q' 時,程序結束。請使用您在練習11.3中開發(fā)的 stack
包。