Announcement

Collapse
No announcement yet.

Chr$(-1) found in string

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • #21
    Originally posted by Michael Mattias View Post
    ..and 'data type overflow' (including intermediate values in expresssions)?

    The NFS for #DEBUG OVERFLOW ON is still on file. I hope it's not waiting me to develop some "high confidence" in my ability to test for overflow and underflow.


    MCM
    I'm not sure I understand your request. Are you suggesting supplying production code with debug options like that turned on? If not then what is its purpose? To explain I have some complex math functions that certain sets of data can even cause 80 bit floating point to underflow or overflow. That statement wouldn't help as that is not an error in the math so wouldn't help in testing, just that the ranges of data in real use could cause it.
    Of course I could use a compiler that did inbuilt error checking for that, but the reason I bought PB is for speed and a compiler with that level of error checking would be useless for me. Its far faster to include a few simple numerical comparisons that detect if the math is heading that direction and take appropriate action before the underflow/overflow is reached. In my case this actually lets the math still generate correct answers in far more data sets as the error state is avoided.
    If you are worried about intermediate results then break the math up and put a test before where it is likely to happen.
    Digital computers are limited in the range of numbers and their accuracy that can be represented with a given number of bits. Its the programmers job to understand the limits when the goal is speed.

    Comment


    • #22
      Originally posted by Bob Zale View Post
      It's unfortunate that this thread has been hijacked a bit rather than really answer your question, so let me try to give you the correct overall information.
      That's funny. I thought I quite clearly explained what went wrong with his code in post #5.
      Jeff Blakeney

      Comment


      • #23
        Originally posted by Gary Peek View Post
        Bob, PB may do anything "non-standard" that they want. But don't you want what you do to make sense? As Michael said, CHR$(negative number) makes no sense.

        In my case it is not going to matter one bit because I test for null, but doing things in as standardized way as possible is a benefit to your company, trust me.

        I know you have some issues with some of the things Michael brings up, but if you just relax and takes notes, I think you will realize he is trying to improve your product.
        Just which standard are you referring to? Way back in early MS Basic it is clearly stated that the valid range is 0 to 255 and normally an error would occur with a value outside that. MS then enhanced it even in 16bit VB as it had to be able to handle the original multi-byte character format and later in 32 bit Unicode To do this two more versions of the instruction ChrB and ChrW were introduced. PB in line with its stated goal of speed thus limited error checking chose a different enhancement as there was no rule to break. Of course multi-byte is an MS idea that quickly went the way of the dinosaur.
        Personally I think it might be usefull to many if PB were to add W (Unicode) versions of many of its standard string instructions, but never remove its current speedy ASCII versions.

        Comment


        • #24
          > As Michael said, CHR$(negative number) makes no sense.

          Okay, to begin from the beginning...

          What should be the result of ASC(x$) when x$ is an empty string? Returning zero makes no sense, since that would imply that x$ starts with CHR$(0), which it doesn't. So a return value of -1 makes sense to me.

          Then... I like the idea that ASC returns -1 for the (several) conditions when the answer is "none". Zero would be the wrong answer. No?

          Then... in the interest of symmetry, I like the idea that CHR$(-1) returns an empty string.

          > I cannot see any use for CHR$() to support anything but 0 to 255 in numeric arguments

          Michael, that statement surprises me. Given your background with databases, the concept of NULL should be well-familiar to you. "No middle initial" is very different from "middle initial not known".

          An empty string and CHR$(0) are very different, and PB provides an easy way -- without critical-error-handing -- to tell the difference. What's the gripe?

          I always applaud your "behavior vs documentation" posts, but... what is the problem here? You don't like the design decision?

          I also applaud BZ's "don't break old code" policy, so... this is a done deal! In other words, tough *****. Exactly what would you like to see happen here?

          -- Eric
          Last edited by Eric Pearson; 30 Sep 2009, 01:47 PM.
          "Not my circus, not my monkeys."

          Comment


          • #25
            Your answer was great, Jeff. My concern was the "noise" along the way about "PowerBASIC makes no sense" and the personal stuff. I just wanted to tie it together and point out the common usage of an exception marker.

            You know, the original idea to use -1 as a marker here came in a conversation with my good friend, Ethan Winer, many years ago. We've used it for a long time. We've received hundreds of compliments about the idea, as did Ethan. To my recollection, this is the first time we've heard this sort of reaction. Is it a full moon? <smile>

            I would recommend that everyone look back at post #5 and read it again. Some very good information there!

            Best regards,

            Bob Zale
            PowerBASIC Inc.

            Comment


            • #26
              >You don't like the design decision?

              In this case, "the old way" was better. Well, maybe not 'better' in the abstract, but certainly 'different from what I am used to.'

              Then again, not a whole lot of PB/WIn users go back to PB/DOS, which like other BASICs of that era, returned an error 5 when you did something naughty with strings, eg LEFT$(stringvar, -2) or CHR$(99999).

              The overflow thing is different. Yes, of course I know how to test and what data types to use, but darned, it is just SO handy to allow the compiler to do it. Eg you don't get this...
              Code:
               LOCAL b AS BYTE
                 DO WHILE B <= 255 
                    INCR B 
                 LOOP
              ... generating an infinite loop, do you? You exit the loop with ERR=6

              BEsides, if Error 6 is in the help file I think I have an expectation it is used. (notwithstanding the text, "Overflow (%ERR_OVERFLOW) - This error is not currently supported")

              So why is it even in the help file? With an assigned internal equate ?

              MCM
              Michael Mattias
              Tal Systems (retired)
              Port Washington WI USA
              [email protected]
              http://www.talsystems.com

              Comment


              • #27
                So now programs should work contrary to the documentation? Okeee...

                I agree it would be nice to be able to set a flag to enforce rigid range checking. It would impose a massive amount of overhead for both size and speed, of course. The suggestion is on the list.

                Comment


                • #28
                  I can understand both sides of this discussion but as the documented behaviour is working correctly and has been working that way for some time, changing it, I feel, is not needed. Some think an error should be set and, in effect, one is. Instead of testing ERR you test the return value from ASC, CHR$, MID$ and INSTR. In the case of ASC, CHR$ and MID$, if you get -1, "" or "" returned respectively then you know something is wrong. The only case I can see for change is INSTR because if I have the following code:

                  Code:
                  X$ = ""
                  Y$ = "Jeff"
                  X& = INSTR("Jeff", X$)
                  Y& = INSTR("Jeff", Y$)
                  Both X& and Y& will return 1. For consistency, I think INSTR should have returned -1 as in this case, if I didn't test my match string to see if it was null before using it, I might assume that I found a valid match. If it returned -1, I would know immediately something was wrong. However, if I were to then do a MID$("Jeff", X&, LEN(X$)) I would end up getting a null string which would also tell me that something went wrong, just a little later. Changing this behaviour isn't necessary but it is a little inconsistent.

                  I don't think I've ever run into the situation where these return values have given me a problem as I try to make sure my data and ranges are okay before I get to these types of commands.

                  By the way, Michael, your loop above will be an endless loop regardless of whether an overflow error occurs because you don't test for an error condition.
                  Jeff Blakeney

                  Comment


                  • #29
                    >So now programs should work contrary to the documentation? Okeee...

                    You've been away too long, Tom.

                    When you implement a New Feature Suggestion (cited), you change BOTH the program AND the documentation.

                    MCM
                    Michael Mattias
                    Tal Systems (retired)
                    Port Washington WI USA
                    [email protected]
                    http://www.talsystems.com

                    Comment


                    • #30
                      Tom,

                      That’ll learn yuh! Do not poke anything through the bars.

                      Jeff,

                      I agree, including the empty string as the first argument. There’s an arcane ivory-tower alabaster beauty — or do I mix my building materials? — to

                      ... Instr("","") = -1

                      Instr is used in two ways: (1) To determine existence. If Instr() <> 0 etc, (2) To determine position: n = Instr(). It makes sense for Instr("",A) to be -1 for all strings A. See my earlier posts.

                      If you need any more convincing, the eminent mathematician Prof. Ludwig von Drake has recently published a hitherto undiscovered — because it’s so deep — relation between circles and strings:

                      ... Instr("","") = e^(i*pi)
                      Politically incorrect signatures about immigration patriots are forbidden. Searching “immigration patriots” is forbidden. Thinking about searching ... well, don’t even think about it.

                      Comment


                      • #31
                        Thank you Bob and Thank you Jeff for the explanations of what I obviously missed in the documentation.

                        I must apologize for what I thought was a simple question (not accusing anyone of anything) could so quickly spiral into some viral debate of how a compiler should or should not do something.

                        Quite honestly I love how PB handles things, I was just confused as to how I was getting -1 (or where it came from, or even what the heck is a character -1???)

                        Going back through the docs, and creating a better example of my question, I found where my problem came into play and have submitted the code to PowerBasic Support for verification.

                        All in all my original question would be fully answered if I had read the documentation closer, or closely follow your explanation or Jeff's


                        Keep up the good work
                        Engineer's Motto: If it aint broke take it apart and fix it

                        "If at 1st you don't succeed... call it version 1.0"

                        "Half of Programming is coding"....."The other 90% is DEBUGGING"

                        "Document my code????" .... "WHYYY??? do you think they call it CODE? "

                        Comment


                        • #32
                          Originally posted by Jeff Blakeney View Post
                          I can understand both sides of this discussion but as the documented behaviour is working correctly and has been working that way for some time, changing it, I feel, is not needed. Some think an error should be set and, in effect, one is. Instead of testing ERR you test the return value from ASC, CHR$, MID$ and INSTR. In the case of ASC, CHR$ and MID$, if you get -1, "" or "" returned respectively then you know something is wrong. The only case I can see for change is INSTR because if I have the following code:

                          Code:
                          X$ = ""
                          Y$ = "Jeff"
                          X& = INSTR("Jeff", X$)
                          Y& = INSTR("Jeff", Y$)
                          Both X& and Y& will return 1. For consistency, I think INSTR should have returned -1 as in this case, if I didn't test my match string to see if it was null before using it, I might assume that I found a valid match. If it returned -1, I would know immediately something was wrong.
                          Yes that would appear to be (hate to use the word) a bug. The first character of the tested string contains a character but the instruction is returning that there is no character there.

                          Comment


                          • #33
                            AFAIK, when the 'look for' is empty ("") it is always found in position 1. Not documented but seems to me it's worked like that forever.

                            But I agree 100% on the consistency thing: if ASC is going to return -1& when target is empty, seems INSTR should follow the same rules when the result is 'empty'
                            Michael Mattias
                            Tal Systems (retired)
                            Port Washington WI USA
                            [email protected]
                            http://www.talsystems.com

                            Comment


                            • #34
                              Mark, I believe INSTR("", "") or INSTR("A", "") should return -1 because the search pattern is null but INSTR("", "A") should return 0 because the search pattern was not found in the main string.

                              John, it may act like a bug but it is consistent with the documentation at present. Not that it isn't possible that buggy behaviour got documented.

                              Michael, the return value from an INSTR instruction where the search string is null is documented.

                              If MatchString is null (an empty string), INSTR returns 1 (if n& not specified) or n& (if n& is specified).
                              So INSTR("something", "") will return 1 and INSTR(5, "something", "") will return 5.
                              Jeff Blakeney

                              Comment


                              • #35
                                Jeff
                                I has never effected me as hopefully I would have checked for the empty seach string (maybe I have just been lucky )
                                Documented or not it is logically incorrect. If I perform a calculation of 1 + 1 and get any other answer than 2 then I would be very upset. As a programmer I rely on getting a logically accurate result. So if I test for an empty string (admittedly using INSTR would be a unusual way) but for such a test to give a totally wrong answer i.e. it is reported as an empty string when it is not IMHO breaks the fundermental rules of boolian algebra programming documented or not.

                                Comment


                                • #36
                                  INSTR("", "abc") should return 0 because the search pattern was not found in the main string.
                                  begs the question.

                                  [ADDED: No it doesn’t. "" is the main string, and "abc" is the search string, and indeed "abc" is not in "". As Jeff points out in the next post, I had Instr’s arguments backwards. And unlike Wrong Way Corrigan I didn’t do it on purpose. However the remainder of this post, after correcting the reversal, might still be of interest. I’ve replaced the first paragraph.]

                                  Instr("abc","") returns 1. Here's why it is should at least be non-zero, that is, why the search pattern "" should be considered in the main string "abc".

                                  Consider two examples of one string possibly within another. At first ignore the fact that a string is not just a collection of letters, it’s an ordered collection. We will address the order in a moment.

                                  Take the “universe” as the letters of the alphabet. (In general we can restrict the universe – or expand it – to any collection of characters which contains all the characters of the strings in question.)

                                  First example:
                                  ... "bc" is within "abcd"
                                  means
                                  ... (the letters b,c) are among (the letters a,b,c,d)
                                  This proposition is equivalent to its contrapositive,
                                  ... (the letters of the alphabet except a,b,c,d) are among (the letters of the alphabet except b,c)

                                  Similarly
                                  ... "" is within "abc"
                                  is equivalent to
                                  ... (the letters of the alphabet except a,b,c) are among (the letters of the alphabet)

                                  And that last is certainly true.

                                  However there’s a problem applying the equivalence of
                                  ... “All X are Y.”
                                  and its contrapositive
                                  ... “All ~Y are ~ X.” (the tilde indicates the complement with respect to the universe) to ordered classes. How do you take into account the order when you perform the complement?

                                  Without order, the complement of
                                  ... k,a,o,s
                                  is
                                  ... b,c,d,e,f,g,h,i,j,l,m,n,p,q,r,t,u,v,w,x,y,z

                                  With order, the complement of
                                  ... kaos
                                  is
                                  ... ?

                                  I asked Prof. Ludwig von Drake about this. Here’s his reply:

                                  “Who cares? All we need to know to answer the original question is the complement of nothing. And of course that’s everything (the universe). And as I said before, ‘anything is within everything’, therefore – since anything is the complement of something else, another anything – the contrapositive of ‘anything is within everything’ is ‘nothing is within anything’.”

                                  Wait a minute. The complement of nothing may be everything, but the second half of the contrapositive goes begging for a meaning. You still need to define the complement of a nonempty string to make a complete proposition. If there is no sensible complement of both classes there is no sensible contrapositive of the proposition.

                                  Well, I’m waiting, Professor.

                                  I’m afraid Professor Ludwig von Drake has stalked off, or anyway waddled off. But the first part of the argument I began with is salvageable as an analogy. Whether or not "" is within "abc" is a matter of definition, and the analogy with unordered collections of letters suggests that the answer should be Yes.
                                  Last edited by Mark Hunter; 5 Oct 2009, 12:10 AM. Reason: corrected per Jeff below (see ADDED remark in text)
                                  Politically incorrect signatures about immigration patriots are forbidden. Searching “immigration patriots” is forbidden. Thinking about searching ... well, don’t even think about it.

                                  Comment


                                  • #37
                                    Mark, you have the parameters backwards for the INSTR function. With the statement INSTR("", "abc"), the main string is null and the search string is "abc". If you change the statement to INSTR("abc", "") your arguments can still be made.

                                    Here is some code I just threw together. The MyINSTR function acts just like the current INSTR function but the MyINSTR2 function returns zero every time.

                                    Code:
                                    #COMPILE EXE
                                    #DIM ALL
                                    
                                    FUNCTION PBMAIN () AS LONG
                                    
                                        LOCAL sMainString   AS STRING
                                        LOCAL sSearchString AS STRING
                                    
                                        sMainString     = "abc"
                                        sSearchString   = ""
                                    
                                        MSGBOX FORMAT$(MyINSTR(0, sMainString, sSearchString)) + $CRLF + _   ' returns 0
                                               FORMAT$(MyINSTR(1, sMainString, sSearchString)) + $CRLF + _   ' returns 1
                                               FORMAT$(MyINSTR(2, sMainString, sSearchString)) + $CRLF + _   ' returns 2
                                               FORMAT$(MyINSTR(3, sMainString, sSearchString)) + $CRLF + _   ' returns 3
                                               FORMAT$(MyINSTR(4, sMainString, sSearchString))               ' returns 0
                                    
                                        MSGBOX FORMAT$(MyINSTR2(0, sMainString, sSearchString)) + $CRLF + _   ' returns 0
                                               FORMAT$(MyINSTR2(1, sMainString, sSearchString)) + $CRLF + _   ' returns 0
                                               FORMAT$(MyINSTR2(2, sMainString, sSearchString)) + $CRLF + _   ' returns 0
                                               FORMAT$(MyINSTR2(3, sMainString, sSearchString)) + $CRLF + _   ' returns 0
                                               FORMAT$(MyINSTR2(4, sMainString, sSearchString))               ' returns 0
                                    
                                    END FUNCTION
                                    
                                    FUNCTION MyINSTR(BYVAL lPos AS LONG, sMainString AS STRING, sSearchString AS STRING) AS LONG
                                    
                                        WHILE lPos > 0 AND lPos <= LEN(sMainString) + LEN(sSearchString)
                                            IF MID$(sMainString, lPos, LEN(sSearchString)) = sSearchString THEN
                                                FUNCTION = lPos
                                                EXIT FUNCTION
                                            END IF
                                            INCR lPos
                                        WEND
                                        FUNCTION = 0
                                    
                                    END FUNCTION
                                    
                                    FUNCTION MyINSTR2(BYVAL lPos AS LONG, sMainString AS STRING, sSearchString AS STRING) AS LONG
                                    
                                        LOCAL lFlag     AS LONG
                                        LOCAL lIndex    AS LONG
                                    
                                        WHILE lPos > 0 AND lPos <= LEN(sMainString) + LEN(sSearchString)
                                            lFlag = 0
                                            FOR lIndex = 1 TO LEN(sSearchString)
                                                IF MID$(sMainString, lPos + lIndex - 1, 1) = MID$(sSearchString, lIndex, 1) THEN
                                                    lFlag = 1
                                                ELSE
                                                    lFlag = 0
                                                END IF
                                            NEXT lIndex
                                            IF ISTRUE(lFlag) THEN
                                                FUNCTION = lPos
                                                EXIT FUNCTION
                                            END IF
                                            INCR lPos
                                        WEND
                                        FUNCTION = 0
                                    
                                    END FUNCTION
                                    You will notice that it there is quite a bit more code involved in MyINSTR2 which is why I'm sure the powers that be chose not to use it as it can slow things down.

                                    Both functions will return zero if the start position is less than 1 or greater than the length of the main string. MyINSTR returns the start position in the other cases because it is using MID$ and specifying a length of zero so it gets a zero length or null string and compares it to the null search string to find a match at the start position. MyINSTR2 returns zero for all the other cases because the code inside the FOR/NEXT loop is never executed because the stop pararmenter is less than the start parameter and the step is the default of plus one.

                                    Personally, I'm happy with the way things work at present, I just need to be sure I'm not using a null string as my search string. I can know that I'm not using a null string if I'm using string constants in my code, or I can infer it from what I set the search string variable to earlier in my code, or, if I'm not sure what the variable is going to be set to (ie. from user input at run time), I can test the search string variable before doing the INSTR call.

                                    The documentation could use a little bit clearer of a warning about this situation but otherwise, it isn't bad as the information is there.
                                    Jeff Blakeney

                                    Comment

                                    Working...
                                    X