Why the newline after the %d is eaten but not the %c in the fmt.Scanf?

Viewed 102
package main

import (
    "fmt"
    "log"
)

func main() {
    var num int
    n, err := fmt.Scanf("%d", &num)
    fmt.Println(n, num)
    if err != nil {
        log.Fatalln(err)
    }

    var r1 rune
    n, err = fmt.Scanf("%c", &r1)
    fmt.Println(n, r1)
    if err != nil {
        log.Fatalln(err)
    }

    var r2 rune
    n, err = fmt.Scanf("%c", &r2)
    fmt.Println(n, r2)
    if err != nil {
        log.Fatalln(err)
    }
}

input(Keyboard keys) is: 1 enter a enter
output is:
1 1
1 97
1 10

Why the value of r2 is \n but the the value of r1 is a?

In the comment of the fmt.Scanf:

Newlines in the input must match newlines in the format. The one exception: the verb %c always scans the next rune in the input, even if it is a space (or tab etc.) or newline.

It seems that the newline after the %d is eaten but the newline after %c is not. Is the newline after the %d miss matching?

Another example: https://play.studygolang.com/p/lRgxrUqyBTI , I try to use a buffer to substitute for the stdin, but the output is different from using the stdin.

go version is go version go1.17.1 windows/amd64

1 Answers

a newline is a single character that is valid input for a rune but not for a int, so when you capture a rune the new line is read and stored while that is not done for other types.

if you don't capture the new line while reading to a rune you will get the error "unexpected newlnie" if yuo try to read from stdin again.

i suggest you do the following to read runes so you always capture the newline and don't get unexpected results

var r1, r2 rune
n, err = fmt.Scanf("%c%c", &r1, &r2)
fmt.Println(n, r1, r2)
if err != nil {
    log.Fatalln(err)
}
Related