 |
codemorphis.com Software development: pure and simple.
|
View previous topic :: View next topic |
Author |
Message |
waveterm
Joined: 12 Jan 2005 Posts: 21 Location: Berkeley, CA
|
Posted: Thu Feb 28, 2008 12:58 pm Post subject: String Tokenizer help needed |
|
|
I get an Index Out Of Range error with the GetToken method. I can't understand what's going on here. Anyone work this out? I'll attach a sample of the code if someone will tell me how. Thanks |
|
Back to top |
|
 |
CodeMorphis
Joined: 02 Dec 2003 Posts: 252
|
Posted: Thu Feb 28, 2008 1:27 pm Post subject: |
|
|
Can you please send your example to support@codemorphis.com? We'll investigate the problem.
Thanks,
CodeMorphis Support |
|
Back to top |
|
 |
waveterm
Joined: 12 Jan 2005 Posts: 21 Location: Berkeley, CA
|
Posted: Thu Feb 28, 2008 2:43 pm Post subject: |
|
|
sent |
|
Back to top |
|
 |
CodeMorphis
Joined: 02 Dec 2003 Posts: 252
|
Posted: Thu Feb 28, 2008 3:45 pm Post subject: |
|
|
Hi waveterm,
Thanks for sending in your example program.
The problem is not a bug but rather a misusage or programming error. The error message that you see is provided by Synopsis to help you identify the programming error.
Let’s look at your program:
In data port 0 of the String Tokenizer component named “Str Tok 1” you have supplied the input string to tokenize: “a:b:c:d” along with a separator character “:”. This means that you should have 4 tokens split by the component. So the input string “a:b:c:d” is stored in “Str Tok 1”.
The problem is that you are then using a new String Tokenizer component named “Str Tok 2” to try to retrieve the split tokens. This second component does not contain your input string and hence neither your expected tokens and so when you ask it for the Nth token in your For Loop, it will of course complain that the index is out of bounds since it has 0 tokens.
What you need to do is query “Str Tok 1”, which contains your input string. Note that the String Tokenizer component is an object component, as indicated by the green background. This means that the component maintains its own data in addition to providing one or more services. You can read about object components in the Help module, in Getting Started | Synopsis Components | Object Connections.
The way to interact with an object component and get to its data is via the Service Call component:
Note that we have replaced the component “Str Tok 2” with a Service Call component that refers to the first String Tokenizer component.
This now does what you want – you are passing the token index from the For Loop control into the Service Call component that acts as an interface to the “Str Tok 1” component.
You can download the corrected version of the program here:
http://www.codemorphis.com/articles/ans08/ans_022808/TokenIndex_Corrected.vpd
As an additional note, you have the number of tokens “hard-coded” into data port 1 of the For Loop component, meaning that you edited the port and put the value 4 there. This works fine for the input of your String Tokenized component “a:b:c:d” which has 4 tokens separated by the colon character. But if you were to change the input string to say “a:b:c:d:e” then you would have 5 tokens but your For Loop component still only loops 4 times. A better programming style would be to pass the output of the “Split String” service of the String Tokenizer component to the For Loop:
This way, your program will behave correctly when you change the input string.
Hope that this helps. |
|
Back to top |
|
 |
waveterm
Joined: 12 Jan 2005 Posts: 21 Location: Berkeley, CA
|
Posted: Thu Feb 28, 2008 7:59 pm Post subject: |
|
|
CodeMorphis wrote: |
In data port 0 of the String Tokenizer component named “Str Tok 1” you have supplied the input string to tokenize: “a:b:c:d” along with a separator character “:”. This means that you should have 4 tokens split by the component. So the input string “a:b:c:d” is stored in “Str Tok 1”.
The problem is that you are then using a new String Tokenizer component named “Str Tok 2” to try to retrieve the split tokens. This second component does not contain your input string and hence neither your expected tokens and so when you ask it for the Nth token in your For Loop, it will of course complain that the index is out of bounds since it has 0 tokens.
|
It will also curiously complain that it is out of bounds if you ask for the zeroth token.
CodeMorphis wrote: |
What you need to do is query “Str Tok 1”, which contains your input string. Note that the String Tokenizer component is an object component, as indicated by the green background. This means that the component maintains its own data in addition to providing one or more services. You can read about object components in the Help module, in Getting Started | Synopsis Components | Object Connections. |
O.K., I think my confusion has to do with the fact that I was able to create the object component StringTokenizer with the GetToken method. It seems to me that this object cannot be used for anything. That object has no data port for a string to get a token from, so I thought that it must relate to any StringTokenizer at the same nesting level! Does this object actually have a function, or is it some sort of residue from having that method available for use in a service call?
CodeMorphis wrote: |
The way to interact with an object component and get to its data is via the Service Call component:
Note that we have replaced the component “Str Tok 2” with a Service Call component that refers to the first String Tokenizer component.
This now does what you want – you are passing the token index from the For Loop control into the Service Call component that acts as an interface to the “Str Tok 1” component. |
Got it!
CodeMorphis wrote: |
As an additional note, you have the number of tokens “hard-coded” into data port 1 of the For Loop component, meaning that you edited the port and put the value 4 there. This works fine for the input of your String Tokenized component “a:b:c:d” which has 4 tokens separated by the colon character. But if you were to change the input string to say “a:b:c:d:e” then you would have 5 tokens but your For Loop component still only loops 4 times. A better programming style would be to pass the output of the “Split String” service of the String Tokenizer component to the For Loop: |
Yeah, it wasn't meant to be pretty or anything Just there to exercise the function a little, because I find it easier to comprehend a function when I see it iterate.
CodeMorphis wrote: |
Hope that this helps. |
It does! Thanks for the help. |
|
Back to top |
|
 |
