Distinguish float and integer types from string

2019-03-09 Thread Jacob Shtokolov via Digitalmars-d-learn

Hi,

Recently, I was trying to solve some funny coding challenges 
(https://www.techgig.com).
The questions were really simple, but I found it interesting 
because the website allows to use D.


One of the task was to take a string from STDIN and detect its 
type.
There were a few options: Float, Integer, string and "something 
else" (which, I think, doesn't have any sense under the scope of 
the task).


Anyway, I was struggling to find a built-in function to 
distinguish float and integer types from a string.


I came to the following solution:

```
import std.stdio;
import std.range;
import std.conv;
import std.string;
import std.format;

immutable msg = "This input is of type %s";

void main()
{
string type;
auto data = stdin.byLine.takeOne.front;

if (data.isNumeric) {
type = data.indexOf(".") >= 0 ? "Float" : "Integer";
}
else {
type = "string";
}

writeln(msg.format(type));
}
```

But I think that's ugly. The thing is that in PHP, for example, I 
would do that like this:


```
if (is_integer($data)) {
//...do smth
}
else if (is_float($data)) {
//...do smth
}
else {
//...do smth
}
```

I tried to use std.conv.to and std.conv.parse, but found that 
they can't really do this. When I call `data.to!int`, the value 
of "123.45" will be converted to int!


Is there any built-in way to detect these types?

Thanks!


Re: Distinguish float and integer types from string

2019-03-09 Thread Adam D. Ruppe via Digitalmars-d-learn

On Saturday, 9 March 2019 at 18:11:09 UTC, Jacob Shtokolov wrote:w
One of the task was to take a string from STDIN and detect its 
type.


The way I'd do this is a very simple loop:

enum Type { String, Float, Int }
if(str.length && str[0] == '-') {
   str = str[1 .. $];
}
Type type = str.length ? Type.Int : Type.String;
foreach(ch; str) {
   if(ch == '.' && type = Type.Int)
type = Type.Float;
   else if(ch < '0' || ch > '9') {
   type = Type.String;
   break;
   }
}

And if you need to support other details, add them on top of 
that. For example, exponents on floats may be a second clause 
like how I put negative ahead.


You may also choose to use a regular expression though I think 
that is overkill for this.



