Announcement

Collapse
No announcement yet.

Replace command

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

  • Replace command

    OK My eyes can't find the bug here, but in this function is a GPF waiting to happen, not sure why exactly.


    Code:
    Type XmitData
         fName      As Asciiz * 60
         CardNo     As Asciiz * 17
         ExpDate    As Asciiz * 5
         TransAmt   As Asciiz * 8        'In Pennies
         Reference  As Asciiz * 255
    End Type
    Global ccData() As XmitData
    Global Template As String
    Global OutFile  As String
    
    ccdata() dimmed in Winmain as XmitData
    
    Now, the dialog is read, I've verified there is length to each ccData() string (asciiz)
    I go to process a credit card, it gets done so I write an output file based on Template (Valid file), The idea is to replace constants in a file with strings, ie %n will be replaced with ccData.fName, then OutFile gets rewritten:
    
    Function WriteOutPutFile(ccData() As XmitData) As Long
    Local F As Long
    Local G As Long
    Local x As Long
    Local y As Long
    
    Local a As String
    Local c As String
    Local e As String
    Local n As String
    Local r As String
    
    a = "%a"
    c = "%c"
    e = "%e"
    n = "%n"
    r = "%r"
    
    
    Dim St(1 To 2000) As String
    
    G = FreeFile
    Open OutFile For Output As #G
    F = FreeFile
    Open Template For Input As #F
    
    If IsTrue Exist(Template) Then
        Do Until Eof(F)
           Incr x   'GPF Occurs on 6th round through loop
           Line Input #F,St(x)
           If Len(St(x)) > 1 And Instr(St(x),c ) Then Replace Any c With ccData(x).CardNo In St(x)     'ccData.everything is string
           If Len(St(x)) > 1 And Instr(St(x),a ) Then Replace Any a With ccData(x).TransAmt In St(x)
           If Len(St(x)) > 1 And Instr(St(x),e ) Then Replace Any e With ccData(x).ExpDate In St(x)
           If Len(St(x)) > 1 And Instr(St(x),n ) Then Replace Any n With ccData(x).fName In St(x)
           If Len(St(x)) > 1 And Instr(St(x),r ) Then Replace Any r With ccData(x).Reference In St(x)
           Print #G, St(x)
        Loop
    Else
        For x = 1 To wCount
            Print #G, TimeStamp + ":"
            Print #G,ccData(x).fName
            Print #G,ccData(x).CardNo
            Print #G,ccData(x).ExpDate
            Print #G,ccData(x).TransAmt
            Print #G,ccData(x).Reference
            Print #G, String$(48,"-")
        Next
    End If
    Close F,G
    Erase St
    End Function  
    
    The Html file has the headers below without the brackets for this BBS sake, the 6th position is null, Although I'm checking for it, it's still GPF'ing...
    
    html
    %n
    %c
    %e
    %a
    %r
    
    html

    -------------
    Scott Turchin


    Scott Turchin
    MCSE, MCP+I
    http://www.tngbbs.com
    ----------------------
    True Karate-do is this: that in daily life, one's mind and body be trained and developed in a spirit of humility; and that in critical times, one be devoted utterly to the cause of justice. -Gichin Funakoshi

  • #2
    What is the ubound of ccData when this routine is called? What line does it gpf on exactly>
    --Don
    Don Dickinson
    www.greatwebdivide.com

    Comment


    • #3
      Code:
      OK I fixed that array problem, ccData() is dimmed 1 to 1000, so 1000 transactions can be processed at one time, however this output file only gets written from web based use, so ccData(1).x will always be accurate, it is done in the ProcessCreditCards and ReadDialogData functions, but this is getting weirder:
      
      After the first two replace commands, I did a Msgbox ccdata(1).fname etc, and by the time it hit TransAmt, it was garbage in my Msgbox ccData(1).TransAmt, which is bizarre, something is corrupting memory.
      
      '------------------------------------------------------------------------------
      Function WriteOutPutFile(ccData() As XmitData) As Long
      Local F As Long
      Local G As Long
      Local x As Long
      
      Local a  As String
      Local c  As String
      Local e  As String
      Local n  As String
      Local r  As String
      Local St As String
      
      a = "%a"
      c = "%c"
      e = "%e"
      n = "%n"
      r = "%r"
      
      G = FreeFile
      Open OutFile For Output As #G
      F = FreeFile
      Open Template For Input As #F
      
      If IsTrue Exist(Template) Then
          Do Until Eof(F)
             Line Input #F,St
             If Len(St) < 2 Then Iterate '%a needs two characters
             Replace Any n With ccData(1).fName In St
             Replace Any c With ccData(1).CardNo In St     'ccData.everything is string
             Replace Any a With ccData(1).TransAmt In St
             Replace Any e With ccData(1).ExpDate In St
             Replace Any r With ccData(1).Reference In St
             Print #G, St
          Loop
      Else
          For x = 1 To wCount
              Print #G, TimeStamp + ":"
              Print #G,ccData(1).fName
              Print #G,ccData(1).CardNo
              Print #G,ccData(1).ExpDate
              Print #G,ccData(1).TransAmt
              Print #G,ccData(1).Reference
              Print #G, String$(48,"-")
          Next
      End If
      Close F,G
      End Function
      [This message has been edited by Scott Turchin (edited January 28, 2000).]
      Scott Turchin
      MCSE, MCP+I
      http://www.tngbbs.com
      ----------------------
      True Karate-do is this: that in daily life, one's mind and body be trained and developed in a spirit of humility; and that in critical times, one be devoted utterly to the cause of justice. -Gichin Funakoshi

      Comment


      • #4
        If you Compile this and it does not GPF on anyone elses system then my OS is hosed (??)

        Code:
        #Dim All
        #Compile Exe
        #Option Version4
        #Register None
        
        Type XmitData
             fName      As Asciiz * 60
             CardNo     As Asciiz * 17
             ExpDate    As Asciiz * 5
             TransAmt   As Asciiz * 8        'In Pennies
             Reference  As Asciiz * 255
        End Type
        Global ccData() As XmitData
        
        Function PbMain() As Long
        Dim ccData(1 To 100) As XmitData
        Local a  As String
        Local c  As String
        Local e  As String
        Local n  As String
        Local r  As String
        Local St As String
        
        a = "%a"
        c = "%c"
        e = "%e"
        n = "%n"
        r = "%r"
        ccData(1).fName = "John M. Doe"
        ccData(1).CardNo = "000000000000000"
        ccData(1).TransAmt = "100"
        ccData(1).ExpDate = "0901"
        ccData(1).Reference = "General Purchase"
        
        St = a + $CRLF + c + $CRLF + e + $CRLF + n + $CRLF + r
        MsgBox St
        Replace Any n With ccData(1).fName In St
        Replace Any c With ccData(1).CardNo In St     'ccData.everything is asciiz
        Replace Any a With ccData(1).TransAmt In St
        Replace Any e With ccData(1).ExpDate In St
        Replace Any r With ccData(1).Reference In St
               
        End Function

        -------------
        Scott Turchin


        Scott Turchin
        MCSE, MCP+I
        http://www.tngbbs.com
        ----------------------
        True Karate-do is this: that in daily life, one's mind and body be trained and developed in a spirit of humility; and that in critical times, one be devoted utterly to the cause of justice. -Gichin Funakoshi

        Comment


        • #5
          Scott --
          you should cancel ANY in REPLACE command. This variant works even with additional difficultes (some n inside St).

          Code:
          #Dim All
          #Compile Exe
          #Option Version4
          #Register None
          
          Type XmitData
               fName      As Asciiz * 60
               CardNo     As Asciiz * 17
               ExpDate    As Asciiz * 5
               TransAmt   As Asciiz * 8        'In Pennies
               Reference  As Asciiz * 255
          End Type
          Global ccData() As XmitData
          
          Function PbMain() As Long
          Dim ccData(1 To 100) As XmitData
          Local a  As String
          Local c  As String
          Local e  As String
          Local n  As String
          Local r  As String
          Local St As String
          
          a = "%a"
          c = "%c"
          e = "%e"
          n = "%n"
          r = "%r"
          ccData(1).fName = "John M. Doe"
          ccData(1).CardNo = "000000000000000"
          ccData(1).TransAmt = "100"
          ccData(1).ExpDate = "0901"
          ccData(1).Reference = "General Purchase"
          
          St = a + $CRLF + n + c + n + $CRLF + e + $CRLF + n + $CRLF + r
          Replace n With ccData(1).fName In St
          Replace c With ccData(1).CardNo In St     'ccData.everything is asciiz
          Replace a With ccData(1).TransAmt In St
          Replace e With ccData(1).ExpDate In St
          Replace r With ccData(1).Reference In St
          MsgBox St
          
          End Function
          What is strange - what compiler do ? Why doesn't select minimum length between MatchString & NewString ?
          Semantic mistake should not be a reason of GPF.

          [This message has been edited by Semen Matusovski (edited January 29, 2000).]

          Comment


          • #6
            You can use REPLACE ANY Only if The New string is the same length
            as the string you are replacing.

            If you want multiple replacement of differnet length string then use

            WHILE INSTR (St(x), n)
            Replace n With ccData(x).fName In St(x)
            WEND


            Comment


            • #7
              Jacob --
              Replace without ANY and with ANY perform different actions.

              REPLACE without ANY replaces ALL (!) occurrences of MatchString in
              MainString with NewString.
              So, it's not necessary to do WHILE INSTR (St(x), n).. WEND

              "If you use the ANY option, within MainString, each occurrence of each
              character in MatchString will be replaced with the corresponding character
              in NewString."
              Means following: If you want to change ALL letters "a" with "x", "b"
              with "y", "c" with "z", you should use REPLACE ANY "abc" WITH "xyz" IN A$

              Sample:
              a$ = "bacdcab"
              Replace "abc" With "xyz" In a$ ' <---- No effect , because there are no substrings "abc"
              MsgBox a$
              Replace Any "abc" With "xyz" In a$ ' <- result is yxzdzxy
              MsgBox a$


              [This message has been edited by Semen Matusovski (edited January 29, 2000).]

              Comment


              • #8
                Just a tip for better performance. You do a lot of printing, but why
                not build up a string buffer and print that one just once instead?
                It's much faster and more reliable. Example:

                Code:
                  Local Buf As String
                  Do Until Eof(F)
                    Incr x
                    Line Input #F,St(x)
                    Replace c With ccData(x).CardNo    In St(x) 'ccData.everything is string
                    Replace a With ccData(x).TransAmt  In St(x)
                    Replace e With ccData(x).ExpDate   In St(x)
                    Replace n With ccData(x).fName     In St(x)
                    Replace r With ccData(x).Reference In St(x)
                    Buf = Buf & St(x) & Chr$(13, 10)            'need a CRLF here
                  Loop
                  Print #G, Buf

                Comment


                • #9
                  Borje --
                  if to speak about performance and string buffer, it's necessary to remember that such statements as a$ = a$ + b$, where a$ is a string with variable length, work very bad since a moment, when a$ becomes enough large. To test this try following:

                  Code:
                  #Compile Exe
                  #Register None
                  DefInt A-z
                  
                  Function PbMain() As Long
                  
                  a$ = Space$(82& * 100000)
                  b$ = Space$(80) + $CRLF
                  t1# = Timer
                  For i = 1 To 100000
                     Mid$(a$, i * 82 - 81, 82) = b$
                  Next
                  t2# = Timer
                  MsgBox Str$(t2# - t1#)
                  a$ = ""
                  t1# = Timer
                  For i = 1 To 10000
                     a$ = a$ + b$
                  Next
                  t2# = Timer
                  MsgBox Str$(t2#-t1#)
                  
                  End Function
                  You will see a difference, even when 100000 to 10000. Then try to increase number of iterations for variant 2.

                  My whatches shows that increasing a buffer after 4-8kb has no effect.
                  So, in my oppinion, better to insert in your code some additional statements:
                  Code:
                    Local Buf As String
                    Do Until Eof(F)
                      Incr x
                      Line Input #F,St(x)
                      Replace c With ccData(x).CardNo In St(x) 'ccData.everything is 
                      ...
                      Buf = Buf & St(x) & Chr$(13, 10)
                      If Len(Buf) > 4096 Then Print #G, Buf;: Buf = ""
                   Loop
                   Print #G, Buf

                  Comment


                  • #10
                    You are right, Semen. I actually do this myself, when I save the language
                    databases I use in my translator to disk. I found that setting the limit
                    to around 32,000 bytes gave the best performace in a lopp that writes to a
                    HD, and then I use the first of your examples there, by filling up already
                    allocated string space with MID$().

                    It's very effective - saving 100,000 items takes less than a second..

                    Comment


                    • #11
                      OK So while that discussion is going on, can anyone produce the original GPF with this code, I'll give you a hint, it will process 2 Replace commands and will die on the 3rd

                      Code:
                      #Dim All
                      #Compile Exe
                      #Option Version4
                      #Register None
                      #Include "win32api.inc"
                      
                      Type XmitData
                           fName      As String * 35
                           CardNo     As String * 17
                           ExpDate    As String * 5
                           TransAmt   As String * 8        'In Pennies
                           Reference  As String * 255
                      End Type
                      Global ccData() As XmitData
                      
                      Function PbMain() As Long
                      Dim ccData(1 To 100) As XmitData
                      Local a  As String
                      Local c  As String
                      Local e  As String
                      Local n  As String
                      Local r  As String
                      Local St As String
                      
                      a = "@@a"
                      c = "@@c"
                      e = "@@e"
                      n = "@@n"
                      r = "@@r"
                      ccData(1).fName = "John M. Doe"
                      ccData(1).CardNo = "000000000000000"
                      ccData(1).TransAmt = "100"
                      ccData(1).ExpDate = "0901"
                      ccData(1).Reference = "General Purchase"
                      
                      St = a + $CRLF + c + $CRLF + e + $CRLF + n + $CRLF + r + Chr$(0)
                      
                      MsgBox St, %MB_ICONINFORMATION, "Test one"
                      'Replace Any "@@n" With ccData(1).fName In St
                      Replace Any "@@c" With ccData(1).CardNo In St     'ccData.everything is asciiz
                      Replace Any "@@a" With ccData(1).TransAmt In St
                      Replace Any "@@e" With ccData(1).ExpDate In St
                      'Replace Any "@@r" With ccData(1).Reference In St
                      MsgBox St, %MB_ICONINFORMATION, "Test two"
                      
                      End Function

                      -------------
                      Scott Turchin


                      Scott Turchin
                      MCSE, MCP+I
                      http://www.tngbbs.com
                      ----------------------
                      True Karate-do is this: that in daily life, one's mind and body be trained and developed in a spirit of humility; and that in critical times, one be devoted utterly to the cause of justice. -Gichin Funakoshi

                      Comment


                      • #12
                        Scott -

                        As Gafny pointed out, when you use REPLACE ANY the search and replace strings must be
                        the same length. Using the ANY option specifies a character-for-character replacement.

                        So when you do this…

                        Code:
                        ccData(1).CardNo = "000000000000000"
                        Replace Any "@@c" With ccData(1).CardNo In St
                        ...you are violating that rule because "@@c" is not the same length as "000000000000000".
                        I am not surprised that this produces a GPF. Not only that, but you are effectively
                        saying "replace @ with the first character of .CardNo, then replace "@" with the second character
                        of .CardNo, and then replace c with the third character of .CardNo" and I strongly suspect
                        that that's not what you intended to do.

                        Get rid of the ANY and I predict that the GPF will disappear.

                        -- Eric

                        -------------
                        Perfect Sync: Perfect Sync Development Tools
                        Email: mailto:[email protected][email protected]</A>



                        [This message has been edited by Eric Pearson (edited January 29, 2000).]
                        "Not my circus, not my monkeys."

                        Comment


                        • #13
                          That was it, OK Sorry for the misunderstanding

                          Cool, it's rther nice because it allows me to replace the %n with a username and write a web page based on a template ...

                          Cool! One more huge bug and this app is done!

                          Thanks!!

                          Scott

                          -------------
                          Scott Turchin


                          Scott Turchin
                          MCSE, MCP+I
                          http://www.tngbbs.com
                          ----------------------
                          True Karate-do is this: that in daily life, one's mind and body be trained and developed in a spirit of humility; and that in critical times, one be devoted utterly to the cause of justice. -Gichin Funakoshi

                          Comment


                          • #14
                            Guys --
                            I think that not GPF could be a thread for further discussion - here all is clear.
                            Scott, as I understand, wanted to replaces "all occurrences of MatchString in MainString with NewString", but not "character-to-character". He used REPLACE ANY, because thought that exactly REPLACE ANY performs needed replacement.
                            If to read documentation, it's very easy to understand, why Scott made a logical mistake and Jacob offered to use While Instr ...: Wend.
                            I was able to understand, what exactly perform these statements after testing only.

                            Another moment - why compiler generate GPF instead of - for example - run-time ON ERROR-situation ?

                            Comment


                            • #15
                              Simple. The programmer is responsible to ensure that these type of errors do not occur. The compiler simply cannot catch every possible error, especially when using pointers.

                              -------------
                              Lance
                              PowerBASIC Support
                              mailto:[email protected][email protected]</A>
                              Lance
                              mailto:[email protected]

                              Comment

                              Working...
                              X