Reading data

Jimmy

Active member
3rd Party Module Dev
Tutorial Author
Joined
Jan 2, 2020
Messages
878
So my question was supposed to a simple one about how you would prefer to check wether a string contains a number or not.
But as I moved from macos to the Linux platform this question changed a bit. because I get a different behaviour here.

Int() with non-numbers on macOS will return NaN, while Linux will return 0.

So they handle this differently, is this expected or a bug?
Back to the question, how would you prefer dealing with checking that a string is indeed not a number but something else in Cerberus?

test.cxs
Code:
Import mojo.app
Function Main:Int()
    Local lines:String[] =LoadString("testdata.txt").Split("~n")
    For Local line:String = Eachin lines
        Local items:String[] = line.Split(",")
        For Local item:= Eachin items
            Print Int(item)  ' Will print "Nan" on macos and "0" on Linux
            Print item
        Next
    Next
    Return 0
End

testdata.txt
Code:
1,2,3,4,5,6,7,8
121,3453245,6564,3224234
987978,CerberusX,4356346
 
Last edited:

Jimmy

Active member
3rd Party Module Dev
Tutorial Author
Joined
Jan 2, 2020
Messages
878
It was my fault, HTML5 gives Nan, Desktop gives 0. On both platforms. I forgot I use different targets on them.
 

dawlane

Well-known member
CX Code Contributor
Joined
Jun 21, 2017
Messages
840
The simplest way is to parse the items for non numeric characters.
Of course you would have to capture negative numbers in the mix as well.
Code:
Import mojo.app
Function Main:Int()
    Local lines:String[] =LoadString("testdata.txt").Split("~n")
    For Local line:String = Eachin lines
        Local items:String[] = line.Split(",")
        For Local item:= Eachin items
            'Print Int(item)  ' Will print "Nan" on macos and "0" on Linux
            If IsNumber( item ) Print "Is number: "+Int(item) Else Print "Is string: "+item
        Next
    Next
    Return 0
End

Function IsNumber:Bool( str:String )
    For Local i:=Eachin str
        If Not (i>"0" And i<"9") Return False
    Next
    Return True
End
 

Jimmy

Active member
3rd Party Module Dev
Tutorial Author
Joined
Jan 2, 2020
Messages
878
That's nice but you have to handle every imaginable input manually then. I must think of how muchh this will explode.
There's no check for types or similiar?

The 0 my example output is an implicit boolean-conversion that is expressed numerically by Print right?
 

Jimmy

Active member
3rd Party Module Dev
Tutorial Author
Joined
Jan 2, 2020
Messages
878
The simplest stable logic I would need would be:
1) "-" is allowed to appear as first char, but only once.
2) "." is allowed to appear anywhere but only once, and if so then there needs to be least one number on either direct side.

I'm used to pattern-matching and type-checking but as I'm not to bothered about speed at this point I can imagine this will be more than okay.
 

Jimmy

Active member
3rd Party Module Dev
Tutorial Author
Joined
Jan 2, 2020
Messages
878
The first thought was to use the 0 and NaN somehow, together with the length of the string and just work out the kinks that it leaves me with.
 

dawlane

Well-known member
CX Code Contributor
Joined
Jun 21, 2017
Messages
840
The quick and dirty method would be to do
If Not(Int(item)) Print "Not number "+item Else Print "number "+Int(item)
But there is a catch: If the value starts with a number be it positive or negative and has Alpha characters as part of the string, then only the first number is evaluated. e.g. -3A5 would evaluate to -3 and not be treated as a string.
 
Last edited:

Jimmy

Active member
3rd Party Module Dev
Tutorial Author
Joined
Jan 2, 2020
Messages
878
Thanks, but what about this using Int()

* Getting a Nan.. we know for certain it is not a number.

* Getting a 0.. well it could still be a non-number so now need doublecheck...
as the data is perfectly clean and simple data, which saved my ass..
we could do this by stringchecking for a "0" and nothing else.

If there where stuff like 0.0 +0 -0 0.00 or intermingled letters then I would be screwed of course.
 

Jimmy

Active member
3rd Party Module Dev
Tutorial Author
Joined
Jan 2, 2020
Messages
878
Got it working! Thanks

This was a nice solution for simple data:
Code:
If Not(Int(item)) And item <>"0" Then Print "NaN " '  < works everywhere for clean data
 

Jimmy

Active member
3rd Party Module Dev
Tutorial Author
Joined
Jan 2, 2020
Messages
878
One more problem, I do have empty commas in the data, and they trigger as "NaN" now.
 

Jimmy

Active member
3rd Party Module Dev
Tutorial Author
Joined
Jan 2, 2020
Messages
878
Almost silvertaping now.. but it's stable so it's pefectable acceptable.
Code:
If item.Length <> 0 Then If Not(Int(item)) And item <>"0" Then Print "Not a number for sure you cannot fool me "
 

dawlane

Well-known member
CX Code Contributor
Joined
Jun 21, 2017
Messages
840
A better example of parsing a string for valid numbers.
Code:
Import mojo.app

Function Main:Int()
    Local lines:String[] =LoadString("testdata.txt").Split("~n")
    For Local line:String = Eachin lines
        Local items:String[] = line.Split(",")
        For Local item:= Eachin items
            If IsNumber( item )
                If item.Contains(".") Print "Is Float: "+Float(item) Else Print "Is Int: "+Int(item)
            Else
                Print "Is String: "+item
            End
        Next
    Next
    Return 0
End

Function IsNumber:Bool( str:String )
    Local skip:Bool, dec:Bool
    
    ' If the first character is +/- symbol, then set a boolean to allow for skipping
    If str[0]="-"[0] Or str[0]="+"[0] skip=True
    
    ' Iterate over the string
    For Local i:=Eachin str
        ' If the skip boolean is set to true or the character is a period (aka decimal point)
        If skip Or i="."[0]
            If skip skip=False
            
            ' If more that one decimal point is in the string, then throw an error
            If dec Error "BAD DECIMAL: "+str
            If i="."[0] dec=True
            Continue
        Endif
        
        ' Non numeric character detected, is Not A Number
        If Not (i>="0"[0] And i<="9"[0]) Return False
    Next
    
    ' String OK, so must be a number
    Return True
End
 

Jimmy

Active member
3rd Party Module Dev
Tutorial Author
Joined
Jan 2, 2020
Messages
878
Thanks, I noticed that the preivous Not(Int(item)) did not react on NaN but instead on true value of zero, so HTML5 was still unsolved.

Just out of curiousiy, if you cannot use thos implicit conversions, how do you check for NaN in Cerberus?
 

Jimmy

Active member
3rd Party Module Dev
Tutorial Author
Joined
Jan 2, 2020
Messages
878
Might use yours instead but for completeness here's how you could use NaN.
This one truly works everywhere. A bit ugly though.

Code:
Import mojo.app

Function Main:Int()
    Local lines:String[] =LoadString("testdata.txt").Split("~n")
    
    For Local line:String = Eachin lines
        Local items:String[] = line.Split(",")
        For Local item:= Eachin items
           
                   If item.Length <> 0 Then If (Int(item) = "NaN") Or (Not(Int(item)) And item<>"0") Then Print "NaN"
              
                 Print item

        Next
    Next
    Return 0
End
 
Top Bottom