Как разобрать два символа за одну итерацию?

У меня есть письменный запрос на сопоставление двух символов и анализ данных, но я чувствую, что поступил неправильно. Позвольте мне поделиться с вами своей логикой

DEFINE VARIABLE I                   AS INTEGER   NO-UNDO.
DEFINE VARIABLE cData               AS CHARACTER NO-UNDO.
DEFINE VARIABLE cParsData           AS CHARACTER NO-UNDO.

ASSIGN
       cData = 'PRRSCLPP0123456789'.

DO I = 1 TO LENGTH(cData):

   cParsData = SUBSTRING(cData,I).
   IF cParsData MATCHES 'PP*' THEN MESSAGE SUBSTRING(cParsData,4,9).

END.

Как вы видите, то, как я поступил, неверно, и я думаю, что он анализирует каждый символ за итерацию, но мне нужно, чтобы он анализировал два символа за итерацию, чтобы мы могли сопоставить «PP». Вы можете поделиться или изменить логику для разных способов получения одного и того же результата


person Thiru    schedule 14.06.2019    source источник


Ответы (2)


Трудно представить причину, по которой нужно перебирать строку по одному символу за раз, ища "PP", а затем выплевывая символы с 4 по 13. Было бы намного проще сделать это:

define variable myData  as character no-undo.
define variable foundIt as integer   no-undo.

myData = "PRRSCLPP0123456789".

foundIt = index( myData, "PP" ).
if foundIt > 0 then 
  message substring( myData, 4, 9 ).

Если есть причина проходить эту строку по одному символу за раз, я думаю, что она не должна содержаться в вашем примере кода или вопросе.

Примечание: МАТЧИ «PP *» эквивалентны BEGINS «PP». В данном случае это не имеет большого значения, но без нужды бросать MATCHES при сравнении строк - плохая привычка. Особенно, если эта привычка заканчивается предложением WHERE. Использование MATCHES в предложениях WHERE вызовет сканирование таблицы. Это почти всегда плохая идея.

Если вы пытаетесь вывести N символов после позиции, в которой был найден "PP" (а не жестко запрограммированных с 4 по 13), вы должны сделать это так (при условии, что n = 9):

define variable myData  as character no-undo.
define variable foundIt as integer   no-undo.

myData = "PRRSCLPP0123456789".

foundIt = index( myData, "PP" ).
if foundIt > 0 then 
  message substring( myData, foundIt + 1, 9 ).
person Tom Bascom    schedule 14.06.2019
comment
Это, очевидно, лучшее решение по сравнению с итеративным методом. Я все еще очень изо всех сил пытаюсь понять реальную решаемую проблему. - person Jensd; 14.06.2019
comment
Я тоже озадачен этим. Если это действительно необходимо, причина (в настоящее время) не указана на этой странице. Единственное объяснение, которое я могу придумать, заключается в том, что, будучи новичком в программировании с помощью Progress, он не имел доступа к функциям, подобным INDEX (), и поэтому решил разделить строку по одному символу за раз. В старые добрые времена мы могли открыть Pocket Progress и легко найти подходящие функции. В дивном новом безбумажном мире не так-то просто искать вероятных подозреваемых;) - person Tom Bascom; 14.06.2019
comment
да. Отсутствие пространства имен и / или структурированной документации (здесь все о строках, здесь о числах и т. Д.). Также затрудняет понимание того, что доступно. - person Jensd; 14.06.2019

Я не совсем понимаю, что ты хочешь делать. Вы хотите найти строку и посмотреть, есть ли в ней «PP»? Тогда вам не нужно делать это в итерации. Просто

cData MATCHES "*PP*" скажет вам об этом.

Если «PP» является своего рода разделителем, и вы хотите что-то сделать с данными до и после, вы можете сделать:

DEFINE VARIABLE I                   AS INTEGER   NO-UNDO.
DEFINE VARIABLE cData               AS CHARACTER NO-UNDO .
DEFINE VARIABLE cParsData           AS CHARACTER NO-UNDO.

ASSIGN
   cData = 'PRRSCLPP0123456789'.

DO I = 1 TO LENGTH(cData):

    cParsData = SUBSTRING(cData,I, 2).
    IF cParsData = 'PP' THEN DO:
        DISPLAY 
            SUBSTRING(cData, i + 2)    FORMAT "x(20)" LABEL "After PP" 
            SUBSTRING(cData, 1, i - 1) FORMAT "x(20)" LABEL "Before PP".
    END.

END.

Это работает только для одного случая появления "PP" в строке. Вы должны попытаться лучше объяснить, что именно вам нужно.

Вы оставили намного больше информации в комментарии к другому ответу:  Комментарий

Если PP действительно всегда находится в позиции 10 (и 11) или 20 (и 21), и вам нужны только следующие 10 символов, вы можете сделать:

DEFINE VARIABLE cData1 AS CHARACTER NO-UNDO.
DEFINE VARIABLE cData2 AS CHARACTER NO-UNDO.
/* Position 10 and 11 */
cData1 = 'PRRSCLAAAPP0123456789'.
/* Position 20 and 21 */
cData2 = 'PRRSCLAAAPRRSCLAAAPP9876543210AA'.

FUNCTION parse  RETURNS CHARACTER 
    (INPUT cString AS CHARACTER ):
    IF INDEX(cString, "PP") > 0 THEN 
        RETURN SUBSTRING(cString, INDEX(cString, "PP") + 2, 10 ).
    ELSE 
        RETURN "".

END.

 MESSAGE cData1 " ->" parse(cData1) SKIP
         cData2 " ->" parse(cData2) VIEW-AS ALERT-BOX.
person Jensd    schedule 14.06.2019
comment
Thx Man. Также работает: разве мы не называем цикл DO как итерацию? Как вы знаете, каждый раз значение «I» изменяется в зависимости от длины cData. Итак, я подумал, что мы можем назвать эту итерацию, и именно об этом я упомянул. Поправьте меня, если я ошибаюсь - person Thiru; 14.06.2019
comment
cParsData = SUBSTRING(cData,I, 2) смотрит на 2 байта на итерацию с увеличением i, поэтому первая итерация смотрит на позиции 1 и 2, вторая итерация 2 и 3 и т. Д. Если это то, что вам нужно сделать, а не просто увидеть, что PP находится в строке, вам нужно вид итерации да. - person Jensd; 14.06.2019
comment
Обновил мой ответ, чтобы отразить фиксированные позиции, упомянутые в комментарии к другому ответу. - person Jensd; 14.06.2019
comment
Привет, Дженсд, Спасибо, это то, что я ищу ... и извините за мои плохие знания, потому что я молод и нахожусь на начальном этапе, чтобы узнать все шаг за шагом - person Thiru; 16.06.2019