ungetc behavior in go

130 views
Skip to first unread message

Doğan Kurt

unread,
Aug 14, 2017, 8:09:01 AM8/14/17
to golang-nuts
I want to do something analogous to this C code.

c = getchar()

if (isdigit(c)) {
ungetc(c, stdin);
scanf("%d", &num);
}

In fmt package, fmt.Scanf("%d", &num) exists but ungetc doesn't exist. For bufio package, Peek function exists which is great but there is no ReadInt. 

Is there an elegant solution that i can use for this situation? Otherwise i will read byte by byte as long as i have a digit and convert it to integer once i'm done.

The input i am trying to tokenize is something like,

(32 + 5) * 2 - 5 / (41 - 7)

Thanks.

Konstantin Khomoutov

unread,
Aug 14, 2017, 8:29:51 AM8/14/17
to Doğan Kurt, golang-nuts
On Mon, Aug 14, 2017 at 05:09:00AM -0700, Doğan Kurt wrote:

> I want to do something analogous to this C code.
>
> c = getchar()
>
> if (isdigit(c)) {
> ungetc(c, stdin);
> scanf("%d", &num);
> }
>
> In fmt package, fmt.Scanf("%d", &num) exists but ungetc doesn't exist. For
> bufio package, Peek function exists which is great but there is no ReadInt.

Consider combining using the bufio package and scanning form a buffered
reader using fmt.Fscanf().

Please see the documentation on the fmt package and notice that the
function it exports come in packs where the first letter of the name of
each function in such a pack indicates ...

For instance:
- Print() just prints to os.Stdout, Printf() is "print formatted".
- Fprint() is "file print" -- it outputs to the specified io.Writer.
- Sprint() is "string print" -- it outputs to a string.

The pack of functions to do scanning roughly conforms to the same idea:
- Scan() scans from os.Stdin.
- Scanf() is "scan formatted".
- Fscan() scans from the specified io.Reader.
- Sscan() scans from a string.
...

Doğan Kurt

unread,
Aug 14, 2017, 8:43:04 AM8/14/17
to golang-nuts, kultig...@gmail.com
Consider combining using the bufio package and scanning form a buffered 
reader using fmt.Fscanf(). 

Great worked like a charm. I just thought i couldn't pass *bufio.Reader to Fscanf which takes io.Reader. 

Konstantin Khomoutov

unread,
Aug 14, 2017, 8:51:13 AM8/14/17
to Doğan Kurt, golang-nuts
Oh, then that's something which you definitely should make yourself
accustomed more -- this consept is one of the corner stones of Go.

Basically, interfaces in Go are sort-of "backwards" to what they mean in
other, "more mainstream" languages. The fact fmt.Fscanf() accepts an
io.Reader means it accepts a value of absolulely any type which
implements func Read ([]byte) (int, error). So it would accept, say, a
network socket just as fine as a bufio.Reader or bytes.Buffer or any
other custom type implementing that method.

[1] might be a good start.

1. https://golang.org/doc/effective_go.html#interfaces_and_types

Doğan Kurt

unread,
Aug 14, 2017, 9:09:00 AM8/14/17
to golang-nuts, kultig...@gmail.com
Thanks it's perfectly clear now. I actually knew that but it didn't look immediately obvious. 
Reply all
Reply to author
Forward
0 new messages