Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fmt: Sscanf handles spaces and \n inconsistently #8515

Closed
gopherbot opened this issue Aug 12, 2014 · 2 comments
Closed

fmt: Sscanf handles spaces and \n inconsistently #8515

gopherbot opened this issue Aug 12, 2014 · 2 comments

Comments

@gopherbot
Copy link

by kwalsh@holycross.edu:

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.
@ianlancetaylor
Copy link
Contributor

Comment 1:

Labels changed: added repo-main, release-none.

@bradfitz bradfitz removed the new label Dec 18, 2014
@rsc rsc added this to the Unplanned milestone Apr 10, 2015
@robpike
Copy link
Contributor

robpike commented Jul 1, 2015

Duplicate of #8944.

@robpike robpike closed this as completed Jul 1, 2015
@golang golang locked and limited conversation to collaborators Jul 1, 2016
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

5 participants