Forum Index
HomeZBasic Home   Forum RulesForum Rules   Forum FAQForum FAQ   MemberlistMemberlist   UsergroupsUsergroups   RSS FeedRSS Feed
Site SearchSite Search   LinksLinks   DownloadDownload   Digests and SubscriptionsDigests and Subscriptions
ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in   RegisterRegister
Converting a String to an Int....
Goto page Previous  1, 2
 
Post new topic   Reply to topic    Forum Index -> ZBasic Language
Author Message
victorf



Joined: 01 Jan 2006
Posts: 342
Location: Schenectady, New York

Posted: 20 July 2006, 9:22 AM    Post subject: Reply with quote

Don,

Quote:

The second test is entirely superfluous. Since c is a Byte value, its value is never less than zero. After subtracting 48, characters preceding the digit zero will result in values from &Hce to &Hff, all of which are larger than 9. Characters following the digit 9 will all yield values above 9 after subtraction. Hence the first test suffices.


I'm not smart enough to have thought of that Smile Thanks for 'enlightening' me.

As for the if/then/else thingy, just more 'enlightenment'

Vic
Back to top
victorf



Joined: 01 Jan 2006
Posts: 342
Location: Schenectady, New York

Posted: 20 July 2006, 9:36 AM    Post subject: Reply with quote

Don,

Quote:

If you use tabs in your code it works out better. The problem is that you can't keyboard a tab in the edit box. You can, however, copy and paste a tab or a block of code containing tabs.

I always use tabs in my code. Confused Tabs have been a bugaboo for me since the '80s when I started writing code. I have tab spacing set to two in my IDE.

Vic
Back to top
victorf



Joined: 01 Jan 2006
Posts: 342
Location: Schenectady, New York

Posted: 20 July 2006, 9:42 AM    Post subject: Reply with quote

Don,

I incorporated your latest suggestions.

Code:

Sub CS2Int(ByRef istr as string, _
                ByRef toint as integer, _
                ByRef flag as byte)

'this subroutine convertes the numeric value in istr into the integer
'toint. The only allowed characters are minus and 0 - 9. If istr represents
'a negative number then the minus sign must be the first character in the
'string.

'The subroutine returns:
'   0 in flag if the conversion is successful,
'   1 in flag if it incounters a non-number in istr
' 2 in flag if number exceeds the value of an integer
' 3 if istr contains NO data

   Const MINUS as byte = 45
   Const MAXINT as Long = 32767
   
   Dim neg as boolean
   Dim l as Long
   Dim d as integer
   Dim ctr as integer
   Dim rstr as string
   Dim c as byte
   
   flag = 0                                    'assume success
   d = 1                                          'start of string
   l = 0                                          'no value yet
   rstr = Trim(istr)                        'dump any spaces
   If Len(rstr) = 0 Then                  'sent a nil string
      flag = 3                                 'flag nothing in string
      toint = 0                                 'send back 0
      Exit Sub                                 'go home
   End If
   
   c = Asc(rstr,1)                           'look at first character
   
   neg = (c = MINUS)                        'is it a minus sign
   If  neg Then                              'if so
      d = 2                                       'skip over it
   End If

   For ctr = d To Len(rstr)            'for all further characters
     c = Asc(rstr, ctr) - 48            'make each numneric
      if (c > 9) Then                        'is it 0 to 9?
         flag = 1                              'if not set error flag
         Exit For                              'get out
      End If
      l = 10 * l + CLng(c)
      If l > MAXINT then                  'got too big??   
         flag = 2                              'flag it
         Exit For                              'get out
      End If
   Next
   
  If CBool(flag) Then                     'other errors?
     l = 0                                    'return 0
   End If
   If neg Then                              'was number negative?
     l = -l                                    'negate our results
   End If
   
   toint = CInt(l)                           'send it home
   
End Sub   'CS2Int


I hope someone finds it useful

BTW: everything was tab aligned in the IDE.

Vic
Back to top
spamiam



Joined: 13 Nov 2005
Posts: 689

Posted: 20 July 2006, 13:15 PM    Post subject: Reply with quote

Vic, it looks slick and quite robust.

I just wonder if the line
Code:
rstr = Trim(istr)

could be omitted in some way. It is a good check to do, but if it is a numerical string with trailing spaces, then you could deal with this in the loop where you decode the number.

To do this, check the first character that should be a digit. If it is, then you have at least one good digit and you can set a "good data" flag to true.

