Announcement

Collapse
No announcement yet.

Substrings from Offsets in a string

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

  • #21
    Originally posted by Fred Harris View Post
    Another possibulity, if you can see your way clear to forgoing the use of Graphic Priint statements, is DrawText(). That Api function call requires exactly the information you specified you have, i.e., length - offset data pairs. This is another way of eliminating the two time consuming operations of
    Thanks Fred, I'll keep it in mind if the FIELDing method bogs down. I've got all this test code in a small test pgm right now. The proof will be to add it back into the main pgm where it belongs and see how well the whole process runs. Right now everything seems to look like FIELD will do the job and is (for me) the simplest to integrate back into the main program.
    I know you havn't been with PowerBASIC a really long time George
    Very true, when you've spent 35 years coding in mainframe Assembler, even Basic seems very high level, add Windows and it's monstrous API and I doubt I'll live long enough to get proficient, I'm just a retired dabbler.

    You guys in the forum are the greatest help imaginable, I truly envy the collective knowledge you all have.
    George

    Comment


    • #22
      >...coding in mainframe Assembler

      But you have to admit mainframe assembler does include the instruction with the absoute 'coolest-' sounding mnemonic: ZAP.

      (Zero and Add Packed for the curious).
      Michael Mattias
      Tal Systems (retired)
      Port Washington WI USA
      [email protected]
      http://www.talsystems.com

      Comment


      • #23
        Originally posted by Michael Mattias View Post
        >...coding in mainframe Assembler

        But you have to admit mainframe assembler does include the instruction with the absoute 'coolest-' sounding mnemonic: ZAP.

        (Zero and Add Packed for the curious).
        True, it was the neatest mnemonic,but system programming didn't do much with packed decimal fields, so it really wasn't too common in the stuff I worked on.

        Ah! the 'good ole days'.

        Comment


        • #24
          OK another question/problem.

          I'm using FIELD variable as described in the original question.

          Although they are effectively STRING variables, I can't pass then to any SUB / FUNCTION routines that expect strings without getting a mismatched parameter error. Souldn't a FIELD variable satisfy the definition type of STRING?

          Do I have to use a UNION structure to overcome this? Or is there some way of fudging the call syntax.

          George

          Comment


          • #25
            'Good question , not sure if a pointer could be used?
            'Of course GLOBAL or GOSUB is another way.
            Code:
            'FIELD.BAS
            'This should be efficient, FIELD once and no function CALL overhead.
            'This applies to disk files, but food for thought.
            #COMPILE EXE
            #DIM ALL
            DECLARE SUB Test(FieldNumber AS LONG)
            GLOBAL fDummy AS FIELD, f() AS FIELD
            FUNCTION PBMAIN AS LONG
              LOCAL sFileName       AS STRING
              LOCAL FieldNumber     AS LONG
              LOCAL FieldsPerRecord AS LONG
              LOCAL hFile           AS LONG
              LOCAL RecordNumber    AS LONG
              LOCAL RecordLength    AS LONG
              LOCAL OffsetLength    AS LONG
              LOCAL TotalRecords    AS LONG
              
            'These could be read from disk to create a dynamic database
              sFileName = "ABC.TXT"
              KILL "ABC.TXT":ERRCLEAR
              RecordLength = 20         'required
              TotalRecords = 3          'required
              FieldsPerRecord = 4       'required
              REDIM StartPosition(1 TO FieldsPerRecord) AS LONG
              REDIM Length (1 TO FieldsPerRecord) AS LONG
              StartPosition(1) = 1:  Length(1) = 4
              StartPosition(2) = 5:  Length(2) = 6
              StartPosition(3) = 11: Length(3) = 3
              StartPosition(4) = 14: Length(4) = 7
            '-------------------------------------------------------------
            'Create some data for testing
              OPEN sFileName FOR RANDOM AS hFile LEN = RecordLength
              FIELD #hFile, RecordLength AS fDummy
              FOR RecordNumber = 1 TO TotalRecords
                fDummy = "The power of BASIC!" + FORMAT$(RecordNumber)
                PUT #hFile
              NEXT
              CLOSE #hFile
            '-------------------------------------------------------------
            'Open database
              hFile= FREEFILE
              OPEN sFileName FOR RANDOM AS #hFile LEN = RecordLength
            'Setup FIELD only once
              REDIM f(1 TO FieldsPerRecord) AS FIELD
              FOR FieldNumber = 1 TO FieldsPerRecord
                OffSetLength = StartPosition(FieldNumber)-1
                FIELD #hFile,OffsetLength AS fDummy, Length(FieldNumber) AS f(FieldNumber)
              NEXT
            'Get record and display
              FOR RecordNumber = 1 TO LOF(hFile)\RecordLength
                GET #hFile,RecordNumber
                FOR FieldNumber = 1 TO FieldsPerRecord
                  Test(FieldNumber)
                 NEXT
              NEXT
              CLOSE hFile
              WAITKEY$
            END FUNCTION
            SUB Test(FieldNumber AS LONG)
                ? f(fieldNumber)
            END SUB

            Comment


            • #26
              Code:
              SUB Test(testdata() AS FIELD, FieldNumber AS LONG)
                   ? TestData(FieldNumber)
              END SUB

              Comment


              • #27
                These also work

                Code:
                'Get record and display
                  FOR RecordNumber = 1 TO LOF(hFile)\RecordLength
                    GET #hFile,RecordNumber
                    FOR FieldNumber = 1 TO FieldsPerRecord
                      test f(FieldNumber)
                     NEXT
                  NEXT
                  CLOSE hFile
                  WAITKEY$
                END FUNCTION
                SUB Test(f AS FIELD)
                     ? f
                END SUB
                 
                SUB Test2(f() AS FIELD, FieldsPerRecord AS LONG)
                   LOCAL x AS LONG
                   FOR x = 1 TO FieldsPerRecord
                      ? f(x)
                    NEXT
                END SUB
                Last edited by Mike Doty; 8 Apr 2008, 11:45 AM. Reason: More solutions

                Comment


                • #28
                  Originally posted by Mike Doty View Post
                  Code:
                  'Get record and display
                    FOR RecordNumber = 1 TO LOF(hFile)\RecordLength
                      GET #hFile,RecordNumber
                      FOR FieldNumber = 1 TO FieldsPerRecord
                        test f(FieldNumber)
                       NEXT
                    NEXT
                    CLOSE hFile
                    WAITKEY$
                  END FUNCTION
                  SUB Test(f AS FIELD)
                       ? f
                  END SUB
                  Hi Mike,
                  Yes, no problem passing FIELD variables AS FIELDS, but I've got existing SUBs which expect STRINGS and are called from lots of other places. Now I've got these FIELDed strings and can't pass them.

                  Temporarily I've just cloned the SUBs in question with a slightly modified name and altered their prototypes to accept FIELDS, but duplicating code is not a real solution.

                  Comment


                  • #29
                    Wrap the field variable in parenthesis or use BYCOPY in you call statement to convert the field variable to a temporary string variable.

                    Code:
                    sub MySub(s as string)
                      ...
                    end sub
                    
                    function pbmain
                      Local f as field
                    
                      ...
                      MySub(BYCOPY f)
                      ' or
                      MySub((f))
                      ...
                    end function
                    Sincerely,

                    Steve Rossell
                    PowerBASIC Staff

                    Comment


                    • #30
                      Originally posted by Steve Rossell View Post
                      Wrap the field variable in parenthesis or use BYCOPY in you call statement to convert the field variable to a temporary string variable.
                      Hi Steve
                      Hmmm, I was using FIELD to access sub-strings of a much larger string to avoid the overhead of creating temporary strings. Doing what you suggest seems to simply negate that entirely, I may as well have used MID$ to access the substrings.

                      Cloning my SUBs and altering the passed parameter from STRING to FIELD works perfectly, so obviously FIELDed variables act just like normal strings (which is what they're supposed to).

                      Would a UNION solve this (pairing a STRING and a FIELD)?

                      Better still, alter Powerbasic to accept FIELDS as STRINGS in parameters.

                      George

                      Comment


                      • #31
                        Pointers work. The strings don't terminate with NUL so the length is a problem. Went through that recently. You know the length of each
                        field though, but a temp string would be created to get the LEFT$ of
                        the string. The fastest way would always be to eliminate the CALL.
                        A pointer expert would probably have a solution here or passing the PEEK$ for length might work.
                        Last edited by Mike Doty; 8 Apr 2008, 12:58 PM.

                        Comment


                        • #32
                          pointer expert would probably have a solution here or passing the PEEK$ for length might work.
                          If you need a null-terminated string for your function call, you have to create it. You can use MID$ or PEEK$, it really doesn't matter. i.e., there is no Silver Bullet using pointers or anything else.

                          But you said you needed a STRING argument anyway, meaning you have to create that string somehow, so what's the actual problem/issue here?
                          Michael Mattias
                          Tal Systems (retired)
                          Port Washington WI USA
                          [email protected]
                          http://www.talsystems.com

                          Comment


                          • #33
                            Hi George--

                            "Doing what you suggest seems to simply negate that entirely, I may as well have used MID$ to access the substrings."

                            Could be that's why Steve recommended MID$() to you a week ago. He said then it was the most practical solution. His comment today was only to offer you safety -- a program that works.


                            "Cloning my SUBs and altering the passed parameter from STRING to FIELD works perfectly, so obviously FIELDed variables act just like normal strings (which is what they're supposed to)."

                            That is not a correct inference. At some point, this will fail. Dramatically.


                            "Would a UNION solve this (pairing a STRING and a FIELD)?"

                            That's a physical impossibility. A string variable is four bytes in size. A field variable is sixteen bytes in size.


                            "Better still, alter Powerbasic to accept FIELDS as STRINGS in parameters."

                            If FIELD variables were STRING variables, would we have two data types? No. They are two different data types because they are different.

                            Best regards,

                            Bob Zale
                            PowerBASIC Inc.

                            Comment


                            • #34
                              Not sure if this will help you but should stop the overhead of OLE string creation.
                              LOCAL Tempstring as ASCIIZ * 10000 'or any value larger than the longest posible substring

                              FOR ' your list of substrings
                              Tempstring = MID$(Longstring, Offset, Length)
                              'do what you want with it
                              NEXT

                              Comment


                              • #35
                                >Not sure if this will help you but should stop the overhead of OLE string creation

                                I would not bet on that working, the compiler may when it sees MID$ decide to create a temp string, which it then moves to the destination buffer, and destroys the temp string.

                                CopyMemory in this case would certainly eliminate string creation:
                                Code:
                                CopyMemory VARPTR(TempString), STRPTR(LongString) + Offset + 1, Length + 1
                                (We add one to length to ensure the trailing nul is copied)

                                (Assuming "offset" here means "zero-based byte number", which by convention is what "offset" means).
                                Michael Mattias
                                Tal Systems (retired)
                                Port Washington WI USA
                                [email protected]
                                http://www.talsystems.com

                                Comment


                                • #36
                                  How soon they forget... {smile}

                                  If you use CopyMemory, where would you copy it to? A temporary string?

                                  Use MID$() and you have a grand total of one (1) temp string and one (1) copy operation.

                                  Use any other method and you have a grand total of 1 or more temp strings. The ASCIIZ method method above will use two (2) temp strings and three (3) copy operations of the text.

                                  Best of luck,

                                  Bob Zale
                                  PowerBASIC Inc.

                                  Comment


                                  • #37
                                    >If you use CopyMemory, where would you copy it to? A temporary string

                                    Huh? I showed my code!

                                    I copied a substring of the already-created "big string" to the local ASCIIZ variable.

                                    No temp strings here.

                                    Oh, wait a minute, I didn't do the null termination correctly, did I?

                                    Let's try.... take two:
                                    Code:
                                    LOCAL pb AS BYTE PTR , pbZ AS BYTE PTR
                                    
                                    pb               = STRPTR(LongString) 
                                    pbZ             = VARPTR(TempString)
                                    CopyMemory    PBZ, pb + Offset + 1, Length
                                    @pbZ[length]    = 0
                                    MCM
                                    (He said, as though he were even going to bother for only a couple hundred strings.)
                                    Last edited by Michael Mattias; 8 Apr 2008, 05:10 PM. Reason: broke. fixed.
                                    Michael Mattias
                                    Tal Systems (retired)
                                    Port Washington WI USA
                                    [email protected]
                                    http://www.talsystems.com

                                    Comment


                                    • #38
                                      Originally posted by Bob Zale View Post
                                      How soon they forget...Use any other method and you have a grand total of [B]1 or more temp strings.
                                      Surely if you use pointers you don't have any temp strings?

                                      Yours absentmindedly,

                                      Comment


                                      • #39
                                        >Surely if you use pointers you don't have any temp strings

                                        Depends on how you use them. Code not shown, except mine: No temp strings.

                                        OF course, if that ASCIIZ is then passed to a GRAPHICS statement requiring a STRING parameter, I would not be at all surprised if the compiler created a temp OLE string to use in the GRAPHICS call anyway. But that would take dis-assembly to figure out and I don't do dis-assembly.

                                        STRING giveth and STRING taketh away.
                                        Michael Mattias
                                        Tal Systems (retired)
                                        Port Washington WI USA
                                        [email protected]
                                        http://www.talsystems.com

                                        Comment


                                        • #40
                                          Originally posted by Chris Holbrook View Post
                                          Surely if you use pointers you don't have any temp strings?
                                          Yours absentmindedly,
                                          All depends upon what you do with those pointers. Regardless, temp strings can be a great asset when used wisely. In the real world, yes you normally have temp strings. Good thing, too.

                                          Comment

                                          Working...
                                          X