|
Hi Mark, > In RPG, this is ONE line of code! The SCAN opcode allows an array in the > result field. The (numeric, no decimals) array will be populated with all > the starting positions of the matches it finds. But that only does part of the job. It loads the positions of the delimiters into an array -- which I guess is useful (??) but doesn't extract the substrings from those positions. I do agree with you that it's not hard to do. In fact, that's why the fact that strtok() keeps coming up on this list tends to completely puzzle me. Strtok() isn't even a good function -- and it's REALLY EASY to write your own replacement for it. So why on earth are people trying to use strtok() in ILE RPG? There's gotta be some book or article that tells people to use strtok() to parse delimited fields or something that makes people keeping trying to use it when there are so many better alternatives. In many situations your SCAN solution will work -- but there are also situations where it won't. strtok(), strsep() and the gettok() subprocedure that I posted all allow you to specify multiple delimiters. That's not (easily) accomplished with SCAN or %scan(). Plus, the strtok(), strsep() and gettok() methods let you change delimiters on each call -- which you COULD do with SCAN or %scan if you called them in a loop, but not when you're returning an array. > > UNFORTUNATELY (DCR time?), this feature is only valid in fixed format! > But it may be worthwhile in order to avoid much more code. > I disagree. If the only thing you wanted to do was store locations in an array, then yes -- the SCAN op-code with an array output is a few lines shorter. But since you have to loop through the array to get any use of the results, it doesn't save you antyhing. Consider the following two programs. One outputs to an array and loops through it, the other uses the %scan() BIF. Notice that it's the exact same amount of code. The only difference is that the actual scanning gets moved into the loop: D string s 100A D len s 10I 0 D x s 10I 0 D lastpos s 10I 0 D pos s 10I 0 dim(50) D field s 52A 1 c eval string = 'Test||||||123|x|||8900' 2 c eval lastpos = 1 3 c '|' scan string pos 4 c for x = 1 to %elem(pos) 5 c if pos(x) = 0 6 c leave 7 c endif 8 c eval len = pos(x) - lastpos 9 c eval field = %subst(string:lastpos:len) 10 c field dsply 11 c eval lastpos = pos(x) + 1 12 c endfor c eval *inlr = *on D string s 100A D len s 10I 0 D lastpos s 10I 0 D pos s 10I 0 D field s 52A 1 c eval string = 'Test||||||123|x|||8900' 2 c eval lastpos = 1 3 c dou pos = 0 4 c eval pos = %scan('|': string: lastpos) 5 c if pos = 0 6 c leave 7 c endif 8 c eval len = pos - lastpos 9 c eval field = %subst(string:lastpos:len) 10 c field dsply 11 c eval lastpos = pos + 1 12 c enddo c eval *inlr = *on By contrast, the gettok() subprocedure that I posted earlier is 11 lines of code (not counting the D-specs, P-specs or /free, /end-free statements -- which I didn't count above, either) so it's actually shorter. Not only that, but it's reusable. You can put it into a service program and use it from anywhere. And, when you call it from your own programs, you can do so in only one line of code (assuming the output is an array) like this: field(*) = gettok(string : '|' : pos); So, I guess I don't agree with you that SCAN is a better solution (though, SCAN probably does perform better) But a more important point, that I think we do agree on, is that it's easy to do in RPG, and there are many different ways it can be done in RPG -- and all of them are better than strtok()!!
As an Amazon Associate we earn from qualifying purchases.
This mailing list archive is Copyright 1997-2024 by midrange.com and David Gibbs as a compilation work. Use of the archive is restricted to research of a business or technical nature. Any other uses are prohibited. Full details are available on our policy page. If you have questions about this, please contact [javascript protected email address].
Operating expenses for this site are earned using the Amazon Associate program and Google Adsense.