Then you read out the digits the way you uusally do. At exit, if you have the error flag set (i.e. abnormal completion of the character interpretation), but also have the "good data" flag, then use the good data and clear the abnormal completion flag and exit.

I have to go now, but I will throw together my modification for you later this AM. Real work calls.

-Tony
Back to top
spamiam



Joined: 13 Nov 2005
Posts: 689

Posted: 20 July 2006, 15:15 PM    Post subject: Reply with quote

Here is the way to avoid the need to use the TRIM function. Functionally it will work the same as your original code, but only tests for a trailing space if it actually encounters a non-numerical character. It ought to work a little faster than ALWAYS testing all the characters for being a space.

Code:
   

     'Do not use the TRIM function
   Const SPACE as Byte = 240       
                      'ascii value of a space less 48,  wrapped around 256
                      '32+256-48 = 240  [be sure this is not "off by 1"]

   For ctr = d To Len(rstr)            'for all further characters
     c = Asc(rstr, ctr) - 48            'make each numneric
      if (c > 9) Then                        'is it 0 to 9?
          If (c=SPACE) Then
               Exit For                        'exit without error
           Else
                flag = 1                        'set error flag
                Exit For                         'get out
           End If
      End If
      l = 10 * l + CLng(c)
      If l > MAXINT then                  'got too big??   
         flag = 2                              'flag it
         Exit For                              'get out
      End If
   Next
Back to top
dkinzer
Site Admin


Joined: 03 Sep 2005
Posts: 2593
Location: Portland, OR

Posted: 20 July 2006, 15:23 PM    Post subject: Reply with quote

Quote:
I have tab spacing set to two in my IDE.

That's why the code has unusual spacing. The standard in the Unix environment has been that tab stops are every 8 spaces. I have always thought that this was entirely too much and have used 4 spaces for many years. The forum code seems to use 3 spaces, as can be seen in the test code below.
Code:

         1         2         3         4
1234567890123456789012345678901234567890
   1 tab
      2 tabs
         3 tabs
            4 tabs

I suspect that the only way to solve this is to expand tabs to spaces before pasting the code. That would preserve the spacing that you see in your editing environment, irrespective of what the tabstop settings are.
Back to top
dkinzer
Site Admin


Joined: 03 Sep 2005
Posts: 2593
Location: Portland, OR

Posted: 20 July 2006, 15:32 PM    Post subject: Reply with quote

Quote:
Here is the way to avoid the need to use the TRIM function.

One advantage to not using Trim() is that the string can then be passed ByVal, and the source string will not be changed.

Quote:
Functionally it will work the same as your original code[...]

As I read it, it does not correctly handle a string with invalid characters after the first trailing space, e.g. " 123 xxx". My original post contained an oft-used function skipWhite(), reproduced below, that could be employed to good advantage. Then, when processing is done, if the index is past the end of the string, then the string contained only acceptable characters.
Code:
'
'' skipWhite
'
' Advance an index past spaces/tabs in a string, limited by the
' given length.  The index of the first non-whitespace character
' is returned.
'
Private Function skipWhite(ByVal str as String, ByVal slen as Integer, _
      ByVal idx as Integer) as Integer
   Do While (idx <= slen)
      Dim c as Byte
      c = Asc(str, idx)
      If ((c <> &H20) And (c <> &H09)) Then
         Exit Do
      End If
      idx = idx + 1
   Loop
   skipWhite = idx
End Function
Back to top
victorf



Joined: 01 Jan 2006
Posts: 342
Location: Schenectady, New York

Posted: 20 July 2006, 17:30 PM    Post subject: Reply with quote

I see little advantage to adding another layer of complexity to the code. The system function TRIM gets the job done. Smile I thought that is what the system library is for. CS2Int is free code and anyone can modify it to their heart's content.

I have a question. In this snippet:
Code:

      If ((c <> &H20) And (c <> &H09)) Then


Is there an advantage to using the hexadecimal values? What advantage is gained over using 32 and 9? Just curious Exclamation

Vic
Back to top
spamiam



Joined: 13 Nov 2005
Posts: 689

Posted: 20 July 2006, 18:16 PM    Post subject: Reply with quote

Quote:
As I read it, it does not correctly handle a string with invalid characters after the first trailing space, e.g. " 123 xxx".


Well, I suppose that depends on the definition of "correctly". I had considered this issue as I suggested my modification.

As Vic wrote the code, any non-numeric characters in the middle of a set of numeric characters, or non-space, non-numeric characters at the end will trigger an error condition.

