Thread overview | |||||||||
---|---|---|---|---|---|---|---|---|---|
|
March 09, 2019 Distinguish float and integer types from string | ||||
---|---|---|---|---|
| ||||
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! |
March 09, 2019 Re: Distinguish float and integer types from string | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jacob Shtokolov | 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... |
March 10, 2019 Re: Distinguish float and integer types from string | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jacob Shtokolov | 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
|
March 11, 2019 Re: Distinguish float and integer types from string | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jacob Shtokolov | 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;
}
|
March 11, 2019 Re: Distinguish float and integer types from string | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jacob Shtokolov | 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);
}
}
}
|
March 11, 2019 Re: Distinguish float and integer types from string | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jacob Shtokolov | 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. |
March 11, 2019 Re: Distinguish float and integer types from string | ||||
---|---|---|---|---|
| ||||
Posted in reply to XavierAP | 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. |
Copyright © 1999-2021 by the D Language Foundation