[英]How to find the index of the string separated by delimeters in progress openedge 4gl?
I want to find the index of 56 in "STS++5623+56+ 123 " . 我想在“ STS ++ 5623 + 56 + 123”中找到索引56。 The code I have written gives me 6 (of 5623) but I need 11. 我编写的代码给了我6个(5623个),但是我需要11个。
DEFINE var v-segment as longchar no-undo.
DEFINE VARIABLE v-element AS CHARACTER NO-UNDO.
ASSIGN v-segment = "STS++5623+56".
ASSIGN v-element = "56".
define variable v-index as integer no-undo.
v-index = index(v-segment , v-element , 1).
MESSAGE v-index
VIEW-AS ALERT-BOX INFO BUTTONS OK.
Sorry the previous answer wasn't what you needed. 抱歉,上一个答案不是您所需要的。 I decided to leave it up, because it is a nice solution to the problem as stated. 我决定将其保留,因为它可以很好地解决上述问题。 But I'll try again. 但我会再试一次。 I made the check for delimiters a separate function so you can easily adapt it to your requirements. 我将分隔符检查设为单独的功能,因此您可以轻松地将其适应您的要求。 Adding multi-byte character capabilities should be straightforward. 添加多字节字符功能应该很简单。
DEFINE VARIABLE v-segment AS LONGCHAR NO-UNDO.
DEFINE VARIABLE v-element AS CHARACTER NO-UNDO.
DEFINE VARIABLE v-delims AS CHARACTER NO-UNDO.
DEFINE VARIABLE v-index AS INTEGER NO-UNDO.
DEFINE VARIABLE v-delimCount AS INTEGER NO-UNDO.
DEFINE VARIABLE v-segLength AS INTEGER NO-UNDO.
DEFINE VARIABLE v-eltLength AS INTEGER NO-UNDO.
DEFINE VARIABLE v-psn AS INTEGER NO-UNDO.
ASSIGN v-segment = "STS++5623+56"
v-element = "56"
v-delims = "+:"
/* For efficiency, don't calculate these inside your loop */
v-seglength = LENGTH( v-segment)
v-eltLength = LENGTH( v-element)
v-delimCount = LENGTH( v-delims).
/*
** isDelin()
** Is character at specified positiion one of the delimiters?
**
** Params:
** CHARACTER p-str - string to search
** INTEGER p-psn - position to check
** CHARACTER p-delims - list of delimiters to check for
**
** Returns TRUE if character at specified position is a delimiter
** Otherwise, returns FALSE
*/
FUNCTION isDelim RETURNS LOGICAL (
INPUT p-str AS LONGCHAR,
INPUT p-psn AS INTEGER,
INPUT p-delims AS CHARACTER
):
/* You might want parameter checking here.... */
RETURN INDEX( p-delims, SUBSTRING( p-str, p-psn, 1)) > 0.
END FUNCTION. /* isDelim */
/*
** You might want special case handling here:
** if v-eltLength = 0 then v-index = 1. return.
** IF v-element = ? or v-segment = ? then v-index = 0. return.
*/
/* Look for v-element, then see if it is surrounded by delimiters */
v-index = 0.
DO WHILE TRUE:
v-index = INDEX( v-segment, v-element, v-index + 1).
If v-index = 0 THEN LEAVE. /* No more matches */
/*
** Found a match. Is it preceded by a delimiter?
** (Don't check if match is at beginning of string.)
*/
v-psn = v-index - 1.
IF v-psn > 0 AND NOT isDelim( v-segment, v-psn, v-delims) THEN NEXT.
/*
** Is match followed by a delimiter?
** (Don't check if match is at end of string.)
*/
v-psn = v-index + v-eltLength.
IF v-psn > v-seglength THEN LEAVE.
IF NOT isDelim(v-segment, v-psn, v-delims) THEN NEXT.
/* Success! */
LEAVE.
END.
MESSAGE v-index VIEW-AS ALERT-BOX INFO BUTTONS OK.
DEFINE var v-segment as longchar no-undo.
DEFINE VARIABLE v-element AS CHARACTER NO-UNDO.
def var v-i as int no-undo.
def var v-data as char no-undo.
ASSIGN v-segment = "STS++5623+56+123".
ASSIGN v-element = "56".
define variable v-index as integer no-undo.
do v-i = 1 to num-entries(v-segment,"+"):
if entry(v-i,v-segment,"+") = v-element then
do:
v-data = entry(v-i,v-segment,"+").
MESSAGE v-data VIEW-AS ALERT-BOX INFO BUTTONS OK.
end.
end.
There are several ways to approach this. 有几种方法可以解决此问题。 Which is smartest depends upon the data. 哪一个最聪明取决于数据。 I can think of two that do not involve loops, which may be what you are looking for. 我可以想到两个不涉及循环的问题,这可能正是您要寻找的。 I haven't done any benchmarking, but I think the code below would is the most efficient algorithm. 我尚未进行任何基准测试,但我认为下面的代码将是最有效的算法。 At most it involves three string searches -- one entry()
, one num-entries()
, and one index()
. 最多包含三个字符串搜索-一个entry()
,一个num-entries()
和一个index()
。 If this doesn't meet your needs, I can suggest alternatives. 如果这不能满足您的需求,我可以建议其他方法。
DEFINE VARIABLE v-segment AS LONGCHAR NO-UNDO.
DEFINE VARIABLE v-element AS CHARACTER NO-UNDO.
DEFINE VARIABLE v-index AS INTEGER NO-UNDO.
DEFINE VARIABLE v-entry AS INTEGER NO-UNDO.
DEFINE VARIABLE v-delim AS CHARACTER NO-UNDO.
ASSIGN v-segment = "STS++5623+56"
v-element = "56"
v-delim = "+".
/* Does the segment contain the exact entry? */
v-entry = LOOKUP(v-element, v-segment, v-delim).
/*
** If entry number = 0, then element is not found
** If entry number = 1, then element is at beginning of segment.
** If entry number = num-entries(), then element is at end of segment
** Otherwise, element is in the middle; just search for it surrounded
** by delimters.
*/
IF v-entry = 0 THEN
v-index = 0.
ELSE IF v-entry = 1 THEN
v-index = 1.
ELSE IF v-entry = NUM-ENTRIES( v-segment, v-delim) THEN
v-index = R-INDEX( v-segment, v-delim) + 1.
else
v-index = INDEX( v-segment, v-delim + v-element + v-delim) + 1.
MESSAGE v-index VIEW-AS ALERT-BOX INFO BUTTONS OK.
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.