I would agree with this. A space in the middle of a string representing a single number would be highly suspect. "123 456" would seem to me to be two separate numbers rather one number of the value 123456. In this case, I would suppose that the most correct of the possible "valid" numerical answer is 123, and this is what my modification would return.

Vic's version is probably most corrrect by just generating an error condition and leaving it at that. So, I stand corrected. Leave Vic's code the way he wrote it.

I consider it bad form to modify the source string. I think it would be "best" to pass the string by val, but it does consume stack space to duplicate the string.

Responding to Vic's question re: hex constants adding any efficiency. I doubt that the HEX values are any more efficient than DEC for the compiler. I use hex if the number is actually a binary bit pattern, and not a numerical value as I am using it. I use Dec if it is a numerical value, usually.

It almost seems as if Don was breaking his own rule about "magic numbers". I always have to look up ascii values. I can remember only a couple of characters off the top of my head. I think that these should have been named constants. That is what I did with the SPACE value in my version of the code.

Of course, as Vic said that this is just suggested code, and feel free to modify it to fit your individual needs. But.... someone may look at this code to paste into their own program. As such it should be as efficient as possible. Even more, it should serve as a coding tutorial. It should demonstrate "best coding practices", whatever they are.

I think the value of this discussion is the discussion istelf, not the actual code that is generated! I know that I have a lot to learn about "good" coding!!!! Like I said, I never took a course, although I actually used to tutor people in Pascal.

It was pretty funny. I was tutoring people in Pascal eventhough I did not know Pascal syntax at all. It worked out really well. Most of the time the students knew HOW to write the code, they just did not know WHAT to write. They needed help on the algorithms. THis worked out really well. I was able to teach them in a non-language specific manner, and they then had to write their own code. If I had more Pascal abilities, I would have led them further down the line until they had a final product after their tutoring. I liked it better this way. I think they got more out of it too. They would come back a little while later and we would look at the code and the output and then see what it was actually doing compared to what we had expected based on the algorithm. I really enjoyed that job.

-Tony
Back to top
stevech



Joined: 23 Feb 2006
Posts: 688

Posted: 20 July 2006, 18:23 PM    Post subject: Reply with quote

A ZBasic version of sscanf() as in C might be useful to everyone. One could transliterate the public domain C code for this handy function.

sscanf() handles longs, ints, signed/unsigned, floats and strings. Often sscanf() is written assembly language for the sake of speed, for microprocessor libraries.

sscanf() is arguably an overkill for just Cint() of a string.

A ZBasic translation of the C library atoi() and atol() are applicable.
Back to top
dkinzer
Site Admin


Joined: 03 Sep 2005
Posts: 2593
Location: Portland, OR

Posted: 20 July 2006, 20:20 PM    Post subject: Reply with quote

victorf wrote:
Is there an advantage to using the hexadecimal values? What advantage is gained over using 32 and 9?

There is no advantage unless you think of character values in terms of hexadecimal. I know the hex values for most of the ASCII character set but I don't know the decimal equivalents. It's somewhat like thinking in French vs. English.

Regarding Tony's comment about magic numbers - ASCII character values are well known and are thus less "magic". If the purpose of a routine is to process a character string, a programmer with even a modicum of experience will recognize what's being done even if they have to consult a chart to figure out the meaning of the specific values. That said, it may still be useful to define constants for the character values for the reader who doesn't know the ASCII table.

Similarly, if your routine is calculating the area of a circle, using the magic number 3.14159 is unlikely to cause anyone to ponder why that particular value is being used.

I suppose a general rule would be to define constants for such values if doing so is likely to make the code more readable.
Back to top
victorf



Joined: 01 Jan 2006
Posts: 342
Location: Schenectady, New York

Posted: 20 July 2006, 20:31 PM    Post subject: Reply with quote

I normally define constants for these 'magic numbers'. I always make them all caps so they stand out. See MAXINT and MINUS in my code. I'm a decimal guy, but keep a chart handy just in case. Smile

Vic
Back to top
Display posts from previous:   
Post new topic   Reply to topic    Forum Index -> ZBasic Language Time synchro. with the server - Timezone/DST with your computer
Goto page Previous  1, 2
Page 2 of 2

 


All content Copyright © 2005-2012 Elba Corp. All Rights Reserved.
Opinions expressed in posts are those of the author and not necessarily those of Elba Corp.
Powered by phpBB © 2001, 2005 phpBB Group