www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - reading formatted strings: readf("%s", &stringvar)

reply "Tyro[17]" <nospam home.com> writes:
I am trying to figure out the cause of my problem in the 
following post:

      
http://forum.dlang.org/thread/qfbugjkrerfboqhvjttw forum.dlang.org

and encountered something peculiar about reading strings. 
Whenever a distinct terminator is indicated in the input format 
(ex. " %s ",   being the terminator), readf() leaves the 
terminator on the input buffer after reading the data. If no 
terminator is specified the only way to indicate end of input is 
to use ctrl-d (ctrl-z on windows), however that causes the eof 
indicator to be set to true and the stream is marked as empty for 
all future attempts to access stdin.

void main(string[] args)
{
     string s1;
     double d;
     string s2;

     writeln("Enter a   terminated string (multiline ok):");
     readf(" %s ", &s1);
     auto arr = s1.split();

     if (!stdin.eof()) {
         writeln("The stream is not empty.");
     } else {
         writeln("The stream is empty.");
     }
     writeln("Enter another string (terminated with 
cntrl-d|ctrl-z):");
     readf(" %s", &s2);  // No matter how many read attempts
                                 // are made after this point, 
none of them will work.
                                 // Insert \n after %s to see 
difference.

     writeln("Enter a decimal value:");
     readf(" %s", &d);
     //readf(" %s", &d);
     //readf(" %s", &d);
     //readf(" %s", &d);
     //readf(" %s", &d);

     if (!stdin.eof()) {
         writeln("The stream is not empty.");
     } else {
         writeln("The stream is empty.");
     }

     writeln("d = ", d);
     writeln("arr = ", arr);
     writeln("s = ", s2);
}

Is there no way to indicate eof without marking the stream 
(buffer?) as empty for all future uses after encountering 
cntrl-d/cntrl-z during string input? I would expect to be able to 
terminate string input with cntrl-d/cntrl-z without rendering the 
input stream inaccessible.

Thanks,
Andrew
Mar 25 2012
parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 03/25/2012 06:00 AM, Tyro[17] wrote:
 I am trying to figure out the cause of my problem in the following post:

 http://forum.dlang.org/thread/qfbugjkrerfboqhvjttw forum.dlang.org