CodeMorphis
Joined: 02 Dec 2003 Posts: 252
|
Posted: Thu Feb 28, 2008 8:18 pm Post subject: |
|
|
waveterm,
Quote: | It will also curiously complain that it is out of bounds if you ask for the zeroth token. |
That is because the component has no data, thus the message is normal and expected. Recall that the 0th index refers to the first token in the list kept as the indices are zero offsets.
Quote: | O.K., I think my confusion has to do with the fact that I was able to create the object component StringTokenizer with the GetToken method. It seems to me that this object cannot be used for anything. That object has no data port for a string to get a token from, so I thought that it must relate to any StringTokenizer at the same nesting level! Does this object actually have a function, or is it some sort of residue from having that method available for use in a service call? |
There is nothing that says that you are required to make the "Split String" service call to the String Tokenizer component first and then use the Service Call component to retrieve the tokens with the "Get Token" service, i.e. you could do the following:
Glad that this has helped you. Understandably, there are some new concepts to grasp but hopefully this all makes sense after the explanation and it helps you to develop/prototype what you need. |
|
Back to top |
|
 |
waveterm
Joined: 12 Jan 2005 Posts: 21 Location: Berkeley, CA
|
Posted: Fri Feb 29, 2008 5:46 pm Post subject: |
|
|
CodeMorphis wrote: | waveterm,
Quote: | O.K., I think my confusion has to do with the fact that I was able to create the object component StringTokenizer with the GetToken method. It seems to me that this object cannot be used for anything. That object has no data port for a string to get a token from, so I thought that it must relate to any StringTokenizer at the same nesting level! Does this object actually have a function, or is it some sort of residue from having that method available for use in a service call? |
There is nothing that says that you are required to make the "Split String" service call to the String Tokenizer component first and then use the Service Call component to retrieve the tokens with the "Get Token" service, i.e. you could do the following:
Glad that this has helped you. Understandably, there are some new concepts to grasp but hopefully this all makes sense after the explanation and it helps you to develop/prototype what you need. |
O.K., that helps.
Am I correct in the following understanding of your example?
First you instantiate the Get token object as Str Tok 1 and then you use the service call to the Get token (Str Tok 1) object. This works because the Get token object is initialized before run time and not the first time it is encountered in the chain. Essentially, you have to declare the object by adding it to the project and then you can make service calls. Correct?
I guess it would be cool procedurally if you could add the service call to the project as it appears in the flow and type in the name of the serviced object, thereby declaring it. Then when you come to adding the serviced object to the project, you could select its reference name from a list. |
|
Back to top |
|
 |
CodeMorphis
Joined: 02 Dec 2003 Posts: 252
|
Posted: Fri Feb 29, 2008 8:58 pm Post subject: |
|
|
Quote: | Am I correct in the following understanding of your example?
First you instantiate the Get token object as Str Tok 1 and then you use the service call to the Get token (Str Tok 1) object. This works because the Get token object is initialized before run time and not the first time it is encountered in the chain. Essentially, you have to declare the object by adding it to the project and then you can make service calls. Correct?
I guess it would be cool procedurally if you could add the service call to the project as it appears in the flow and type in the name of the serviced object, thereby declaring it. Then when you come to adding the serviced object to the project, you could select its reference name from a list. |
You can do that and you can also do what you asked for.
You can create a Service Call component and name it as desired and connect it in your program. You can then instantiate an object component such as the String Tokenizer component and edit the Service Call component to reference it.
An object component needs to exist in the program before it can be referenced by a Service Call component but it can be called in the program flow after referencing Service Call components. |
|
Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|