문제

나는 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())
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top