2013-07-01 21 views
5

Tôi đang làm việc thông qua Go cuốn sách Caleb Doxsey và tôi có hai câu hỏi về fmt.Scanfhttp://www.golang-book.com/4Tại sao fmt.Scanf ở chế độ chờ đợi cho đầu vào của người dùng?

Tôi tự hỏi tại sao chương trình không chỉ dừng lại sau khi scanf thứ hai và chờ đợi cho người dùng nhập vào? Và làm thế nào để kiểm tra nếu người dùng đã nhập một số nguyên và/hoặc không để trống?

package main 

import (
"fmt" 
//"math" 
) 


// compute square roots by using Newton's method 

func main() { 

var x float64   //number to take square root 
var y float64   //this is the guess 
var q float64   //this is the quotient 
var a float64   //this is the average 


// how do check if the user entered a number 
fmt.Print("Enter a number to take its square root: ") 
var inputSquare float64 
fmt.Scanf("%f", &inputSquare) 

// why doesn't program stop after 
// the Print statement and wait 
// for user input? 
fmt.Print("Enter first guess ") 
var inputGuess float64 
fmt.Scanf("%f", &inputGuess) 

//x = 2 
x = inputSquare 
y = inputGuess 

for i := 0; i < 10; i++ { //set up the for loop for iterations 
    q = x/y     //compute the quotient; x and y are given 
    a = (q + y)/x   //compute the average  
    y = a     //set the guess to the average    
}       //for the next loop 


fmt.Println("y --> ", y) 
//fmt.Println("Sqrt(2)", math.Sqrt(2)) 
} 
+1

Nó hoạt động đúng cho tôi. Tôi sẽ đoán rằng đó là một dòng kết thúc vấn đề. Nếu bạn đang chạy trên Windows, dòng kết thúc được ký hiệu thông thường bởi '\ r \ n', trong khi trên Mac OS X và Linux (nơi tôi đã thử nghiệm này), nó chỉ là '\ n'. Tôi đoán là có thể Go đang đọc '\ r', coi nó là một dòng kết thúc, và để '\ n' trên luồng. Vì vậy, khi bạn gọi fmt.Scanf một lần nữa, đã có một cái gì đó trong bộ đệm và không cần phải chặn. Đây chỉ là một đoán hoang dã mặc dù. – deong

+0

ok. Bất kỳ đề xuất làm thế nào để sửa chữa nó? Đây là những gì tôi chạy trong dòng lệnh của Windows: c: \ Go \ src \ play \ exercise> chạy vòng lặp_exercise.go Nhập số cần căn bậc hai: 2 Nhập lần đầu tiên đoán y -> + Inf – Zeynel

+1

Cái gì gì xảy ra nếu bạn đọc một ký tự dòng mới bằng lệnh Scanf một cách rõ ràng? Giống như "' fmt.Scanf ("% f \ n", & inputGuess) '"? Cách khác, bạn có thể xả stdin sau mỗi lần đọc. Tôi không biết cũng đủ để biết nơi để nói với bạn để tìm một chức năng Flush. – deong

Trả lời

9

Đó là Issue 5391: fmt: Scanf từ chối \r\n ở cuối dòng trên Windows.

Là một workaround và để kiểm tra đầu vào hợp lệ, viết,

var inputSquare float64 
n, err := fmt.Scanf("%f\n", &inputSquare) 
if err != nil || n != 1 { 
    // handle invalid input 
    fmt.Println(n, err) 
} 

var inputGuess float64 
n, err = fmt.Scanf("%f\n", &inputGuess) 
if err != nil || n != 1 { 
    // handle invalid input 
    fmt.Println(n, err) 
} 

Cách giải quyết là newline trong "%f\n" định dạng chuỗi.

Gói fmt

func Scanf

func Scanf(format string, a ...interface{}) (n int, err error) 

Scanf quét văn bản đọc từ đầu vào tiêu chuẩn, lưu trữ liên tiếp giá trị không gian tách thành luận cứ liên tiếp được xác định bởi các định dạng . Nó trả về số lượng các mục được quét thành công.

Dưới đây là một chương trình làm việc hoàn chỉnh:

package main 

import (
    "fmt" 
) 

// compute square roots by using Newton's method 
func main() { 
    var x float64 //number to take square root 
    var y float64 //this is the guess 
    var q float64 //this is the quotient 
    var a float64 //this is the average 

    fmt.Print("Enter a number to take its square root: ") 
    var inputSquare float64 
    n, err := fmt.Scanf("%f\n", &inputSquare) 
    if err != nil || n != 1 { 
     // handle invalid input 
     fmt.Println(n, err) 
     return 
    } 

    fmt.Print("Enter first guess ") 
    var inputGuess float64 
    n, err = fmt.Scanf("%f\n", &inputGuess) 
    if err != nil || n != 1 { 
     // handle invalid input 
     fmt.Println(n, err) 
     return 
    } 

    x = inputSquare 
    y = inputGuess 
    for i := 0; i < 10; i++ { 
     q = x/y  // compute the quotient; x and y are given 
     a = (q + y)/x // compute the average 
     y = a   // set the guess to the average 
    } 
    fmt.Printf("sqrt(%g) = %g\n", x, y) 
} 

Output:

Enter a number to take its square root: 2.0 
Enter first guess 1.0 
sqrt(2) = 1.414213562373095 

tôi sử dụng Go 1.1.1 trên Windows 7:

C:\>go version 
go version go1.1.1 windows/amd64 
+0

Cảm ơn. 'Fmt.Scanf()' có trả về lỗi không? Tôi giả sử, 'n' là đầu vào và' err' là thông báo lỗi có thể có trong 'n, err: = fmt.Scanf ("% f \ n ", & inputSquare)' Có đúng không? – Zeynel

+1

Xem câu trả lời đã sửa đổi của tôi. 'n' là số mục được quét thành công và' err' báo cáo bất kỳ lỗi nào gặp phải trong quá trình quét. Vì vậy, nếu có một lỗi hoặc số lượng các mục được quét không phải là những gì bạn mong đợi ('err! = Nil || n! = 1'), hãy làm điều gì đó để xử lý lỗi.Tuy nhiên, nếu mọi thứ suôn sẻ ('err == nil && n == 1'), đầu vào hợp lệ, như một số dấu phẩy động (' float64'), có thể được đọc từ '* inputSquare'. Trong mã của bạn, bạn đã loại bỏ 'n' và' err', đó là lý do tại sao bạn không nhận thấy lỗi. – peterSO

+0

Tôi phải làm điều gì sai. Nếu tôi chạy chương trình với phần xử lý lỗi 'n, err: = fmt.Scanf (" f \ n ", & inputSquare) \t \t \t \t // nhận lỗi \t nếu err! = Nil || n! = 1 { \t \t fmt.Println (n, err) 'Tôi nhận được" 0 đầu vào không phù hợp với định dạng "(tôi nhập, ví dụ, 2.0 cho inputSquare) Nếu tôi nhận xét lỗi xử lý tất cả hoạt động tốt! Tôi đang làm gì sai? – Zeynel

Các vấn đề liên quan