loopsdo-loopsrexxoorexx

Stop Rexx Do Loop from Exiting


For some reason my Rexx loop breaks and I don't know why. I'm trying to search a phone number database by ICCID (The identification number for sim cards) and pull the phone number. Here's the loop I have, a little simplified:

(t) is the tab hex code, ICCIDlist.txt contains a list of ICCIDs I'm trying to gather info on
and phonenumberinfo.txt an exhaustive list of ICCIDs and Phone Numbers, looking something like this:
89298374987   409-392-2434
89298765345   409-365-2132
89298334745   409-967-2863

----------------------------------------------

streamICCID=.stream~new('iccidList.txt')
  lni = streamICCID~lines
DO i = 1 to lni
  ICCID.i = streamICCID~linein(i)
END

soFile=.stream~new('phonenumberinfo.txt')
  lno = soFile~lines
DO line = 1 to lno
  lnInfo = soFile~linein(line)
  lnFind = POS(ICCID.i,lnInfo)
    IF lnFind==1 THEN DO
    PARSE VAR lnInfo ICCID (t) ownNum.i
    i = i + 1; ITERATE
    END
    ELSE ITERATE
END

DO n = 1 to i
  SAY ownNum.n
END

It works for the first one, but as soon as it pulls a phone number from the first ICCID it breaks. I need it to continue until it's done all of the ICCIDs. can anyone help me out?


Solution

  • You're right, this will only work when searching for one ICCID - the last one. As NicC says, you'd probably figure that out if you put a Trace Intermediate (or just Trace I) instruction right before your do line = ... loop. Doing so would show you that you're entering that loop with i set to the number of the last ICCID you read, and you're counting up from there (i=i+1; ITERATE).

    In other languages, this sort of searching problem is usually solved with two nested loops. After loading the first dataset, you iterate over the second, and for each record, you iterate over the entire first dataset, checking for a match. You're not doing that, you're hand-writing the inner loop, and you're using its index variable (i) for two different and conflicting purposes (iterating over the first dataset and creating the output dataset).

    In Rexx, we wouldn't do that (athough we could). We'd solve this instead by loading the first dataset into an associative array, and then directly accessing it while iterating over the second dataset. That turns an order N-squared algorithm into order N, for a big win.

    /* Load the ICCIDs into the "ICCID.*" associative array.  The value of
       each element we load is TRUE, and the value of anything else is FALSE.
     */
    ICCIDlist. = 0  /* Set all the elements to FALSE */
    streamICCID=.stream~new('iccidList.txt')
    DO i = 1 to streamICCID~lines
      item = streamICCID~linein(i)
      ICCIDlist.item = 1  /* Set this element to TRUE */
    END
    
    /* Search the phone number file for ICCIDs we loaded above and record their presence. */
    soFile=.stream~new('phonenumberinfo.txt')
    lno = 0
    DO line = 1 to soFile~lines
      lnInfo = soFile~linein(line)
      PARSE VAR lnInfo ICCID (t) phoneNumber
      IF ICCIDlist.ICCID THEN DO  /* If the ICCIDlist element is TRUE, it was in the first dataset */
        lno = lno + 1
        ownNum.lno = phoneNumber
      END
    END
    
    /* Write out the phone numbers for the ICCIDs that we found in both datasets. */
    DO n = 1 to lno
      SAY ownNum.n
    END