Sorry that I missed your question there. :(
 and encountered something peculiar about reading strings. Whenever a
 distinct terminator is indicated in the input format (ex. " %s ",  
 being the terminator), readf() leaves the terminator on the input buffer
 after reading the data. If no terminator is specified the only way to
 indicate end of input is to use ctrl-d (ctrl-z on windows), however that
 causes the eof indicator to be set to true and the stream is marked as
 empty for all future attempts to access stdin.

 void main(string[] args)
 {
 string s1;
 double d;
 string s2;

 writeln("Enter a   terminated string (multiline ok):");
 readf(" %s ", &s1);
 auto arr = s1.split();

 if (!stdin.eof()) {
 writeln("The stream is not empty.");
 } else {
 writeln("The stream is empty.");
 }
 writeln("Enter another string (terminated with cntrl-d|ctrl-z):");
I am not sure about the cntrl-d|ctrl-z part though. Since it terminates the input, the program should not be able to read any more characters.
 readf(" %s", &s2); // No matter how many read attempts
I advise reading string by readln(). You can call chomp() to get rid of whitespace around it: while (s2.length == 0) { s2 = chomp(readln()); } This has been my understanding of the matter: [1] <quote> There are surprises even when reading strings from the console. Being character arrays, strings can contain control characters like '\n' as well. When reading strings from the input, the control character that corresponds to the Enter key that is pressed at the end of console input becomes a part of the string as well. Further, because there is no way to tell readf() how many characters to read, it continues to read until the end of the entire input. For these reasons, readf() does not work as intended when reading strings: </quote>
 // are made after this point, none of them will work.
 // Insert \n after %s to see difference.

 writeln("Enter a decimal value:");
 readf(" %s", &d);
 //readf(" %s", &d);
 //readf(" %s", &d);
 //readf(" %s", &d);
 //readf(" %s", &d);

 if (!stdin.eof()) {
 writeln("The stream is not empty.");
 } else {
 writeln("The stream is empty.");
 }

 writeln("d = ", d);
 writeln("arr = ", arr);
 writeln("s = ", s2);
 }

 Is there no way to indicate eof without marking the stream (buffer?) as
 empty for all future uses after encountering cntrl-d/cntrl-z during
 string input? I would expect to be able to terminate string input with
 cntrl-d/cntrl-z without rendering the input stream inaccessible.

 Thanks,
 Andrew
With the change above (and assuming that we don't end the stream), the rest of the reads succeed for me. Ali [1] http://ddili.org/ders/d.en/strings.html
Mar 25 2012
next sibling parent reply "Tyro[17]" <nospam home.com> writes:
First of all thank your very much for your assistance.

On Sunday, 25 March 2012 at 15:04:30 UTC, Ali Çehreli wrote:
 On 03/25/2012 06:00 AM, Tyro[17] wrote:
 I am trying to figure out the cause of my problem in the
following post:
 
http://forum.dlang.org/thread/qfbugjkrerfboqhvjttw forum.dlang.org Sorry that I missed your question there. :(
 and encountered something peculiar about reading strings.
Whenever a
 distinct terminator is indicated in the input format (ex. "
%s ",
 being the terminator), readf() leaves the terminator on the
input buffer
 after reading the data. If no terminator is specified the
only way to
 indicate end of input is to use ctrl-d (ctrl-z on windows),
however that
 causes the eof indicator to be set to true and the stream is
marked as
 empty for all future attempts to access stdin.

 void main(string[] args)
 {
 string s1;
 double d;
 string s2;

 writeln("Enter a   terminated string (multiline ok):");
 readf(" %s ", &s1);
 auto arr = s1.split();

 if (!stdin.eof()) {
 writeln("The stream is not empty.");
 } else {
 writeln("The stream is empty.");
 }
 writeln("Enter another string (terminated with
cntrl-d|ctrl-z):"); I am not sure about the cntrl-d|ctrl-z part though. Since it terminates the input, the program should not be able to read any more characters.
 readf(" %s", &s2); // No matter how many read attempts
I advise reading string by readln(). You can call chomp() to get rid of whitespace around it: while (s2.length == 0) { s2 = chomp(readln()); }
You can achieve the same with: readf(" %s\n", &s2); My goal however, is not to read one line of information. Rather, it is to read multiple lines of information from standard input. I get close to being able to do so if i don't including "\n" as a part of my format string or if I changing your suggestion to while (!stdin.eol()) { s2 = chomp(readln()); } but again I run into the predicament was before, a need to close the the stream with Ctrl-D/Ctrl-Z. Andrew
Mar 26 2012
next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 3/26/12 5:55 AM, Tyro[17] wrote:
 You can achieve the same with:

 readf(" %s\n", &s2);

 My goal however, is not to read one line of information. Rather, it is to
 read multiple lines of information from standard input. I get close to
 being able to do so if i don't including "\n" as a part of my format string
 or if I changing your suggestion to

 while (!stdin.eol()) {
 s2 = chomp(readln());
 }

 but again I run into the predicament was before, a need to close the
 the stream with Ctrl-D/Ctrl-Z.
I made the decision for the current behavior while implementing readf. Basically I tried to avoid what I think was a mistake of scanf, i.e. that of stopping string reading at the first whitespace character, which is fairly useless. Over the years scanf was improved with %[...] which allows reading strings with any characters in a set. Anyway, if I understand correctly, there's no way to achieve what you want unless you read character-by-character and define your own control character. There's no out-of-band character that means "end of this input, but not that of the file". Andrei
Mar 26 2012
parent reply "Tyro[17]" <nospam home.com> writes:
On Monday, 26 March 2012 at 14:41:41 UTC, Andrei Alexandrescu 
wrote:
 On 3/26/12 5:55 AM, Tyro[17] wrote:
 You can achieve the same with:

 readf(" %s\n", &s2);

 My goal however, is not to read one line of information. 
 Rather, it is to
 read multiple lines of information from standard input. I get 
 close to
 being able to do so if i don't including "\n" as a part of my 
 format string
 or if I changing your suggestion to

 while (!stdin.eol()) {
 s2 = chomp(readln());
 }

 but again I run into the predicament was before, a need to 
 close the
 the stream with Ctrl-D/Ctrl-Z.
I made the decision for the current behavior while implementing readf. Basically I tried to avoid what I think was a mistake of scanf, i.e. that of stopping string reading at the first whitespace character, which is fairly useless.
Couldn't the state of stdin be checked upon entrance into readf and reopened if it is already closed? Wouldn't that accomplish the desired effect while avoiding the pitfalls of scanf?
 Over the years scanf was improved with %[...] which allows 
 reading strings with any characters in a set.

 Anyway, if I understand correctly, there's no way to achieve 
 what you want unless you read character-by-character and define 
 your own control character. There's no out-of-band character 
 that means "end of this input, but not that of the file".


 Andrei
Mar 26 2012
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 3/26/12 2:52 PM, Tyro[17] wrote:
 Couldn't the state of stdin be checked upon entrance into readf
 and reopened if it is already closed?
That won't work.
 Wouldn't that accomplish the desired effect while avoiding
 the pitfalls of scanf?
I don't think this is a pitfall. Essentially you don't have a definition of what constitutes a chunk of input. Once you get that define, you should be able to express it more or less easily. Andrei
Mar 26 2012
parent reply "Tyro[17]" <nospam home.com> writes:
On Tuesday, 27 March 2012 at 00:05:51 UTC, Andrei Alexandrescu 
wrote:
 On 3/26/12 2:52 PM, Tyro[17] wrote:
 Couldn't the state of stdin be checked upon entrance into readf
 and reopened if it is already closed?
That won't work.
But this does: import std.stdio, std.array; extern(C) // As defined for MAC OS X Lion { immutable TCSANOW = 0; immutable NCCS = 20; immutable VEOF = 0; /* ICANON */ int tcgetattr(int fd, termios *termios_p); int tcsetattr(int fd, int actions, termios *termios_p); alias ulong tcflag_t; alias ubyte cc_t; alias ulong speed_t; struct termios { tcflag_t c_iflag; /* input flags */ tcflag_t c_oflag; /* output flags */ tcflag_t c_cflag; /* control flags */ tcflag_t c_lflag; /* local flags */ cc_t c_cc[NCCS]; /* control chars */ speed_t c_ispeed; /* input speed */ speed_t c_ospeed; /* output speed */ } } void main(string[] args) { termios oldT; tcgetattr(0, &oldT); auto newT = oldT; newT.c_cc[VEOF] = 3; // temporary reassignment of EOF indicator. tcsetattr(0,TCSANOW,&newT); string s1; writeln("Enter Ctrl-D terminated string (multiline ok):"); readf(" %s\x04", &s1); tcsetattr(0,TCSANOW,&oldT); auto arr = s1.split(); writeln(arr); int data; readf(" %s", &data); writeln(i); } Could that technique be used to implement readf for stdin?
 Wouldn't that accomplish the desired effect while avoiding
 the pitfalls of scanf?
I don't think this is a pitfall. Essentially you don't have a definition of what constitutes a chunk of input. Once you get that define, you should be able to express it more or less easily.
I'm of the opinion that Ctrl-D defines the boundary of that chunk of input. We simply have to prevent it from closing the stream when working with stdin.
 Andrei
Mar 27 2012
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 3/27/12 6:54 AM, Tyro[17] wrote:
 On Tuesday, 27 March 2012 at 00:05:51 UTC, Andrei Alexandrescu wrote:
 On 3/26/12 2:52 PM, Tyro[17] wrote:
 Couldn't the state of stdin be checked upon entrance into readf
 and reopened if it is already closed?
That won't work.
But this does:
[snip] Very interesting! But then what if people press Ctrl-C? That would end the input instead of ending the program.
 Could that technique be used to implement readf for stdin?
I don't think we should pursue this path.
 Wouldn't that accomplish the desired effect while avoiding
 the pitfalls of scanf?
I don't think this is a pitfall. Essentially you don't have a definition of what constitutes a chunk of input. Once you get that define, you should be able to express it more or less easily.
I'm of the opinion that Ctrl-D defines the boundary of that chunk of input. We simply have to prevent it from closing the stream when working with stdin.
You're in a sparse minority at best. Every Unix application out there uses Ctrl-D for end-of-console-input, and your users would be surprised by your exotic use of it. Why not pick any other character for end of chunk - double newline, Ctrl-S, pretty much anything but Ctrl-D? It's a waste of your time to fight a long-established standard. Andrei
Mar 27 2012
next sibling parent "Tyro[17]" <nospam home.com> writes:
On Tuesday, 27 March 2012 at 15:14:07 UTC, Andrei Alexandrescu 
wrote:
 On 3/27/12 6:54 AM, Tyro[17] wrote:
 On Tuesday, 27 March 2012 at 00:05:51 UTC, Andrei Alexandrescu 
 wrote:
 On 3/26/12 2:52 PM, Tyro[17] wrote:
 Couldn't the state of stdin be checked upon entrance into 
 readf
 and reopened if it is already closed?
That won't work.
But this does:
[snip] Very interesting! But then what if people press Ctrl-C? That would end the input instead of ending the program.
 Could that technique be used to implement readf for stdin?
I don't think we should pursue this path.
 Wouldn't that accomplish the desired effect while avoiding
 the pitfalls of scanf?
I don't think this is a pitfall. Essentially you don't have a definition of what constitutes a chunk of input. Once you get that define, you should be able to express it more or less easily.
I'm of the opinion that Ctrl-D defines the boundary of that chunk of input. We simply have to prevent it from closing the stream when working with stdin.
You're in a sparse minority at best. Every Unix application out there uses Ctrl-D for end-of-console-input, and your users would be surprised by your exotic use of it.
Point taken.
 Why not pick any other character for end of chunk - double 
 newline, Ctrl-S, pretty much anything but Ctrl-D? It's a waste 
 of your time to fight a long-established standard.
Thanks for the clarification. That's me just not knowing. I've settled on Ctrl-X (\x018) because i have access to it without doing anything special as opposed to Ctrl-S and no operating system (as far as I know) uses it as a Command line shortcut. Thanks for keeping the conversation going so I could find a solution. Now, is it too much it the standard terminator for string input from stdin?
 Andrei
Andrew
Mar 27 2012
prev sibling parent reply "Matt Peterson" <ricochet1k gmail.com> writes:
On Tuesday, 27 March 2012 at 15:14:07 UTC, Andrei Alexandrescu
wrote:
 On 3/27/12 6:54 AM, Tyro[17] wrote:
 On Tuesday, 27 March 2012 at 00:05:51 UTC, Andrei Alexandrescu 
 wrote:
 On 3/26/12 2:52 PM, Tyro[17] wrote:
 Couldn't the state of stdin be checked upon entrance into 
 readf
 and reopened if it is already closed?
That won't work.
But this does:
[snip] Very interesting! But then what if people press Ctrl-C? That would end the input instead of ending the program.
 Could that technique be used to implement readf for stdin?
I don't think we should pursue this path.
 Wouldn't that accomplish the desired effect while avoiding
 the pitfalls of scanf?
I don't think this is a pitfall. Essentially you don't have a definition of what constitutes a chunk of input. Once you get that define, you should be able to express it more or less easily.
I'm of the opinion that Ctrl-D defines the boundary of that chunk of input. We simply have to prevent it from closing the stream when working with stdin.
You're in a sparse minority at best. Every Unix application out there uses Ctrl-D for end-of-console-input, and your users would be surprised by your exotic use of it. Why not pick any other character for end of chunk - double newline, Ctrl-S, pretty much anything but Ctrl-D? It's a waste of your time to fight a long-established standard. Andrei
GDB handles Ctrl-D differently. It doesn't close the input on the first one, it waits for the second one and then exits. After the first one it acts like you typed 'quit', which asks you if you really want to quit when there's a program still running.
Mar 27 2012
next sibling parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Tue, Mar 27, 2012 at 08:56:56PM +0200, Matt Peterson wrote:
 On Tuesday, 27 March 2012 at 15:14:07 UTC, Andrei Alexandrescu
 wrote:
[...]
You're in a sparse minority at best. Every Unix application out there
uses Ctrl-D for end-of-console-input, and your users would be
surprised by your exotic use of it.

Why not pick any other character for end of chunk - double newline,
Ctrl-S, pretty much anything but Ctrl-D? It's a waste of your time to
fight a long-established standard.
[...]
 
 GDB handles Ctrl-D differently. It doesn't close the input on the
 first one, it waits for the second one and then exits. After the first
 one it acts like you typed 'quit', which asks you if you really want
 to quit when there's a program still running.
That's because gdb uses libreadline (or something along those lines) with cbreak, so it can intercept control characters without them getting interpreted by the terminal. This requires manual control of terminal functions, which is something outside the scope of readf(). (You'd be better off writing your own terminal handling from scratch, if that's what you want.) T -- This is a tpyo.
Mar 27 2012
parent "Matt Peterson" <ricochet1k gmail.com> writes:
On Tuesday, 27 March 2012 at 19:05:19 UTC, H. S. Teoh wrote:
 On Tue, Mar 27, 2012 at 08:56:56PM +0200, Matt Peterson wrote:
 On Tuesday, 27 March 2012 at 15:14:07 UTC, Andrei Alexandrescu
 wrote:
[...]
You're in a sparse minority at best. Every Unix application 
out there
uses Ctrl-D for end-of-console-input, and your users would be
surprised by your exotic use of it.

Why not pick any other character for end of chunk - double 
newline,
Ctrl-S, pretty much anything but Ctrl-D? It's a waste of your 
time to
fight a long-established standard.
[...]
 
 GDB handles Ctrl-D differently. It doesn't close the input on 
 the
 first one, it waits for the second one and then exits. After 
 the first
 one it acts like you typed 'quit', which asks you if you 
 really want
 to quit when there's a program still running.
That's because gdb uses libreadline (or something along those lines) with cbreak, so it can intercept control characters without them getting interpreted by the terminal. This requires manual control of terminal functions, which is something outside the scope of readf(). (You'd be better off writing your own terminal handling from scratch, if that's what you want.) T
Ah, nice to know. Thanks.
Mar 27 2012
prev sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 3/27/12 12:56 PM, Matt Peterson wrote:
 GDB handles Ctrl-D differently. It doesn't close the input on the
 first one, it waits for the second one and then exits. After the
 first one it acts like you typed 'quit', which asks you if you
 really want to quit when there's a program still running.
A variety of other programs handle Ctrl-D differently (emacs, vi, etc). They aren't simple console input programs. Andrei
Mar 27 2012
prev sibling parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 03/26/2012 04:55 AM, Tyro[17] wrote:

 void main(string[] args)
 {
 string s1;
 double d;
 string s2;

 writeln("Enter a   terminated string (multiline ok):");
 readf(" %s ", &s1);
 auto arr = s1.split();

 if (!stdin.eof()) {
Ah! That's one of the problems. stdin has no idea whether there are more characters available. eof() being true is not dependable unless an attempt to read a character is made and failed. This is the case in C and C++ as well.
 writeln("The stream is not empty.");
 } else {
 writeln("The stream is empty.");
 }
 writeln("Enter another string (terminated with
cntrl-d|ctrl-z):"); I am not sure about the cntrl-d|ctrl-z part though. Since it terminates the input, the program should not be able to read any more characters.
I would like to repeat: ending the stream is not a solution because you want to read more data.
 readf(" %s", &s2); // No matter how many read attempts
That's the actual problem, and ironically is already known to you. :) Use a \n at the end of that format string.
 I advise reading string by readln(). You can call chomp() to get rid
 of whitespace around it:

 while (s2.length == 0) {
 s2 = chomp(readln());
 }
You can achieve the same with: readf(" %s\n", &s2);
Thank you. However, that method does not remove trailing whitespace.
 My goal however, is not to read one line of information. Rather, it is to
 read multiple lines of information from standard input. I get close to
 being able to do so if i don't including "\n" as a part of my format 
string
 or if I changing your suggestion to

 while (!stdin.eol()) {
 s2 = chomp(readln());
 }

 but again I run into the predicament was before, a need to close the
 the stream with Ctrl-D/Ctrl-Z.
If I understand you correctly, the following program works for me: import std.stdio; import std.string; void main(string[] args) { string s1; double d; string s2; writeln("Enter a terminated string (multiline ok):"); readf(" %s ", &s1); auto arr = s1.split(); writeln("Enter a line of string:"); readf(" %s\n", &s2); writeln("Enter a decimal value:"); readf(" %s", &d); writeln("d = ", d); writeln("arr = ", arr); writeln("s = ", s2); } Ali
Mar 26 2012
parent reply "Tyro[17]" <nospam home.com> writes:
On Monday, 26 March 2012 at 17:34:37 UTC, Ali Çehreli wrote:
 On 03/26/2012 04:55 AM, Tyro[17] wrote:

 readf(" %s", &s2); // No matter how many read attempts
That's the actual problem, and ironically is already known to you. :) Use a \n at the end of that format string.
Thanks. I'le use chomp(readln()) in the future.
 I advise reading string by readln(). You can call chomp() to
get rid
 of whitespace around it:

 while (s2.length == 0) {
 s2 = chomp(readln());
 }
You can achieve the same with: readf(" %s\n", &s2);
Thank you. However, that method does not remove trailing whitespace.
 My goal however, is not to read one line of information.
Rather, it is to
 read multiple lines of information from standard input. I get
close to
 being able to do so if i don't including "\n" as a part of my
format string
 or if I changing your suggestion to

 while (!stdin.eol()) {
 s2 = chomp(readln());
 }

 but again I run into the predicament was before, a need to
close the
 the stream with Ctrl-D/Ctrl-Z.
If I understand you correctly, the following program works for me: import std.stdio; import std.string; void main(string[] args) { string s1; double d; string s2;
Actually the problem is right here:
     writeln("Enter a   terminated string (multiline ok):");
     readf(" %s ", &s1);
     auto arr = s1.split();
I don't want to provide an explicit terminator, but instead rely on Ctrl-D/Ctrl-Z to do the job while being able to continue processing read request. As explained by Andrei, this is not possible. But in my mind if the stdin stream can be opened once, it can be opened again. What is the negative effect of testing if it is closed and reopening it on entering readf? Especially since there is a unique implementation of readf to deal with input from stdin. What is wrong with implementing reopen() in File for specific use with stdin and then implementing readf like this: uint readf(A...)(in char[] format, A args) { if(stdin.eof) stdin.reopen(); return stdin.readf(format, args); } Andrew
Mar 26 2012
parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 03/26/2012 02:12 PM, Tyro[17] wrote:

 I don't want to provide an explicit terminator, but instead
 rely on Ctrl-D/Ctrl-Z to do the job while being able to
 continue processing read request. As explained by Andrei,
 this is not possible. But in my mind if the stdin stream
 can be opened once, it can be opened again. What is the
 negative effect of testing if it is closed and reopening it
 on entering readf? Especially since there is a unique
 implementation of readf to deal with input from stdin.

 What is wrong with implementing reopen() in File for
 specific use with stdin and then implementing readf
 like this:

 uint readf(A...)(in char[] format, A args)
 {
 if(stdin.eof) stdin.reopen();
 return stdin.readf(format, args);
 }

 Andrew
That doesn't fit the way standard input and output streams work. These streams are bound to the application from the environment that has started them. The program itself does not have a way of manipulating how these streams are ended or connected. Imagine that your program's stdin if piped from the output of another process: other | yours Once 'other' finishes with its output, that's the end of the input of 'yours'. 'yours' cannot communicate to the environment that it would like to continue reading more. What you are asking for could be achieved only if both the environment and the program agreed that this would be the case. Maybe I am missing something but that has been standard on many environments. Ali
Mar 26 2012
parent "Tyro[17]" <nospam home.com> writes:
On Monday, 26 March 2012 at 21:20:00 UTC, Ali Çehreli wrote:
 On 03/26/2012 02:12 PM, Tyro[17] wrote:

 I don't want to provide an explicit terminator, but instead
 rely on Ctrl-D/Ctrl-Z to do the job while being able to
 continue processing read request. As explained by Andrei,
 this is not possible. But in my mind if the stdin stream
 can be opened once, it can be opened again. What is the
 negative effect of testing if it is closed and reopening it
 on entering readf? Especially since there is a unique
 implementation of readf to deal with input from stdin.

 What is wrong with implementing reopen() in File for
 specific use with stdin and then implementing readf
 like this:

 uint readf(A...)(in char[] format, A args)
 {
 if(stdin.eof) stdin.reopen();
 return stdin.readf(format, args);
 }

 Andrew
That doesn't fit the way standard input and output streams work. These streams are bound to the application from the environment that has started them. The program itself does not have a way of manipulating how these streams are ended or connected. Imagine that your program's stdin if piped from the output of another process: other | yours Once 'other' finishes with its output, that's the end of the input of 'yours'. 'yours' cannot communicate to the environment that it would like to continue reading more.
Thanks for that explanation. I am only now understanding the problem.
 What you are asking for could be achieved only if both the 
 environment and the program agreed that this would be the case.
Not really, we can "borrow" Ctrl-D form the OS until our input is complete. Please see response to Andrei.
 Maybe I am missing something but that has been standard on many 
 environments.

 Ali
Mar 27 2012
prev sibling parent "Tyro[17]" <nospam home.com> writes:
First of all thank your very much for your assistance.

On Sunday, 25 March 2012 at 15:04:30 UTC, Ali Çehreli wrote:
 On 03/25/2012 06:00 AM, Tyro[17] wrote:
 I am trying to figure out the cause of my problem in the
following post:
 
http://forum.dlang.org/thread/qfbugjkrerfboqhvjttw forum.dlang.org Sorry that I missed your question there. :(
 and encountered something peculiar about reading strings.
Whenever a
 distinct terminator is indicated in the input format (ex. "
%s ",
 being the terminator), readf() leaves the terminator on the
input buffer
 after reading the data. If no terminator is specified the
only way to
 indicate end of input is to use ctrl-d (ctrl-z on windows),
however that
 causes the eof indicator to be set to true and the stream is
marked as
 empty for all future attempts to access stdin.

 void main(string[] args)
 {
 string s1;
 double d;
 string s2;

 writeln("Enter a   terminated string (multiline ok):");
 readf(" %s ", &s1);
 auto arr = s1.split();

 if (!stdin.eof()) {
 writeln("The stream is not empty.");
 } else {
 writeln("The stream is empty.");
 }
 writeln("Enter another string (terminated with
cntrl-d|ctrl-z):"); I am not sure about the cntrl-d|ctrl-z part though. Since it terminates the input, the program should not be able to read any more characters.
 readf(" %s", &s2); // No matter how many read attempts
I advise reading string by readln(). You can call chomp() to get rid of whitespace around it: while (s2.length == 0) { s2 = chomp(readln()); }
You can achieve the same with: readf(" %s\n", &s2); My goal however, is not to read one line of information. Rather, it is to read multiple lines of information from standard input. I get close to being able to do so if i don't including "\n" as a part of my format string or if I changing your suggestion to while (!stdin.eol()) { s2 = chomp(readln()); } but again I run into the predicament was before, a need to close the the stream with Ctrl-D/Ctrl-Z. Andrew
Mar 26 2012