-
Notifications
You must be signed in to change notification settings - Fork 17.9k
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: Scanf works differently on Windows and Linux #23562
Comments
@ans-ashkan thank you for raising this issue. I can reproduce what you see. I added some debugging: package main
import (
"fmt"
"os"
)
type myReader struct{}
func (r myReader) Read(p []byte) (n int, err error) {
n, err = os.Stdin.Read(p)
fmt.Fprintf(os.Stderr, "DEBUG: %q %v\n", p[:n], err)
return n, err
}
func main() {
input := myReader{}
var firstString string
var secondString string
fmt.Printf("Please enter first string:\n")
fmt.Fscanf(input, "%s", &firstString)
fmt.Printf("Please enter second string:\n")
_, err := fmt.Fscanf(input, "%s", &secondString)
fmt.Println(err)
} if I run this program, I see:
on Windows. Windows has Alex |
@rasky I'm confused, if the problem is |
The scanning code in fmt is cursed. cc @rsc |
We all agree that the \n after \r should be eaten by the first Scanf. |
fmt.Fscanf doesn't read newline so you should do: |
@mattn , but fmt.Scanf does read new lines and the code for fmt.Scanf is: func Scanf(format string, a ...interface{}) (n int, err error) {
return Fscanf(os.Stdin, format, a...)
} so fmt.Scanf calls fmt.Fscanf and it reads newlines. |
Hmm, fare enough. diff --git a/src/fmt/scan.go b/src/fmt/scan.go
index ae79e39dee..f3f5bb49f0 100644
--- a/src/fmt/scan.go
+++ b/src/fmt/scan.go
@@ -139,7 +139,7 @@ func Fscanln(r io.Reader, a ...interface{}) (n int, err error) {
// returns the number of items successfully parsed.
// Newlines in the input must match newlines in the format.
func Fscanf(r io.Reader, format string, a ...interface{}) (n int, err error) {
- s, old := newScanState(r, false, false)
+ s, old := newScanState(r, true, false)
n, err = s.doScanf(format, a)
s.free(old)
return Anyone know why this part is "true"? |
Which branch/commit?, I don't see "true" there. this is what it looks like in my version: func Fscanf(r io.Reader, format string, a ...interface{}) (n int, err error) {
s, old := newScanState(r, false, false)
n, err = s.doScanf(format, a)
s.free(old)
return
} |
Sorry, it's my typo. I want to know why this is |
Change https://golang.org/cl/110595 mentions this issue: |
The test case used to open this issue, after CL https://golang.org/cl/110595 is applied,
|
I've encountered a similar issue. The following code: package main
import (
"fmt"
"io"
"io/ioutil"
"os"
"strings"
)
func main() {
const data = "1\n2\n"
f, _ := ioutil.TempFile("", "strtest")
defer os.Remove(f.Name())
if _, err := f.WriteString(data); err != nil {
panic(err.Error())
}
if _, err := f.Seek(0, 0); err != nil {
panic(err.Error())
}
for i, r := range []io.Reader{strings.NewReader(data), f} {
a, b := 0, 0
fmt.Fscanf(r, "%d", &a)
fmt.Fscanf(r, "\n")
fmt.Fscanf(r, "%d", &b)
fmt.Printf("Reader %d: %d %d\n", i, a, b)
}
} produces
, but when I comment out the
I've tested this on go 1.10 linux/amd64 and on https://play.golang.org/ that it supposed to be running 1.11. |
Hi, I just want to give another use case (using numbers). So The code: package main
import "fmt"
func main() {
// Variables
var firstNumber float64
var secondNumber float64
// First number
fmt.Print("Please enter the first number: ")
n1, err1 := fmt.Scanf("%f", &firstNumber)
fmt.Println("Info: ", n1, err1) // debug info
fmt.Printf("The first number is: %v \n", firstNumber)
// Second number
fmt.Print("Please enter the second number: ")
n2, err2 := fmt.Scanf("%f", &secondNumber)
fmt.Println("Info: ", n2, err2) // debug info
fmt.Printf("The second number is: %v \n", secondNumber)
} Linux output
Windows output
|
I encounters the same problem. error-reproducible testing code: https://play.golang.org/p/s_VfYgM6ftj The problem, I think, happens because fmt package works depending on io.Reader's underlying type. |
I encounter the same problem. Programming language should support portability, and I think that fmt.Fscanf with CRLF or just LF should behave the same. I'm using windows and vagrant (ubuntu 18.04 with go inside) and it's a pain in the ass, please fix. |
This looks to becoming more of a common issue over the past few weeks, as we've seen an influx of newbies looking at Go due to quarantine. I've added a reply to the one outstanding comment on the change. The tl;dr is while I could be visualizing the code incorrectly, I believe CL 110595 should be considered for merge. I've rebased the change on top of master locally, and can confirm I was able to build the Go toolchain and all tests passed. @bcmills I see you were the last to make a status change on the CL. If we can resolve the comment from @griesemer, is there anything else blocking this change? cc @rsc |
Well, Hi i had a problem with scanf today import ( func main() {
}` |
I encounter the same problem. My ugly workaround for windows is using "github.com/eiannone/keyboard". Hope the KeyEnter is the same on Linux.
|
Hi , i used this to solve the problem: the first scan i used scanf and the second i used scanln. I hope this helps |
Change https://golang.org/cl/375214 mentions this issue: |
After spending some time on a possible fix, the behavior of Scanf() seems consistent. Using the same case, adding a blank after the input gets the same error on macOS and no more on windows. Documentation of
The suggested case uses format Line 1107 in da7891f
As mentioned in some comments, the input buffer is not cleared but read according to format which may exhaust before the input without contradiction. The current behavior is necessary to read an input stream using multiple Scanf() as in the example. The error is produced because the |
Change https://go.dev/cl/506016 mentions this issue: |
What version of Go are you using (
go version
)?go version go1.9.3 windows/amd64 and go version go1.9.3 linux/amd64
Does this issue reproduce with the latest release?
yes
What operating system and processor architecture are you using (
go env
)?on Windows:
on Linux:
What did you do?
What did you expect to see?
Same behavior on Windows and Linux.
Either it should capture
secondString
on Windows and Linux,or reject it on both operating systems.
What did you see instead?
on Windows:
unexpected newline
.on Linux: no errors.
The text was updated successfully, but these errors were encountered: