Solved

Reading characters in a string.

Posted on 2001-07-10
18
216 Views
Last Modified: 2007-12-19
I have a function that takes a compressed string, uncompresses it, and returns the uncompressed string.  The compression is very simple.  When 3 or more consecutive spaces or zeroes are encountered, they are removed and replaced with a flag (ASCII 126 for zeroes and ASCII 127 for spaces) and the binary number of spaces or zeroes.  All of this works properly.

My problem is that when I create an EXE, the program takes 2 to 3 times longer to uncompress the string than just running the program through the VB IDE.  Both are running the exact same code.

Any ideas on what the problem could be?  I can post the code if it will help.

0
Comment
Question by:brandonb
  • 6
  • 5
  • 4
  • +2
18 Comments
 
LVL 3

Expert Comment

by:jrspano
ID: 6270593
post the code.
0
 
LVL 2

Expert Comment

by:exelrud
ID: 6270620
Is this a function or do you create another process to handle the uncompression or do it on the idle time ?
0
 
LVL 1

Author Comment

by:brandonb
ID: 6270646
Here is the code.  One other thing to mention about the compression is that if there are ASCII characters > 123, the compression routine doubles them as a way to let the uncompression routine know that they are truly characters not flags.

This is a function that is called from a .BAS module.

Function Uncompress_String(TalkInputString As String)

    Dim Char As String
    Dim NextChar As String
    Dim Cntr As Integer

    Uncompress_String = ""
   
    For X = 1 To Len(TalkInputString)
        Char = Mid$(TalkInputString, X, 1)
        If Char > Chr$(123) Then
            NextChar = Mid$(TalkInputString, X + 1, 1)
        End If
       
        If Char > Chr$(123) And Char = NextChar Then
            Uncompress_String = Uncompress_String + Char
        Else
            If Char = Chr$(126) Or Char = Chr$(127) Then
                Cntr = Asc(NextChar)
                    If Char = Chr$(127) Then
                        Uncompress_String = Uncompress_String + String(Cntr, " ")
                    Else
                        Uncompress_String = Uncompress_String + String(Cntr, "0")
                    End If
                X = X + 1
            Else
                Uncompress_String = Uncompress_String + Char
            End If
        End If
       
    Next X
   
End Function
0
 
LVL 2

Expert Comment

by:exelrud
ID: 6270683
I do not like using X = X + 1 inside a for X
change the for X for a while just to be sure.
The compiler otimizations may conflict with what you're trying to do (skip a char)
0
 
LVL 2

Expert Comment

by:exelrud
ID: 6270685
Ooops.
Change the for into a While.
0
 
LVL 38

Expert Comment

by:PaulHews
ID: 6270835
This kind of manipulation would be a lot faster in a byte array.
0
 
LVL 1

Author Comment

by:brandonb
ID: 6270946
PaulHews,
I haven't ever used a byte array.  Could you give me an example?  Speed is of the utmost importance.  This is a piece of a communications package between a UNIX C program and a VB program.  Some of our sites use a 56K lease line.  We have experimented with gzip compression, but found this simple compression gives us the best combination of compression and processing time.  Anything that would speed up the compression/uncompression would be greatly appreciated.

exelrud,
I understand the concern with adding 1 to X, but would I not have the same problem running the program through the IDE?
0
 
LVL 2

Accepted Solution

by:
exelrud earned 100 total points
ID: 6270974
Maybe so, maybe not.
The debug environment may act in a different way then the compiled code.
It should behave the same but "should" and "does" and 2 different words...
0
 
LVL 38

Expert Comment

by:PaulHews
ID: 6271022
This is what I mean...  I can't really test this, so there may be bugs, but it is the broad idea of what I mean:

