Commit 0580deaf authored by Rob Pike's avatar Rob Pike

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
https://golang.org/cl/1390041
parent 31f2503c
...@@ -4,9 +4,11 @@ ...@@ -4,9 +4,11 @@
/* /*
Package fmt implements formatted I/O with functions analogous 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. are simpler.
Printing:
The verbs: The verbs:
General: General:
...@@ -74,9 +76,23 @@ ...@@ -74,9 +76,23 @@
If an operand implements method String() string that method If an operand implements method String() string that method
will be used for %v, %s, or Print etc. 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 package fmt
// BUG(r): There is no format-driven scanning yet.
import ( import (
"bytes" "bytes"
......
...@@ -181,12 +181,32 @@ func (s *ss) token() string { ...@@ -181,12 +181,32 @@ func (s *ss) token() string {
return s.buf.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 // into successive arguments. Newlines count as space. Each argument must
// be a pointer to a basic type or an implementation of the Scanner // be a pointer to a basic type or an implementation of the Scanner
// interface. It returns the number of items successfully parsed. If that // interface. It returns the number of items successfully parsed. If that
// is less than the number of arguments, err will report why. // 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) s := newScanState(r, true)
n = s.doScan(a) n = s.doScan(a)
err = s.err err = s.err
...@@ -194,13 +214,13 @@ func Scan(r io.Reader, a ...interface{}) (n int, err os.Error) { ...@@ -194,13 +214,13 @@ func Scan(r io.Reader, a ...interface{}) (n int, err os.Error) {
return 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 // 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 // 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 // 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 // returns the number of items successfully parsed. If that is less than the
// number of arguments, err will report why. // 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) s := newScanState(r, false)
n = s.doScan(a) n = s.doScan(a)
err = s.err err = s.err
......
...@@ -135,11 +135,11 @@ func testScan(t *testing.T, scan func(r io.Reader, a ...interface{}) (int, os.Er ...@@ -135,11 +135,11 @@ func testScan(t *testing.T, scan func(r io.Reader, a ...interface{}) (int, os.Er
} }
func TestScan(t *testing.T) { func TestScan(t *testing.T) {
testScan(t, Scan) testScan(t, Fscan)
} }
func TestScanln(t *testing.T) { func TestScanln(t *testing.T) {
testScan(t, Scanln) testScan(t, Fscanln)
} }
func TestScanOverflow(t *testing.T) { func TestScanOverflow(t *testing.T) {
...@@ -147,7 +147,7 @@ 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") re := testing.MustCompile("overflow|too large|out of range|not representable")
for _, test := range overflowTests { for _, test := range overflowTests {
r := strings.NewReader(test.text) r := strings.NewReader(test.text)
_, err := Scan(r, test.in) _, err := Fscan(r, test.in)
if err == nil { if err == nil {
t.Errorf("expected overflow scanning %q", test.text) t.Errorf("expected overflow scanning %q", test.text)
continue continue
...@@ -162,7 +162,7 @@ func TestScanMultiple(t *testing.T) { ...@@ -162,7 +162,7 @@ func TestScanMultiple(t *testing.T) {
text := "1 2 3 x" text := "1 2 3 x"
r := strings.NewReader(text) r := strings.NewReader(text)
var a, b, c, d int 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 { if n != 3 {
t.Errorf("count error: expected 3: got %d", n) t.Errorf("count error: expected 3: got %d", n)
} }
...@@ -174,7 +174,7 @@ func TestScanMultiple(t *testing.T) { ...@@ -174,7 +174,7 @@ func TestScanMultiple(t *testing.T) {
func TestScanNotPointer(t *testing.T) { func TestScanNotPointer(t *testing.T) {
r := strings.NewReader("1") r := strings.NewReader("1")
var a int var a int
_, err := Scan(r, a) _, err := Fscan(r, a)
if err == nil { if err == nil {
t.Error("expected error scanning non-pointer") t.Error("expected error scanning non-pointer")
} else if strings.Index(err.String(), "pointer") < 0 { } else if strings.Index(err.String(), "pointer") < 0 {
...@@ -185,7 +185,7 @@ func TestScanNotPointer(t *testing.T) { ...@@ -185,7 +185,7 @@ func TestScanNotPointer(t *testing.T) {
func TestScanlnNoNewline(t *testing.T) { func TestScanlnNoNewline(t *testing.T) {
r := strings.NewReader("1 x\n") r := strings.NewReader("1 x\n")
var a int var a int
_, err := Scanln(r, &a) _, err := Fscanln(r, &a)
if err == nil { if err == nil {
t.Error("expected error scanning string missing newline") t.Error("expected error scanning string missing newline")
} else if strings.Index(err.String(), "newline") < 0 { } else if strings.Index(err.String(), "newline") < 0 {
...@@ -196,7 +196,7 @@ func TestScanlnNoNewline(t *testing.T) { ...@@ -196,7 +196,7 @@ func TestScanlnNoNewline(t *testing.T) {
func TestScanlnWithMiddleNewline(t *testing.T) { func TestScanlnWithMiddleNewline(t *testing.T) {
r := strings.NewReader("123\n456\n") r := strings.NewReader("123\n456\n")
var a, b int var a, b int
_, err := Scanln(r, &a, &b) _, err := Fscanln(r, &a, &b)
if err == nil { if err == nil {
t.Error("expected error scanning string with extra newline") t.Error("expected error scanning string with extra newline")
} else if strings.Index(err.String(), "newline") < 0 { } else if strings.Index(err.String(), "newline") < 0 {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment