Thread overview
Smartest way to read a number?
Nov 10, 2011
Fabian
Nov 10, 2011
Tobias Brandt
Nov 10, 2011
Fabian
Nov 10, 2011
Kai Meyer
Nov 10, 2011
Tobias Brandt
Nov 10, 2011
Andrej Mitrovic
Nov 10, 2011
Fabian
Nov 10, 2011
Jonathan M Davis
Nov 11, 2011
Fabian
November 10, 2011
Hey guys.

I just want to write a few console applications. Usualy I have to read numbers to calculate some values. But what's the smartest way to read and convert the input?

I've coded these lines:

import std.stdio, std.string, std.conv;

T readNumber(T)()
{
	string buffer;
	stdin.readln(buffer);
	buffer = chomp(buffer);

	if(isNumeric(buffer))
	{
		return parse!T(buffer);
	}
	else
	{
		throw new Exception("Input is not a number!");
	}
}

void main()
{
	try
	{
		int n = readNumber!int();
		writeln(n);

		float f = readNumber!float();
		writeln(f);
	}
	catch(Exception e)
	{
		writeln(e.msg);
	}
}

Can I use that function or is there a cleaner way to do this job?

Greetings
Fabian
November 10, 2011
import std.stdio;

T readNumber(T)()
{
    T result;
    stdin.readf("%s", &result);
    return result;
}

Throws a ConvException if the input string wasn't in the right format.

On 10 November 2011 22:48, Fabian <talk2fab@online.de> wrote:
> Hey guys.
>
> I just want to write a few console applications. Usualy I have to read numbers to calculate some values. But what's the smartest way to read and convert the input?
>
> I've coded these lines:
>
> import std.stdio, std.string, std.conv;
>
> T readNumber(T)()
> {
>        string buffer;
>        stdin.readln(buffer);
>        buffer = chomp(buffer);
>
>        if(isNumeric(buffer))
>        {
>                return parse!T(buffer);
>        }
>        else
>        {
>                throw new Exception("Input is not a number!");
>        }
> }
>
> void main()
> {
>        try
>        {
>                int n = readNumber!int();
>                writeln(n);
>
>                float f = readNumber!float();
>                writeln(f);
>        }
>        catch(Exception e)
>        {
>                writeln(e.msg);
>        }
> }
>
> Can I use that function or is there a cleaner way to do this job?
>
> Greetings
> Fabian
>
November 10, 2011
This: https://github.com/he-the-great/JPDLibs/tree/cmdln/cmdln

The HTML docs explain how to use it. Not mine, but I think this would be a sweet addition to Phobos imo.
November 10, 2011
Thanks a lot. That's exactly what I was searching for.
November 10, 2011
Andrej Mitrovic wrote:

> This: https://github.com/he-the-great/JPDLibs/tree/cmdln/cmdln
>
> The HTML docs explain how to use it. Not mine, but I think this would be a sweet addition to Phobos imo.

Thank you. :)

November 10, 2011
On Thursday, November 10, 2011 13:48 Fabian wrote:
> Hey guys.
> 
> I just want to write a few console applications. Usualy I have to read numbers to calculate some values. But what's the smartest way to read and convert the input?
> 
> I've coded these lines:
> 
> import std.stdio, std.string, std.conv;
> 
> T readNumber(T)()
> {
> string buffer;
> stdin.readln(buffer);
> buffer = chomp(buffer);
> 
> if(isNumeric(buffer))
> {
> return parse!T(buffer);
> }
> else
> {
> throw new Exception("Input is not a number!");
> }
> }
> 
> void main()
> {
> try
> {
> int n = readNumber!int();
> writeln(n);
> 
> float f = readNumber!float();
> writeln(f);
> }
> catch(Exception e)
> {
> writeln(e.msg);
> }
> }
> 
> Can I use that function or is there a cleaner way to do this job?

parse already throws an exception if it can't parse anything. There's no need to call isNumeric and throw an exception yourself. However, if you want to guarantee that the whole string is a valid number instead of just the beginning (parse parses as much as it can, leaving what it can't in the string, and throwing if it couldn't parse anything), then use std.conv.to. It requires that the string be _exactly_ a number (no whitespace or extraneous characters). It also doesn't consume the string at all (since it's converting all or nothing).

- Jonathan M Davis
November 10, 2011
I don't get the exception on Linux after a new line, I have to wait until EOF, which is typically the end of the program if reading from STDIN. Not very useful.

import std.stdio;

T readNumber(T)()
{
    T result;
    stdin.readf("%s", &result);
    return result;
}
void main()
{
    try
    {
        int n = readNumber!int();
        writeln(n);

        float f = readNumber!float();;
        writeln(f);
    }
    catch(Exception e)
    {
        writeln(e.msg);
    }
}


Sample execution:
-----------------------
[kai.meyer@kai-rhel6 D]$ dmd -run readnum.d
a
1
1.2
** I hit Ctrl-D here, so this line isn't part of the output ***
std.conv(1157): Can't convert value `a
1
1.2
' of type LockingTextReader to type int
-----------------------

