From fe0dc05b328eadf5c8832c8ea427f351ba69dcf4 Mon Sep 17 00:00:00 2001 From: Rob Pike Date: Fri, 28 May 2010 11:29:27 -0700 Subject: fmt.Scan: add Fscan and Fscanln and make Scan and Scanln read from standard input. Add description of scanning to the package comment. R=rsc CC=golang-dev http://codereview.appspot.com/1390041 --- src/pkg/fmt/print.go | 18 +++++++++++++++++- src/pkg/fmt/scan.go | 28 ++++++++++++++++++++++++---- src/pkg/fmt/scan_test.go | 14 +++++++------- 3 files changed, 48 insertions(+), 12 deletions(-) (limited to 'src/pkg/fmt') diff --git a/src/pkg/fmt/print.go b/src/pkg/fmt/print.go index 9c1940599..77af45a94 100644 --- a/src/pkg/fmt/print.go +++ b/src/pkg/fmt/print.go @@ -4,9 +4,11 @@ /* Package fmt implements formatted I/O with functions analogous - to C's printf. The format 'verbs' are derived from C's but + to C's printf and scanf. The format 'verbs' are derived from C's but are simpler. + Printing: + The verbs: General: @@ -74,9 +76,23 @@ If an operand implements method String() string that method will be used for %v, %s, or Print etc. + + Scanning: + + An analogous set of functions scans formatted text to yield + values. Scan and Scanln read from os.Stdin; Fscan and Fscanln + read from a specified os.Reader. By default, tokens are + separated by spaces. Fscanln and Scanln stop scanning at a + newline and require that the items be followed by one; the + other routines treat newlines as spaces. + + If an operand implements method Scan() (that is, it implements + the Scanner interface) that method will be used to scan the + text for that operand. */ package fmt +// BUG(r): There is no format-driven scanning yet. import ( "bytes" diff --git a/src/pkg/fmt/scan.go b/src/pkg/fmt/scan.go index 0c9ed4d76..fee9fd843 100644 --- a/src/pkg/fmt/scan.go +++ b/src/pkg/fmt/scan.go @@ -181,12 +181,32 @@ func (s *ss) token() string { return s.buf.String() } -// Scan parses text read from r, storing successive space-separated values +// Scan parses text read from standard input, storing successive +// space-separated values into successive arguments. Newlines count as +// space. Each argument must be a pointer to a basic type or an +// implementation of the Scanner interface. It returns the number of items +// successfully parsed. If that is less than the number of arguments, err +// will report why. +func Scan(a ...interface{}) (n int, err os.Error) { + return Fscan(os.Stdin, a) +} + +// Fscanln parses text read from standard input, storing successive +// space-separated values into successive arguments. Scanning stops at a +// newline and after the final item there must be a newline or EOF. Each +// argument must be a pointer to a basic type or an implementation of the +// Scanner interface. It returns the number of items successfully parsed. +// If that is less than the number of arguments, err will report why. +func Scanln(a ...interface{}) (n int, err os.Error) { + return Fscanln(os.Stdin, a) +} + +// Fscan parses text read from r, storing successive space-separated values // into successive arguments. Newlines count as space. Each argument must // be a pointer to a basic type or an implementation of the Scanner // interface. It returns the number of items successfully parsed. If that // is less than the number of arguments, err will report why. -func Scan(r io.Reader, a ...interface{}) (n int, err os.Error) { +func Fscan(r io.Reader, a ...interface{}) (n int, err os.Error) { s := newScanState(r, true) n = s.doScan(a) err = s.err @@ -194,13 +214,13 @@ func Scan(r io.Reader, a ...interface{}) (n int, err os.Error) { return } -// Scanln parses text read from r, storing successive space-separated values +// Fscanln parses text read from r, storing successive space-separated values // into successive arguments. Scanning stops at a newline and after the // final item there must be a newline or EOF. Each argument must be a // pointer to a basic type or an implementation of the Scanner interface. It // returns the number of items successfully parsed. If that is less than the // number of arguments, err will report why. -func Scanln(r io.Reader, a ...interface{}) (n int, err os.Error) { +func Fscanln(r io.Reader, a ...interface{}) (n int, err os.Error) { s := newScanState(r, false) n = s.doScan(a) err = s.err diff --git a/src/pkg/fmt/scan_test.go b/src/pkg/fmt/scan_test.go index 95aaffef8..19bb6d2a5 100644 --- a/src/pkg/fmt/scan_test.go +++ b/src/pkg/fmt/scan_test.go @@ -135,11 +135,11 @@ func testScan(t *testing.T, scan func(r io.Reader, a ...interface{}) (int, os.Er } func TestScan(t *testing.T) { - testScan(t, Scan) + testScan(t, Fscan) } func TestScanln(t *testing.T) { - testScan(t, Scanln) + testScan(t, Fscanln) } func TestScanOverflow(t *testing.T) { @@ -147,7 +147,7 @@ func TestScanOverflow(t *testing.T) { re := testing.MustCompile("overflow|too large|out of range|not representable") for _, test := range overflowTests { r := strings.NewReader(test.text) - _, err := Scan(r, test.in) + _, err := Fscan(r, test.in) if err == nil { t.Errorf("expected overflow scanning %q", test.text) continue @@ -162,7 +162,7 @@ func TestScanMultiple(t *testing.T) { text := "1 2 3 x" r := strings.NewReader(text) var a, b, c, d int - n, err := Scan(r, &a, &b, &c, &d) + n, err := Fscan(r, &a, &b, &c, &d) if n != 3 { t.Errorf("count error: expected 3: got %d", n) } @@ -174,7 +174,7 @@ func TestScanMultiple(t *testing.T) { func TestScanNotPointer(t *testing.T) { r := strings.NewReader("1") var a int - _, err := Scan(r, a) + _, err := Fscan(r, a) if err == nil { t.Error("expected error scanning non-pointer") } else if strings.Index(err.String(), "pointer") < 0 { @@ -185,7 +185,7 @@ func TestScanNotPointer(t *testing.T) { func TestScanlnNoNewline(t *testing.T) { r := strings.NewReader("1 x\n") var a int - _, err := Scanln(r, &a) + _, err := Fscanln(r, &a) if err == nil { t.Error("expected error scanning string missing newline") } else if strings.Index(err.String(), "newline") < 0 { @@ -196,7 +196,7 @@ func TestScanlnNoNewline(t *testing.T) { func TestScanlnWithMiddleNewline(t *testing.T) { r := strings.NewReader("123\n456\n") var a, b int - _, err := Scanln(r, &a, &b) + _, err := Fscanln(r, &a, &b) if err == nil { t.Error("expected error scanning string with extra newline") } else if strings.Index(err.String(), "newline") < 0 { -- cgit v1.2.3