www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Smartest way to read a number?

reply Fabian <talk2fab online.de> writes:
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
Nov 10 2011
next sibling parent reply Tobias Brandt <tob.brandt googlemail.com> writes:
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 nu=
mbers
 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)()
 {
 =A0 =A0 =A0 =A0string buffer;
 =A0 =A0 =A0 =A0stdin.readln(buffer);
 =A0 =A0 =A0 =A0buffer =3D chomp(buffer);

 =A0 =A0 =A0 =A0if(isNumeric(buffer))
 =A0 =A0 =A0 =A0{
 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0return parse!T(buffer);
 =A0 =A0 =A0 =A0}
 =A0 =A0 =A0 =A0else
 =A0 =A0 =A0 =A0{
 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0throw new Exception("Input is not a number=
!");
 =A0 =A0 =A0 =A0}
 }

 void main()
 {
 =A0 =A0 =A0 =A0try
 =A0 =A0 =A0 =A0{
 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0int n =3D readNumber!int();
 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0writeln(n);

 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0float f =3D readNumber!float();
 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0writeln(f);
 =A0 =A0 =A0 =A0}
 =A0 =A0 =A0 =A0catch(Exception e)
 =A0 =A0 =A0 =A0{
 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0writeln(e.msg);
 =A0 =A0 =A0 =A0}
 }

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

 Greetings
 Fabian
Nov 10 2011
next sibling parent Fabian <talk2fab online.de> writes:
Thanks a lot. That's exactly what I was searching for.
Nov 10 2011
prev sibling parent reply Kai Meyer <kai unixlords.com> writes:
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
Nov 10 2011
parent Tobias Brandt <tob.brandt googlemail.com> writes:
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)()
 {
 =A0 =A0T result;
 =A0 =A0stdin.readf("%s", &result);
 =A0 =A0return result;
 }
 void main()
 {
 =A0 =A0try
 =A0 =A0{
 =A0 =A0 =A0 =A0int n =3D readNumber!int();
 =A0 =A0 =A0 =A0writeln(n);

 =A0 =A0 =A0 =A0float f =3D readNumber!float();;
 =A0 =A0 =A0 =A0writeln(f);
 =A0 =A0}
 =A0 =A0catch(Exception e)
 =A0 =A0{
 =A0 =A0 =A0 =A0writeln(e.msg);
 =A0 =A0}
 }


 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)()
 {
 =A0 =A0 T result;
 =A0 =A0 stdin.readf("%s",&result);
 =A0 =A0 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> =A0wrote:
 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 conve=
rt
 the
 input?

 I've coded these lines:

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

 T readNumber(T)()
 {
 =A0 =A0 =A0 =A0string buffer;
 =A0 =A0 =A0 =A0stdin.readln(buffer);
 =A0 =A0 =A0 =A0buffer =3D chomp(buffer);

 =A0 =A0 =A0 =A0if(isNumeric(buffer))
 =A0 =A0 =A0 =A0{
 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0return parse!T(buffer);
 =A0 =A0 =A0 =A0}
 =A0 =A0 =A0 =A0else
 =A0 =A0 =A0 =A0{
 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0throw new Exception("Input is not a numb=
er!");
 =A0 =A0 =A0 =A0}
 }

 void main()
 {
 =A0 =A0 =A0 =A0try
 =A0 =A0 =A0 =A0{
 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0int n =3D readNumber!int();
 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0writeln(n);

 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0float f =3D readNumber!float();
 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0writeln(f);
 =A0 =A0 =A0 =A0}
 =A0 =A0 =A0 =A0catch(Exception e)
 =A0 =A0 =A0 =A0{
 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0writeln(e.msg);
 =A0 =A0 =A0 =A0}
 }

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

 Greetings
 Fabian
Nov 10 2011
prev sibling next sibling parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
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.
Nov 10 2011
parent Fabian <talk2fab online.de> writes:
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. :)
Nov 10 2011
prev sibling parent reply "Jonathan M Davis" <jmdavisProg gmx.com> writes:
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
Nov 10 2011
parent Fabian <talk2fab online.de> writes:
Ok - Good to know. Thank you ;)
Nov 10 2011