Or if you prefer with out my terminal echoing my input:
-----------------------
[kai.meyer@kai-rhel6 D]$ echo -e 'a\n1\n1.2\n' | dmd -run readnum.d
std.conv(1157): Can't convert value `a
1
1.2

' of type LockingTextReader to type int
----------------------


On 11/10/2011 02:58 PM, Tobias Brandt wrote:
> import std.stdio;
>
> T readNumber(T)()
> {
>      T result;
>      stdin.readf("%s",&result);
>      return result;
> }
>
> Throws a ConvException if the input string wasn't in the right format.
>
> On 10 November 2011 22:48, Fabian<talk2fab@online.de>  wrote:
>> Hey guys.
>>
>> I just want to write a few console applications. Usualy I have to read numbers
>> to calculate some values. But what's the smartest way to read and convert the
>> input?
>>
>> I've coded these lines:
>>
>> import std.stdio, std.string, std.conv;
>>
>> T readNumber(T)()
>> {
>>         string buffer;
>>         stdin.readln(buffer);
>>         buffer = chomp(buffer);
>>
>>         if(isNumeric(buffer))
>>         {
>>                 return parse!T(buffer);
>>         }
>>         else
>>         {
>>                 throw new Exception("Input is not a number!");
>>         }
>> }
>>
>> void main()
>> {
>>         try
>>         {
>>                 int n = readNumber!int();
>>                 writeln(n);
>>
>>                 float f = readNumber!float();
>>                 writeln(f);
>>         }
>>         catch(Exception e)
>>         {
>>                 writeln(e.msg);
>>         }
>> }
>>
>> Can I use that function or is there a cleaner way to do this job?
>>
>> Greetings
>> Fabian
>>

November 10, 2011
Yes, you are right. You can make it work by changing to line buffering:

stdin.setvbuf(null, _IOLBF);

But at that point, another solution (like using std.conv.to) is
probably the better choice.

On 10 November 2011 23:40, Kai Meyer <kai@unixlords.com> wrote:
> I don't get the exception on Linux after a new line, I have to wait until EOF, which is typically the end of the program if reading from STDIN. Not very useful.
>
> import std.stdio;
>
> T readNumber(T)()
> {
>    T result;
>    stdin.readf("%s", &result);
>    return result;
> }
> void main()
> {
>    try
>    {
>        int n = readNumber!int();
>        writeln(n);
>
>        float f = readNumber!float();;
>        writeln(f);
>    }
>    catch(Exception e)
>    {
>        writeln(e.msg);
>    }
> }
>
>
> Sample execution:
> -----------------------
> [kai.meyer@kai-rhel6 D]$ dmd -run readnum.d
> a
> 1
> 1.2
> ** I hit Ctrl-D here, so this line isn't part of the output ***
> std.conv(1157): Can't convert value `a
> 1
> 1.2
> ' of type LockingTextReader to type int
> -----------------------
>
> Or if you prefer with out my terminal echoing my input:
> -----------------------
> [kai.meyer@kai-rhel6 D]$ echo -e 'a\n1\n1.2\n' | dmd -run readnum.d
> std.conv(1157): Can't convert value `a
> 1
> 1.2
>
> ' of type LockingTextReader to type int
> ----------------------
>
>
> On 11/10/2011 02:58 PM, Tobias Brandt wrote:
>>
>> import std.stdio;
>>
>> T readNumber(T)()
>> {
>>     T result;
>>     stdin.readf("%s",&result);
>>     return result;
>> }
>>
>> Throws a ConvException if the input string wasn't in the right format.
>>
>> On 10 November 2011 22:48, Fabian<talk2fab@online.de>  wrote:
>>>
>>> Hey guys.
>>>
>>> I just want to write a few console applications. Usualy I have to read
>>> numbers
>>> to calculate some values. But what's the smartest way to read and convert
>>> the
>>> input?
>>>
>>> I've coded these lines:
>>>
>>> import std.stdio, std.string, std.conv;
>>>
>>> T readNumber(T)()
>>> {
>>>        string buffer;
>>>        stdin.readln(buffer);
>>>        buffer = chomp(buffer);
>>>
>>>        if(isNumeric(buffer))
>>>        {
>>>                return parse!T(buffer);
>>>        }
>>>        else
>>>        {
>>>                throw new Exception("Input is not a number!");
>>>        }
>>> }
>>>
>>> void main()
>>> {
>>>        try
>>>        {
>>>                int n = readNumber!int();
>>>                writeln(n);
>>>
>>>                float f = readNumber!float();
>>>                writeln(f);
>>>        }
>>>        catch(Exception e)
>>>        {
>>>                writeln(e.msg);
>>>        }
>>> }
>>>
>>> Can I use that function or is there a cleaner way to do this job?
>>>
>>> Greetings
>>> Fabian
>>>
>
>
November 11, 2011
Ok - Good to know. Thank you ;)