Function Uncompress_String(TalkInputString As String) As String

   Dim Char As Byte
   Dim NextChar As Byte
   Dim Cntr As Integer
   Dim bytInputString() As Byte
   Dim bytUncompressedString() As Byte  'Output string
   Dim intChunkSize As Integer  'used to allocate memory in 1K blocks (faster)
   Dim intCount As Integer  'incremented for each addition to output
   'AscII constants
   Const chSpace As Byte = 32
   Const chZero As Byte = 48
   
   intChunkSize = 1024
    bytInputString = StrConv(TalkInputString, vbFromUnicode)  'Convert string to bytes
   
'   Uncompress_String = ""
   intCount = 0
   
   For X = 1 To Len(TalkInputString)
       Char = bytInputString(i - 1) 'Mid$(TalkInputString, X, 1)
       If Char > 123 Then
           NextChar = bytInputString(i - 1) 'Mid$(TalkInputString, X + 1, 1)
       End If
       
       If Char > 123 And Char = NextChar Then
            'This code could go in a sub for readability, but a little faster inline.  :)
            intCount = intCount + 1
            If intCount > intChunkSize Then
                intChunkSize = intChunkSize + 1024
                ReDim Preserve bytUncompressedString(1 To intChunkSize)
            End If
            bytUncompressedString(intCount) = Char
           
           'Uncompress_String = Uncompress_String + Char
       Else
           If Char = 126 Or Char = 127 Then
               Cntr = NextChar
                    intCount = intCount + 1
                    If intCount > intChunkSize Then
                        intChunkSize = intChunkSize + 1024
                        ReDim Preserve bytUncompressedString(1 To intChunkSize)
                    End If
                   
                   If Char = 127 Then
                        bytUncompressedString(intCount) = chSpace
'                       Uncompress_String = Uncompress_String + String(Cntr, " ")
                   Else
                        bytUncompressedString(intCount) = chZero
'                       Uncompress_String = Uncompress_String + String(Cntr, "0")
                   End If
               X = X + 1
           Else
                intCount = intCount + 1
                If intCount > intChunkSize Then
                    intChunkSize = intChunkSize + 1024
                    ReDim Preserve bytUncompressedString(1 To intChunkSize)
                End If
                bytUncompressedString(intCount) = Char
'               Uncompress_String = Uncompress_String + Char
           End If
       End If
       
   Next X
   Uncompress_String = StrConv(bytUncompressedString, vbUnicode)   'Convert bytes back to string
   
End Function
0
IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 
LVL 38

Expert Comment

by:PaulHews
ID: 6271024
Commented out your code where mine was different...

This should perform significantly faster, especially if the strings are long.
0
 
LVL 38

Expert Comment

by:PaulHews
ID: 6271029
Found one bug already:

If Char > 123 Then
          NextChar = bytInputString(i) 'Mid$(TalkInputString, X + 1, 1)
      End If
0
 
LVL 1

Author Comment

by:brandonb
ID: 6271088
I'm going to give both of you points for your help.  exelrud seems to have solved my problem and I'm just beginning to test PaulHews code.
0
 
LVL 14

Expert Comment

by:wsh2
ID: 6271308
Built for speed.. <smile>

=====================================================
1. Start a New Standard.Exe Project.
2. Copy/Paste the following into the Form1 code window.
3. Press F8 to Run. The contents of strWork will appear in a MsgBox.

<----- Code Begin ----->
Option Explicit

Private Sub Form_Load()
   
   Dim strWork As String
   strWork = "a" & Chr(127) & Chr(12) & "b"
   MsgBox Uncompress_String(strWork)

End Sub

