Я ищу Движение, эквивалентное из scanf (). Я попробовал следующим кодом:
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 и import.
Глядя на ваш код, я заметил несколько вещей. Вот моя исправленная версия вашего кода.
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
и инициализирует ее нулем, затем функция new ()
выделяет целочисленную ссылку на слайс и инициализирует ее нулем, а затем присваивает ее ] nums
. Я написал: var nums vector.IntVector
, что позволяет избежать избыточности, просто выделяя целочисленную ссылку на фрагмент с именем nums
и инициализируя ее нулем.
Вы не проверили значение err
для strconv.Atoi ()
, что означает, что неверный ввод был преобразован в нулевое значение; Я это пропускаю.
Чтобы скопировать из вектора в новый срез и вернуть срез, вы написали:
r := make([]int, nums.Len())
for i := 0; i < nums.Len(); i++ {
r[i] = nums.At(i)
}
return r
Во-первых, я просто заменил его на эквивалент, метод IntVector.Data ()
: вернуть nums.Data ()
. Затем я воспользовался тем фактом, что тип IntVector [] int
избежал выделения и копирования, заменив это на: return nums
.
Хотя его можно использовать для других целей, пакет сканера предназначен для сканирования текста программы Go. Ints (-123), Chars ('c'), Strings ("str") и т. Д. Являются типами токенов языка Go.
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()
}
}
В комментарии к одному из моих ответов вы сказали:
Из спецификации языка: "Когда {{ 1}} память выделяется для хранения значения либо посредством объявления, либо вызова make () или new (), и явная инициализация не предоставляется, память { {1}} получает инициализацию по умолчанию ". Тогда в чем смысл 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
выделяет память для хранения целочисленное значение и инициализирует значение нулем. Объявление var j * int
выделяет память для хранения указателя на целочисленное значение и инициализирует указатель нулем (указатель nil); для хранения целочисленного значения память не выделяется. Мы видим вывод программы, подобный следующему:
i (a value) = 0 ; j (a pointer) = <nil>
Встроенная функция new
принимает тип T
и возвращает значение типа * T
.Память инициализируется нулевыми значениями. Оператор j = new (int)
выделяет память для хранения целочисленного значения и инициализирует значение нулем, а затем сохраняет указатель на это целочисленное значение в j. Мы видим вывод программы, подобный следующему:
i (a value) = 0 ; j (a pointer) = 0x7fcf913a90f0 ; *j (a value) = 0
В этом примере всегда выполняется чтение по строке за раз и возвращается вся строка в виде строки. Если вы хотите извлечь из него определенные значения, вы можете.
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
}
В последней версии Go (27.05.2010) в пакет 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())
}