Neha
Neha

Reputation: 3650

Fast method to take input separated by space [Golang]

I'm trying to take fast input through scanner.Bytes and I'm it converting to int. The problem is : input provided is single line spaced elements ( like an array ) and scanner.Bytes reads it as a whole and converts it into int. How can I use a Splitfunction on the bytes read!

func main()  {
    scanner := bufio.NewScanner(os.Stdin)
    var t int
    fmt.Scanf("%d", &t)

    for o := 0; o < t; o++ {
        scanner.Scan()
        //scanner.Split(bufio.ScanWords())
        val := toInt(scanner.Bytes())
        fmt.Println(val)
    }
}

func toInt(buf []byte) (n int) {
    for _, v := range buf {
        n = n*10 + int(v-'0')
    }
    return
}

Upvotes: 5

Views: 3392

Answers (3)

Kaveh Shahbazian
Kaveh Shahbazian

Reputation: 13523

Assuming the input is 3 65 65 65 and 3 is the number of following bytes, then this works:

func main() {
    var t int
    fmt.Scanf("%d", &t)
    values := make([]byte, t)
    buf := make([]interface{}, t)
    for i := 0; i < t; i++ {
        buf[i] = &values[i]
    }
    fmt.Scanln(buf...)

    // test
    fmt.Printf("%v\n", values)
}

The test output is [65 65 65].

Upvotes: 1

icza
icza

Reputation: 417592

The default bufio.Scanner (with the default split function) breaks the input into lines with line termination stripped. If you want to break the input into words, you have to set a different split function using the Scanner.Split() method.

There is a ready split function for breaking words: bufio.ScanWords(). We can see this function commented in your code.

But know that Scanner.Split() method expects a function value. You do not need to call the split function, the scanner will call it to break the input data. You just have to pass the function value, which you can do so without calling it, without appending () after the function name, e.g.:

scanner.Split(bufio.ScanWords)

Also note that you only have to do this once, and you can only do this once, before starting to scan the input, so move this line above the for loop:

var t int
fmt.Scanf("%d", &t)

scanner := bufio.NewScanner(os.Stdin)
scanner.Split(bufio.ScanWords)
for o := 0; o < t; o++ {
    scanner.Scan()
    val := toInt(scanner.Bytes())
    fmt.Println(val)
}

Now running the app, and entering the following lines:

3
1 2 3

The output will be:

1
2
3

Also note that Scanner.Scan() returns a bool value indicating if scanning was successful and you may process the token. You should use this return value and not rely on the user inputting valid data.

Upvotes: 5

Amnon
Amnon

Reputation: 334

why not just try something like

func main()  {
    scanner := bufio.NewScanner(os.Stdin)

    for scanner.Scan() {
        val, err := strconv.Atoi(scanner.Text())
        if err != nil {
            log.Fatal(err)
        }
        fmt.Println(val)
    }
}

Upvotes: 1

Related Questions