Function Uncompress_String(TalkInputString As String)

   Dim bytGet() As Byte: ReDim bytGet(Len(TalkInputString) * 1)
   Dim lngGet As Long: lngGet = 0
   Dim bytPut() As Byte: ReDim bytPut(Len(TalkInputString) * 2) ' Estimate
   Dim lngPut As Long: lngPut = 0
   Dim lngX As Long
   
   bytGet() = StrConv(TalkInputString & ":", vbFromUnicode)

   For lngGet = LBound(bytGet) To UBound(bytGet) - 1
      If (bytGet(lngGet) = 126 And bytGet(lngGet + 1) <> 126) _
      Or (bytGet(lngGet) = 127 And bytGet(lngGet + 1) <> 127) _
      Then
         For lngX = 1 To bytGet(lngGet + 1)
            Select Case bytGet(lngGet)
               Case 126
                  bytPut(lngPut) = Asc(" ")
               Case 127
                  bytPut(lngPut) = Asc("0")
            End Select
            lngPut = lngPut + 1
            If lngPut >= UBound(bytPut) Then
               ReDim Preserve bytPut(lngPut)
            End If
         Next lngX
         lngGet = lngGet + 1
      Else
         If bytGet(lngGet) > 123 And bytGet(lngGet) = bytGet(lngGet + 1) Then
            lngGet = lngGet + 1
         End If
         bytPut(lngPut) = bytGet(lngGet)
         lngPut = lngPut + 1
         If lngPut >= UBound(bytPut) Then
            ReDim Preserve bytPut(lngPut)
         End If
      End If
   Next lngGet
   
   ReDim Preserve bytPut(lngPut - 1)
   Uncompress_String = StrConv(bytPut(), vbUnicode)
   
End Function

<----- Code End ----->
0
 
LVL 1

Author Comment

by:brandonb
ID: 6274415
wsh2,
Your code works great except if I change anything after pasting the code in my program.  If I add some blank lines or realign the beginning of each line with the program, I receive the following error when I try to run the program.  Sometimes, when VB restarts, the error doesn't occur again, but other times it still does.  Any ideas?

The instruction at "0x0facb9ac" referenced memory at "0x00000000". The memory could not be "read".

Click on OK to terminate the program
Click on CANCEL to debug the program
0
 
LVL 14

Expert Comment

by:wsh2
ID: 6276449
brandonb..

It sounds like your copy of Visual Basic is corrupt.. <sigh>. You may want to consider reinstalling it and applying VB6 SP5 which you can get at this URL address:

http://msdn.microsoft.com/vstudio/sp/vs6sp5
0
 
LVL 1

Author Comment

by:brandonb
ID: 6294921
Thanks for help everyone.
0
 
LVL 38

Expert Comment

by:PaulHews
ID: 6294933
Ah.  Did you intentionally choose that answer, or was it a mistake.
0
 
LVL 1

Author Comment

by:brandonb
ID: 6294987
Intentionally.  exelrud's suggestion solved my original problem.

Check the question list.  There should be a "question" just for you for your help with the byte array.

BTW, the error I was receiving has something to do with the code not VB being corrupt.  I haven't had the time to narrow it down, but I modified PaulHews code and it works wonderfully.
0

Featured Post

Better Security Awareness With Threat Intelligence

See how one of the leading financial services organizations uses Recorded Future as part of a holistic threat intelligence program to promote security awareness and proactively and efficiently identify threats.

Join & Write a Comment

Introduction In a recent article (http://www.experts-exchange.com/A_7811-A-Better-Concatenate-Function.html) for the Excel community, I showed an improved version of the Excel Concatenate() function.  While writing that article I realized that no o…
The debugging module of the VB 6 IDE can be accessed by way of the Debug menu item. That menu item can normally be found in the IDE's main menu line as shown in this picture.   There is also a companion Debug Toolbar that looks like the followin…
Get people started with the process of using Access VBA to control Excel using automation, Microsoft Access can control other applications. An example is the ability to programmatically talk to Excel. Using automation, an Access application can laun…
This lesson covers basic error handling code in Microsoft Excel using VBA. This is the first lesson in a 3-part series that uses code to loop through an Excel spreadsheet in VBA and then fix errors, taking advantage of error handling code. This l…

757 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

20 Experts available now in Live!

Get 1:1 Help Now