November 02, 2010
Hello.

I'm new to D and I stumbled upon something strange about readf while writing some test code.

The code:

import std.stream;
import std.stdio;

int main(char[][] args)
{
	string input = "2abc";
	auto memstream = new TArrayStream!(string)(input);
	int x;
	memstream.readf("%d", &x);
	char[] s = memstream.readString(x);
	writefln("%d:%s", x, s); // expected 2:ab, writes 2:bc.
	return 0;
}

After looking in stream.d I can understand why it is working in unexpected way (readf uses ungetc() which has no effect on readString() ), but is it intended behavior? I see in documentation that ungetc() affects only what is read afterwards with getc(), but no mention that readf() is incompatible with other reading methods.

It wouldn't even be the problem if I knew for sure that there is always _exactly_ one char offset, or that return value of readf must be number of bytes read from stream. Is it so or is it all just the way it happened to be in current implementation?

On another topic. Compiled with D 2.050 it won't work at all, printing "object.Error: Access Violation". Apparently readf in 2.0 requires mutable string as a format string. Writing it like this

memstream.readf("%d".dup, &x);

works. Is it intended too?

On yet another topic :) Is there alternative to stream.readf? Somehow while searching for explanation of unexpected behavior I got the idea that readf and streams considered to be second-class citizens in world of D and they are not a proper way to do things, so no one really cares about them... Therefore the question. What do I use to read numbers from file?
November 02, 2010
Nick Voronin:

> On yet another topic :) Is there alternative to stream.readf? Somehow while searching for explanation of unexpected behavior I got the idea that readf and streams considered to be second-class citizens in world of D and they are not a proper way to do things, so no one really cares about them... Therefore the question. What do I use to read numbers from file?

In std.stdio there is a function to read a line, and then you may use std.conv.parse or std.conv.to.

Bye,
bearophile