if (data.isNumeric) {


There are several caveats on that isNumeric function: it sees if 
something looks like a D numeric literal, which might not be what 
you want. For example, isNumeric("1UL") passes because the U and 
L suffixes are allowed in D literals...



But I think that's ugly. The thing is that in PHP, for example, 
I would do that like this:


```
if (is_integer($data)) {


Simiarly, this also will not od what you want. is_integer("1") 
will return false. "1" is of type string. Those functions check 
the dynamic type tag, not the contents of a string.


(actually, you arguably can just always return "string" cuz stdin 
is basically just a string or a binary stream anyway :P )


PHP's is_numeric returns true for both integer and floating point 
things, similarly to D's...


Re: Distinguish float and integer types from string

2019-03-10 Thread spir via Digitalmars-d-learn

On 09/03/2019 19:11, Jacob Shtokolov via Digitalmars-d-learn wrote:

The thing is that in PHP, for example, I would do


The thing is php needs to be able to "lexify" raw input data at runtime, while 
in D this is done at compile-time. The ompiler has the lexer to do that.


But I agree that, for user input, it would be cool to have such a feature 
available. However, this would quickly become complex because of (the reciprocal 
of) localisation, or even personalisation. Eg I like to write decimals like:

-1'234'457,098

diniz



Re: Distinguish float and integer types from string

2019-03-11 Thread Soulsbane via Digitalmars-d-learn

On Saturday, 9 March 2019 at 18:11:09 UTC, Jacob Shtokolov wrote:

Hi,

Recently, I was trying to solve some funny coding challenges 
(https://www.techgig.com).
The questions were really simple, but I found it interesting 
because the website allows to use D.


One of the task was to take a string from STDIN and detect its 
type.
There were a few options: Float, Integer, string and "something 
else" (which, I think, doesn't have any sense under the scope 
of the task).


Anyway, I was struggling to find a built-in function to 
distinguish float and integer types from a string.


I came to the following solution:

```
import std.stdio;
import std.range;
import std.conv;
import std.string;
import std.format;

immutable msg = "This input is of type %s";

void main()
{
string type;
auto data = stdin.byLine.takeOne.front;

if (data.isNumeric) {
type = data.indexOf(".") >= 0 ? "Float" : "Integer";
}
else {
type = "string";
}

writeln(msg.format(type));
}
```

But I think that's ugly. The thing is that in PHP, for example, 
I would do that like this:


```
if (is_integer($data)) {
//...do smth
}
else if (is_float($data)) {
//...do smth
}
else {
//...do smth
}
```

I tried to use std.conv.to and std.conv.parse, but found that 
they can't really do this. When I call `data.to!int`, the value 
of "123.45" will be converted to int!


Is there any built-in way to detect these types?

Thanks!


Unless I'm missing something perhaps two functions like this:

bool isInteger(string value) pure nothrow @safe
{
import std.string : isNumeric;
	return (isNumeric(value) && value.count(".") == 0) ? true : 
false;

}

bool isDecimal(string value) pure nothrow @safe
{
import std.string : isNumeric;
	return (isNumeric(value) && value.count(".") == 1) ? true : 
false;

}




Re: Distinguish float and integer types from string

2019-03-11 Thread Johann Lermer via Digitalmars-d-learn

On Saturday, 9 March 2019 at 18:11:09 UTC, Jacob Shtokolov wrote:
I tried to use std.conv.to and std.conv.parse, but found that 
they can't really do this. When I call `data.to!int`, the value 
of "123.45" will be converted to int!


Are you sure? This here works for me:

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

void main ()
{
auto s = readln.strip;

try
{
int i = to!int (s);
writefln ("string is an int: %s", i);
}
catch(Exception e)
{
try
{
float f = to!float(s);
writefln ("string is a float: %s", f);
}
catch(Exception e)
{
writefln ("string is an neither an int nor a float: 
%s", s);

}
}
}


Re: Distinguish float and integer types from string

2019-03-11 Thread XavierAP via Digitalmars-d-learn

On Saturday, 9 March 2019 at 18:11:09 UTC, Jacob Shtokolov wrote:


One of the task was to take a string from STDIN and detect its 
type.
There were a few options: Float, Integer, string and "something 
else" (which, I think, doesn't have any sense under the scope 
of the task).


Another std-based solution I came up with:

bool isInteger(string str)
{
if(str.isNumeric)
{
try { return str.to!long == str.to!real; }
catch(ConvException) { return false; }
}
else return false;
}

I tried to use std.conv.to and std.conv.parse, but found that 
they can't really do this. When I call `data.to!int`, the value 
of "123.45" will be converted to int!


What compiler version are you using? I on the other hand was 
surprised that I needed the try-catch above, after having already 
checked isNumeric. The documentation claims that the conversion 
to int or long would truncate, but my compiler (v2.084.0) throws 
instead.


Re: Distinguish float and integer types from string

2019-03-11 Thread XavierAP via Digitalmars-d-learn

On Monday, 11 March 2019 at 15:03:39 UTC, XavierAP wrote:


What compiler version are you using? I on the other hand was 
surprised that I needed the try-catch above, after having 
already checked isNumeric. The documentation claims that the 
conversion to int or long would truncate, but my compiler 
(v2.084.0) throws instead.


Of course now I realize that using try-catch I no longer need to 
check isNumeric... My design didn't use try-catch but I had to 
add it because std.conv:to behaves differently from the 
documentation:


https://dlang.org/phobos/std_conv.html#to

Not sure if I need to update my DMD, or it's the documentation 
that's out of date, or something else is wrong.