Join GitHub today
GitHub is home to over 50 million developers working together to host and review code, manage projects, and build software together.Sign up
GitHub is where the world builds software
Millions of developers and companies build, ship, and maintain their software on GitHub — the largest and most advanced development platform in the world.
fmt: Sscanf handles spaces and \n inconsistently #8515
What does 'go version' print? go version go1.3 linux/amd64 What steps reproduce the problem? If possible, include a link to a program on play.golang.org. Example: http://play.golang.org/p/RoYiOHlHCQ Try any of these examples with var x, y int 1. n, err = fmt.Sscanf("7 8", "%d %d", &x, &y) 2. n, err = fmt.Sscanf("7\n8", "%d %d", &x, &y) 3. n, err = fmt.Sscanf("7 8", "%d%d", &x, &y) 4. n, err = fmt.Sscanf("7\n8", "%d%d", &x, &y) 5. n, err = fmt.Sscanf("7\n\n8", "%d\n\n%d", &x, &y) What happened? The results are, respectively: 1. n=2 2. n=2 3. n=2 4. n=1 5. n=1 What should have happened instead? If I am to believe the documentation for fmt, something like: 1. n=2 2. n=1 3. n=1 4. n=1 5. n=2 Please provide any additional information below. See also issue #8236 for a related error. Case (1) is as expected. All the other examples give surprising results, either contradicting other examples or directly contradicting the docs. The docs says "Scanf, Fscanf and Sscanf require newlines in the input to match newlines in the format". Case (2) contradicts that, since apparently newlines in the input can instead match a variety of kinds of space in the format. The docs says "When scanning with a format, all non-empty runs of space characters (except newline) are equivalent to a single space in both the format and the input. With that proviso, text in the format string must match the input text;" Case (3) contradicts that, since apparently certain spaces in the input don't have to match anything in the format. Case (4) is similar to case (3), but gives different results (arguably following the docs this time). Case (5) is just crazy talk, since the format matches the input perfectly. Some of the problem seems to stem from fmt/scan.go:1075 func (s *ss) advance(format string) (i int) which seems to treaty *any* sequence of spaces (including newlines) in the format string as being equivalent to a single space, directly contradicting the docs for Sscanf and friends. It also mishandles the case of "\r\n" in the input because, around line 1096 it directly checks for '\n' without bothering to check for '\r' too. And all of that code completely ignores ss.nlIsSpace, but then after the first input space it invokes skipSpace which has yet different behavior. Compounding those problems, in fmt/scan.go:651 func (s *ss) scanInt(verb rune, bitSize int) int64 and many similar functions, skipSpace() is called, though the docs mention nothing about skipping leading spaces. I think this one is just a documentation bug: classic C scanf ignores leading spaces for most verbs, and apparently fmt/scan does too but does not document that behavior and actually repeatedly implies the opposite.