go version)?go version go1.9.3 windows/amd64 and go version go1.9.3 linux/amd64
yes
go env)?on Windows:
set GOARCH=amd64
set GOBIN=
set GOEXE=.exe
set GOHOSTARCH=amd64
set GOHOSTOS=windows
set GOOS=windows
set GOPATH=D:\golang
set GORACE=
set GOROOT=C:\Go
set GOTOOLDIR=C:\Go\pkg\tool\windows_amd64
set GCCGO=gccgo
set CC=gcc
set GOGCCFLAGS=-m64 -mthreads -fmessage-length=0 -fdebug-prefix-map=C:\Users\ANS_AS~1\AppData\Local\Temp\go-build251374523=/tmp/go-build -gno-record-gcc-switches
set CXX=g++
set CGO_ENABLED=1
set CGO_CFLAGS=-g -O2
set CGO_CPPFLAGS=
set CGO_CXXFLAGS=-g -O2
set CGO_FFLAGS=-g -O2
set CGO_LDFLAGS=-g -O2
set PKG_CONFIG=pkg-config
on Linux:
GOARCH="amd64"
GOBIN=""
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/home/ans_ashkan/go"
GORACE=""
GOROOT="/usr/local/go"
GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
GCCGO="gccgo"
CC="gcc"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build871792404=/tmp/go-build -gno-record-gcc-switches"
CXX="g++"
CGO_ENABLED="1"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
package main
import "fmt"
func main() {
var firstString string
var secondString string
fmt.Printf("Please enter first string:\n")
fmt.Scanf("%s", &firstString)
fmt.Printf("Please enter second string:\n")
n, err := fmt.Scanf("%s", &secondString)
fmt.Println(err)
}
Same behavior on Windows and Linux.
Either it should capture secondString on Windows and Linux,
or reject it on both operating systems.
on Windows: unexpected newline.
on Linux: no errors.
@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:
C:\>u:\test
Please enter first string:
first
DEBUG: "f" <nil>
DEBUG: "i" <nil>
DEBUG: "r" <nil>
DEBUG: "s" <nil>
DEBUG: "t" <nil>
DEBUG: "\r" <nil>
Please enter second string:
DEBUG: "\n" <nil>
unexpected newline
C:\>
on Windows. Windows has \r\n as line delimiters, instead of \n on Linux. I am not sure what to do here. Leaving for others to decide.
Alex
The documentation of the package says: In all the scanning functions, a carriage return followed immediately by a newline is treated as a plain newline (\r\n means the same as \n).
I would think this is a bug but maybe a fmt expert should confirm. /cc @robpike @martisch
@rasky I'm confused, if the problem is \r\n then what is happening in this playground. (this is using Fscanf though that is what Scanf does under the hood)
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"?
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 false?
Change https://golang.org/cl/110595 mentions this issue: fmt: Scanning newlines should work the same way on Windows and Linux
The test case used to open this issue, after CL https://golang.org/cl/110595 is applied,
i23562.go:
package main
import "fmt"
func main() {
var firstString string
var secondString string
fmt.Printf("Please enter first string:\n")
n, err := fmt.Scanf("%s", &firstString)
fmt.Println(n, err, firstString)
fmt.Printf("Please enter second string:\n")
n, err = fmt.Scanf("%s", &secondString)
fmt.Println(n, err, secondString)
}
/*
Linux:
$ go run i23562.go
Please enter first string:
first
1 <nil> first
Please enter second string:
second
1 <nil> second
$
Windows:
>go run i23562.go
Please enter first string:
first
1 <nil> first
Please enter second string:
second
1 <nil> second
>
*/
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
Reader 0: 1 2
Reader 1: 1 0
, but when I comment out the fmt.Fscanf(r, "\n"), it flips:
Reader 0: 1 0
Reader 1: 1 2
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 Scanf gives no error on Linux but does not work on Windows. (Using go 1.11.4)
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
Please enter the first number: 20
Info: 1 <nil>
The first number is: 20
Please enter the second number: 30
Info: 1 <nil>
The second number is: 30
Windows output
Here the program dosen't even let to write the number, just defaults to 0
Please enter the first number: 20
Info: 1 <nil>
The first number is: 20
Please enter the second number: Info: 0 unexpected newline
The second number is: 0
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
here is the code :
`package main
import (
"fmt"
)
//
func checkrow(n int, line int,column int, matrizSize int, matrix [100][100]int,r int) (int,bool){
if column!=0{
for c:=0;c
return r + 1, false
}
}
}
return r,true
}
func checkcolumn(n int,line int,column int,matrix [100][100]int,c int,matrizSize int) (int,bool){
if line!=0 {
for l := 0; l
return c + 1, false
}
}
}
return c,true
}
func main() {
var matrix [100][100]int
k:=0 //tracer (sum of main diagonal numbers)
c:=0 //number of columns that have repeated numbers
r:=0 //number of rows that contain repetead numbers
T:=0 // numbers of texts
row:=true
col:=true
var matrizSize int // size of matriz
fmt.Scanf("%d ",&T)
fmt.Scanf("%d",&matrizSize)
fmt.Scanf("%d","")
for i:=0; i
for column := 0; column < matrizSize; column++ {//column
fmt.Scanf("%d ", &matrix[line][column])
if column==line {
k = k + matrix[line][column]
}
if row==true {
r, row = checkrow(matrix[line][column], line,column, matrizSize, matrix,r)
}
if col==true {
c, col = checkcolumn(matrix[line][column],line, column, matrix, c, matrizSize)
}
}
col=true
row=true
}
fmt.Printf("Case n° %d: %d %d %d\n",i+1,k,r,c)
i++
if i<T-1 {
fmt.Scanf(" %d", &matrizSize)
fmt.Scanf("%d","")
}
k=0
r=0
c=0
}
}`
To resume i was getting the secound scanf, being satisfied by something, probably a "\n" from the first one, so the solution, was kinda similiar that i used with scanf on C give a space after and sometimes use a empty scanf. Is sad see that, as far i know, Go don't have a simple way, like a standard func, to clear the keyboard buffer, at least scanf should clear after receive a input, so it will make multiples scanf, run without a problem.
I encounter the same problem. My ugly workaround for windows is using "github.com/eiannone/keyboard". Hope the KeyEnter is the same on Linux.
func ScanKeyb() string {
var input string
for {
char, key, err := keyboard.GetKey()
if err != nil {
panic(err)
} else if key == keyboard.KeyEnter {
fmt.Println()
break
}
fmt.Printf("%c", char)
input += fmt.Sprintf("%c", char)
}
return input
}
Hi , i used this to solve the problem:
fmt.Println("test1")
fmt.Scanf("%s\n", &nr)
fmt.Println("test2")
fmt.Scanln(&n1)
the first scan i used scanf and the second i used scanln. I hope this helps
Most helpful comment
The scanning code in fmt is cursed. cc @rsc