문제
나는 scanf ()와 동등한 GO를 찾고 있습니다. 다음 코드로 시도했습니다.
1 package main
2
3 import (
4 "scanner"
5 "os"
6 "fmt"
7 )
8
9 func main() {
10 var s scanner.Scanner
11 s.Init(os.Stdin)
12 s.Mode = scanner.ScanInts
13 tok := s.Scan()
14 for tok != scanner.EOF {
15 fmt.Printf("%d ", tok)
16 tok = s.Scan()
17 }
18 fmt.Println()
19 }
정수 줄이있는 텍스트에서 입력으로 실행합니다. 그러나 항상 -3-3을 출력합니다.
그리고 문자열과 정수로 구성된 줄을 스캔하는 방법은 무엇입니까? 새 데이터 유형이 발생할 때마다 모드 변경?
패키지 문서 :
패키지 스캐너
UTF-8 인코딩 된 텍스트에 대한 일반 목적 스캐너.
그러나 스캐너는 일반적인 용도가 아닌 것 같습니다.
업데이트 된 코드 :
func main() {
n := scanf()
fmt.Println(n)
fmt.Println(len(n))
}
func scanf() []int {
nums := new(vector.IntVector)
reader := bufio.NewReader(os.Stdin)
str, err := reader.ReadString('\n')
for err != os.EOF {
fields := strings.Fields(str)
for _, f := range fields {
i, _ := strconv.Atoi(f)
nums.Push(i)
}
str, err = reader.ReadString('\n')
}
r := make([]int, nums.Len())
for i := 0; i < nums.Len(); i++ {
r[i] = nums.At(i)
}
return r
}
개선 된 버전 :
package main
import (
"bufio"
"os"
"io"
"fmt"
"strings"
"strconv"
"container/vector"
)
func main() {
n := fscanf(os.Stdin)
fmt.Println(len(n), n)
}
func fscanf(in io.Reader) []int {
var nums vector.IntVector
reader := bufio.NewReader(in)
str, err := reader.ReadString('\n')
for err != os.EOF {
fields := strings.Fields(str)
for _, f := range fields {
if i, err := strconv.Atoi(f); err == nil {
nums.Push(i)
}
}
str, err = reader.ReadString('\n')
}
return nums
}
해결책
업데이트 된 코드는 줄 번호가 없으면 컴파일하기가 훨씬 쉽지만 패키지 및 가져 오기 문에는 누락되었습니다.
당신의 코드를보고, 나는 몇 가지를 발견했습니다. 다음은 수정 된 코드 버전입니다.
package main
import (
"bufio"
"fmt"
"io"
"os"
"strconv"
"strings"
"container/vector"
)
func main() {
n := scanf(os.Stdin)
fmt.Println()
fmt.Println(len(n), n)
}
func scanf(in io.Reader) []int {
var nums vector.IntVector
rd := bufio.NewReader(os.Stdin)
str, err := rd.ReadString('\n')
for err != os.EOF {
fields := strings.Fields(str)
for _, f := range fields {
if i, err := strconv.Atoi(f); err == nil {
nums.Push(i)
}
}
str, err = rd.ReadString('\n')
}
return nums
}
입력 파일을 사용하고 싶을 수도 있습니다 scanf()
, 뿐만 아니라 Stdin
; scanf()
가져갑니다 io.Reader
매개 변수로.
당신은 다음과 같이 썼습니다. nums := new(vector.IntVector)
, 어디 type IntVector []int
. 이것은 이름이 지정된 정수 슬라이스 참조를 할당합니다 nums
그리고 그것을 0으로 초기화 한 다음 new()
함수는 정수 슬라이스 참조를 할당하고 0으로 초기화 한 다음 할당합니다. nums
. 나는 썼다 : var nums vector.IntVector
, 이는 단순히 정수 슬라이스 참조를 할당하여 중복성을 피합니다. nums
그리고 그것을 0으로 초기화합니다.
당신은 확인하지 않았습니다 err
가치 strconv.Atoi()
, 이는 유효하지 않은 입력이 0 값으로 변환되었음을 의미했습니다. 나는 그것을 건너 뜁니다.
벡터에서 새 조각으로 복사하고 슬라이스를 반환하려면 다음과 같이 썼습니다.
r := make([]int, nums.Len())
for i := 0; i < nums.Len(); i++ {
r[i] = nums.At(i)
}
return r
먼저, 나는 단순히 그것을 동등한 것으로 대체했습니다. IntVector.Data()
방법: return nums.Data()
. 그런 다음 사실을 활용했습니다 type IntVector []int
다음을 대체하여 할당 및 복사를 피했습니다. return nums
.
다른 팁
다른 것들에 사용할 수 있지만 스캐너 패키지는 GO 프로그램 텍스트를 스캔하도록 설계되었습니다. ints (-123), chars ( 'c'), 문자열 ( "str") 등은 언어 토큰 유형입니다.
package main
import (
"fmt"
"os"
"scanner"
"strconv"
)
func main() {
var s scanner.Scanner
s.Init(os.Stdin)
s.Error = func(s *scanner.Scanner, msg string) { fmt.Println("scan error", msg) }
s.Mode = scanner.ScanInts | scanner.ScanStrings | scanner.ScanRawStrings
for tok := s.Scan(); tok != scanner.EOF; tok = s.Scan() {
txt := s.TokenText()
fmt.Print("token:", tok, "text:", txt)
switch tok {
case scanner.Int:
si, err := strconv.Atoi64(txt)
if err == nil {
fmt.Print(" integer: ", si)
}
case scanner.String, scanner.RawString:
fmt.Print(" string: ", txt)
default:
if tok >= 0 {
fmt.Print(" unicode: ", "rune = ", tok)
} else {
fmt.Print(" ERROR")
}
}
fmt.Println()
}
}
이 예제는 항상 한 번에 한 줄로 읽히고 전체 줄을 문자열로 반환합니다. 특정 값을 구문 분석하고 싶다면 할 수 있습니다.
package main
import (
"fmt"
"bufio"
"os"
"strings"
)
func main() {
value := Input("Please enter a value: ")
trimmed := strings.TrimSpace(value)
fmt.Printf("Hello %s!\n", trimmed)
}
func Input(str string) string {
print(str)
reader := bufio.NewReader(os.Stdin)
input, _ := reader.ReadString('\n')
return input
}
내 답변 중 하나에 대한 의견에서 당신은 다음과 같이 말했습니다.
언어 사양에서 : "메모리가 선언 또는 () 또는 새 () 호출을 통해 값을 저장하기 위해 할당되면 명시 적 초기화가 제공되지 않으면 메모리에 기본 초기화가 제공됩니다." 그렇다면 New ()의 요점은 무엇입니까?
우리가 달리는 경우 :
package main
import ("fmt")
func main() {
var i int
var j *int
fmt.Println("i (a value) = ", i, "; j (a pointer) = ", j)
j = new(int)
fmt.Println("i (a value) = ", i, "; j (a pointer) = ", j, "; *j (a value) = ", *j)
}
선언 var i int
정수 값을 저장하기 위해 메모리를 할당하고 값을 0으로 초기화합니다. 선언 var j *int
정수 값에 대한 포인터를 저장하기 위해 메모리를 할당하고 포인터를 0으로 초기화합니다 (NIL 포인터). 정수 값을 저장하기 위해 메모리가 할당되지 않습니다. 우리는 다음과 유사한 프로그램 출력을 본다.
i (a value) = 0 ; j (a pointer) = <nil>
내장 기능 new
유형을 취합니다 T
유형의 값을 반환합니다 *T
. 메모리는 0 값으로 초기화됩니다. 진술 j = new(int)
정수 값을 저장하기 위해 메모리를 할당하고 값을 0으로 초기화 한 다음 J 의이 정수 값에 대한 포인터를 저장합니다. 우리는 다음과 유사한 프로그램 출력을 본다.
i (a value) = 0 ; j (a pointer) = 0x7fcf913a90f0 ; *j (a value) = 0
최신 GO (2010-05-27)의 최신 릴리스는 두 가지 기능을 추가했습니다. fmt
패키지: Scan()
그리고 Scanln()
. 패턴 문자열을 사용하지 않습니다. C에서와 마찬가지로, 대신 인수의 유형을 확인합니다.
package main
import (
"fmt"
"os"
"container/vector"
)
func main() {
numbers := new(vector.IntVector)
var number int
n, err := fmt.Scan(os.Stdin, &number)
for n == 1 && err == nil {
numbers.Push(number)
n, err = fmt.Scan(os.Stdin, &number)
}
fmt.Printf("%v\n", numbers.Data())
}