View previous topic :: View next topic
|
Author |
Message |
Narmadha Krishnamurthy
New User
Joined: 19 Aug 2008 Posts: 8 Location: Chennai
|
|
|
|
Hello,
I am a novice to REXX and I am trying to automate a routine task. Here's my problem :
I have a huge record of 2000 bytes which has an array starting position 500 and ending at position 1500. The array stores 200 strings of 4 bytes each, in sorted order by spaces (AAB1 ABC3 ACR2 ADE1 etc). The purpose of my macro is, when given a particular string, I should be able to find the position of the string in the input file and insert it there. I don't want to edit the same file. I just want to find the position and write it along with the other strings to an output file.
I thought I could read the file, move all the records to a stem, then access the array starting position 500, move it to another stem, access the strings one by one and compare against the string I have, when I find a string that is greater than the one I have, say at i th position, I could move the string to i+1 th position, move my string to i th position and write the data to the output file.
Here is where I am:
As the first step, I wrote the following small piece of macro, to check if I am able to access the records of the input file using a stem:
Code: |
/*Rexx*/
Address TSO
"ALLOC FILE(myindd) DA('T.INPT') SHR"
"EXECIO * DISKR myindd (STEM INPTrec."
"Free F(myindd)"
do
i = 1 TO INPTrec.0
say INPTrec.i
end |
and I get the following error message:
FILE MYINDD NOT FREED, DATA SET IS OPEN
INPTREC.1 TO 1060
***
I guess my bookish knowledge isn't helping here. Please bear with me if my mistakes are absurd and kindly let me know if my approach will work. Any advice on the code is most welcome.
Thank you in anticipation! |
|
Back to top |
|
|
expat
Global Moderator
Joined: 14 Mar 2007 Posts: 8797 Location: Welsh Wales
|
|
|
|
try changing
Code: |
"EXECIO * DISKR myindd (STEM INPTrec." |
to
Code: |
"EXECIO * DISKR myindd (STEM INPTrec. FINIS" |
|
|
Back to top |
|
|
Narmadha Krishnamurthy
New User
Joined: 19 Aug 2008 Posts: 8 Location: Chennai
|
|
|
|
Hello Expat,
I still don't get the display I am hoping to see...I get the following display
INPTREC.1 TO 10
***
I thought my piece of code will display the records one by one from the Input file. Am I wrong in my understanding? |
|
Back to top |
|
|
Marso
REXX Moderator
Joined: 13 Mar 2006 Posts: 1353 Location: Israel
|
|
|
|
Two small modifications to your REXX:
1. FINIS added to the EXECIO command.
2. "do i=" on one line (otherwise they are 2 different commands).
Code: |
/*Rexx*/
Address TSO
"ALLOC FILE(myindd) DA('T.INPT') SHR"
"EXECIO * DISKR myindd (FINIS STEM INPTrec."
"Free F(myindd)"
do i = 1 TO INPTrec.0
say INPTrec.i
end |
I wouldn't work with a stem for the array, as there is no function to insert an item in the middle of a stem.
Instead, I would use something like that:
Code: |
PARSE VAR INPTrec.I 1 LeftSide 500 TheList 1501 RightSide
Do Disp = 1 By 5
TheWord = Substr(TheList,Disp,4)
If TheWord = '' Then Leave
If TheWord > MyNewWord Then Leave
End
TheList = Insert(MyNewWord,TheList,Disp,5)
OUTrec.I = LeftSide || Left(TheList,1000) || RightSide |
I haven't tested this piece of art, you will have to do some debugging.
Learn about the functions, test them with TRACE and come back to tell us how you succeeded. |
|
Back to top |
|
|
Pedro
Global Moderator
Joined: 01 Sep 2006 Posts: 2547 Location: Silicon Valley
|
|
|
|
The open dataset is probably from an earlier open and read. It is hard to close it by running the exec a second time. Trying logging on again. |
|
Back to top |
|
|
Narmadha Krishnamurthy
New User
Joined: 19 Aug 2008 Posts: 8 Location: Chennai
|
|
|
|
Hello Marso,
Thank you for your kind help! All your corrections worked and your logic had hit the bull's eye! It was a fine piece of art!
So here is the code that works
Code: |
/*Rexx*/
Address TSO
"ALLOC FILE(myindd) DA('T.INPUT') SHR"
"ALLOC FILE(myoutdd) DA('T.OUTPUT') SHR"
"EXECIO * DISKR myindd (FINIS STEM INPTrec."
"Free F(myindd)"
Say 'Enter the string to be added'
Pull Newstr
do i = 1 TO INPTrec.0
PARSE VAR INPTrec.i 1 Leftside 501 oldstr 1501 Rightside
Do disp = 1 by 5 until oldstr = ' '
Opt = substr(oldstr,disp,4)
If oldstr = ' ' Then Leave
If oldstr < Newstr Then nop
If oldstr > Newstr Then Leave
end
If oldstr > Newstr Then
disp = disp - 1
oldstr = Insert(Newstr,oldstr,disp,5)
outrec.I = Leftside||Left(oldstr,1000)||Rightside
"EXECIO * DISKW myoutdd (FINIS STEM outrec."
end
"Free F(myoutdd)" |
Code'd
The only thing that is running in my mind is that, if I try to loop the code (like a recursive call based on a user reply) for adding multiple strings, this doesn't work. Any advice for the looping idea?
Once again, Many Thanks! |
|
Back to top |
|
|
Marso
REXX Moderator
Joined: 13 Mar 2006 Posts: 1353 Location: Israel
|
|
|
|
- You're welcome.
- I think you got mixed with Opt and oldstr when you copied your program.
- Although your program works, there is still one big bug:
The EXECIO * DISKW is located within the loop. It means you update the 1st line, rewrite the whole file, update the 2nd line, rewrite the whole file... and so on.
- When posting on the forum, always use BBCode.
This will keep the indentation you use in your programs and make bugs like this one easier to spot.
Now, about your other question,
The trick is to split the logic into smaller blocks.
Look at this:
Code: |
Say 'Enter the string to be added'
Pull Newstr
do i = 1 TO INPTrec.0
PARSE VAR INPTrec.i 1 Leftside 501 oldstr 1501 Rightside
Call Process_One_Rec
outrec.I = Leftside||Left(oldstr,1000)||Rightside
end
EXECIO...
FREE...
Exit
Process_One_Rec:
Do disp = 1 by 5 until opt = ' '
Opt = substr(oldstr,disp,4)
If opt = ' ' Then Leave
If opt < Newstr Then nop
If opt > Newstr Then Leave
end
If opt > Newstr Then
disp = disp - 1
oldstr = Insert(Newstr,oldstr,disp,5)
Return
|
It is almost the same code as you wrote but...
now you want multiple strings ? No problem!
Code: |
Say 'Enter many strings to be added'
Pull NewstrList
Strmax = Words(NewstrList)
do i = 1 TO INPTrec.0
PARSE VAR INPTrec.i 1 Leftside 501 oldstr 1501 Rightside
Do Mult = 1 to Strmax
Newstr = Word(NewstrList,Mult)
Call Process_One_Rec
end
outrec.I = Leftside||Left(oldstr,1000)||Rightside
end
EXECIO...
FREE...
Exit
|
Again, I didn't validate this code. |
|
Back to top |
|
|
Narmadha Krishnamurthy
New User
Joined: 19 Aug 2008 Posts: 8 Location: Chennai
|
|
|
|
Hello Marso,
Thank you again for the reply...Sorry about the Opt and Old str...I had to give different terms while pasting it here....will certainly use BBC code from now on.
Please clarify just one little thing in your code..
For adding multiple strings, what does the variable Newstrlist indicate? list of strings delimited by spaces?
Thanks and Regards,
Narmadha |
|
Back to top |
|
|
Marso
REXX Moderator
Joined: 13 Mar 2006 Posts: 1353 Location: Israel
|
|
|
|
Yes, it is a list of strings delimited by spaces
for each record, you insert the words one by one into the array.
Don't give up reading the REXX reference books.
I still do (and I wrote my first rexx program around 1984...) |
|
Back to top |
|
|
Narmadha Krishnamurthy
New User
Joined: 19 Aug 2008 Posts: 8 Location: Chennai
|
|
|
|
Hello Marso,
It is such an honour to be able to contact veterans like you on these forums. Very kind of you to help novices like me!
And yes, your code doesn't have to be tested. You seem to auto-run the code while writing
I will certainly follow your advice and keep reading as much Rexx manuals as possible.
Many Thanks for your kind help!
Regards,
Narmadha |
|
Back to top |
|
|
Pedro
Global Moderator
Joined: 01 Sep 2006 Posts: 2547 Location: Silicon Valley
|
|
|
|
Quote: |
I still do (and I wrote my first rexx program around 1984...) |
And that is about the time that rexx came out on MVS! |
|
Back to top |
|
|
|