INTELLIGENT WORK FORUMS FOR COMPUTER PROFESSIONALS
Come Join Us!
Are you a Computer / IT professional? Join Tek-Tips now!
- Talk With Other Members
- Be Notified Of Responses
To Your Posts
- Keyword Search
- One-Click Access To Your
Favorite Forums
- Automated Signatures
On Your Posts
- Best Of All, It's Free!
*Tek-Tips's functionality depends on members receiving e-mail. By joining you are opting in to receive e-mail.
Partner With Us!
"Best Of Breed" Forums Add Stickiness To Your Site

(Download This Button Today!)
Feedback
"...Praise should be given to the Forum managers or the Tipmasters - they are what make it work - give them extra recognition!!! They are timely (prompt - unlike ACTUAL support sites) and on the ball!!!..."
Geography
Where in the world do Tek-Tips members come from?
|
Removing spaces form a Message
|
|
I have a i/p message line,consisting of some writing,some nos.etc. Now, anywhere in the msg there can be more than one space. I want to remove the spaces to one space if the spaces are not at starting,or if its at staring then I dont need any space. for eg. 'a/c balace is $200.00 name is smith' sholud be ''a/c balace is $200.00 name is smith' and if ' 'a/c balace is $200.00',I need it to be 'a/c balace is $200.00' Please suggest me a way out. |
|
...or have a look at the INSPECT statement to replace two spaces by one. If you want to replace multiple spaces by one you could use INSPECT in a loop. |
|
How to use the INSPECT loop? can u write a scribble that?it would b helpful... |
|
|
mikrom (Programmer) |
23 Dec 08 11:43 |
INSPECT has REPLACING, CONVERTING and TALYING, but with REPLACING you can replace only some definite characters with another, e.g. INSPECT MY-STRING REPLACING ALL 'XY' BY 'AB' or CODEINSPECT MY-STRING REPLACING ALL SPACE BY '*' But then you will get for example instead of CODE'a/c balace is $200.00 name is smith' this CODE'a/c*balace*is*$200.00******name****is****smith' and this si not, what we need - we want reduce all spaces to one space only. I don't know if this can be done simply with INSPECT, but instead of exploring the INSPECT alchemy you can code your own algorithm, like this CODE IDENTIFICATION DIVISION. PROGRAM-ID. RMVSPACES. AUTHOR. MIKROM. ENVIRONMENT DIVISION.
DATA DIVISION. WORKING-STORAGE SECTION. 01 MY-INPUT-STRING PIC X(200) VALUE 'a/c balace is $200.00 name is smith'. 01 MY-OUTPUT-STRING PIC X(200).
01 WS-FIELDS. 05 WS-DATA PIC X(200). 05 WS-DATA-LENGTH PIC 9(3). 05 X PIC 9(3). 05 J PIC 9(3). 05 K PIC 9(3). 05 N PIC 9(3). 05 S PIC 9(3).
PROCEDURE DIVISION. MAIN. INITIALIZE WS-FIELDS
MOVE MY-INPUT-STRING TO WS-DATA PERFORM COMPUTE-LENGTH-OF-THE-DATA DISPLAY 'MY-INPUT-STRING = ' QUOTE MY-INPUT-STRING(1:WS-DATA-LENGTH) QUOTE END-DISPLAY DISPLAY 'LENGTH OF STRING = ' WS-DATA-LENGTH
PERFORM FORMAT-STRING-WITH-SPACES
PERFORM COMPUTE-LENGTH-OF-THE-DATA MOVE WS-DATA TO MY-OUTPUT-STRING DISPLAY 'MY-OUTPUT-STRING = ' QUOTE MY-OUTPUT-STRING(1:WS-DATA-LENGTH) QUOTE END-DISPLAY DISPLAY 'LENGTH OF STRING = ' WS-DATA-LENGTH
* End GOBACK .
COMPUTE-LENGTH-OF-THE-DATA. COMPUTE X = 0. INSPECT FUNCTION REVERSE(WS-DATA) TALLYING X FOR LEADING SPACES. COMPUTE WS-DATA-LENGTH = LENGTH OF WS-DATA - X .
FORMAT-STRING-WITH-SPACES. MOVE WS-DATA-LENGTH TO N PERFORM VARYING J FROM 1 BY 1 UNTIL J > N IF WS-DATA(J : 1) = SPACE AND WS-DATA(J + 1 : 1) = SPACE COMPUTE J = J + 1 MOVE J TO K * S - number of superfluous Spaces INITIALIZE S * Search from position J+1 for Not-Space-Characters PERFORM UNTIL WS-DATA(K:1) NOT = SPACE ADD 1 TO K ADD 1 TO S END-PERFORM * Shift substring left from position K to J MOVE WS-DATA(K : N - K + 1) TO WS-DATA(J : N - K + 1) * Adjust new length COMPUTE N = N - S * Clear last characters in String MOVE SPACE TO WS-DATA(N + 1 : S) END-IF END-PERFORM MOVE N TO WS-DATA-LENGTH . Output CODE> call rmvspaces MY-INPUT-STRING = 'a/c balace is $200.00 name is smith' LENGTH OF STRING = 046 MY-OUTPUT-STRING = 'a/c balace is $200.00 name is smith' LENGTH OF STRING = 035 |
|
@mikrom: you're right of course. INSPECT ... REPLACING cannot be used in this case. |
|
I have a subroutine in COBOL which does three things with a string of up to 999 bytes: 1), converts the case to upper, lower or title (or no conversion), 2) Justifies the string left, right or center (or no justification), 3) tests the string for caracters outside the range of 32 (space) through 126 (~), or 0-9, A-Z. |
|
Since we're posting programs now: CODE IDENTIFICATION DIVISION. PROGRAM-ID. REMSPACES. ENVIRONMENT DIVISION. DATA DIVISION. WORKING-STORAGE SECTION. 01 INPUT-VARIABLES. 04 INPUT-STRING1 PIC X(80) VALUE "a/c balace is $200.00 name is smith". 04 INPUT-STRING2 PIC X(80) VALUE " a/c balace is $200.00". 01 PROCESSING-VARIABLES. 04 PROC-STRING PIC X(80). 04 PARTS-WHOLE. 08 PARTS-TABLE PIC X(20) OCCURS 9 TIMES INDEXED BY PARTS-NDX. 04 SPACE-COUNT PIC S9(4) BINARY. 01 OUTPUT-VARIABLES. 04 OUTPUT-STRING PIC X(80).
PROCEDURE DIVISION. 0000-MAIN SECTION. MOVE INPUT-STRING1 TO PROC-STRING. DISPLAY " INPUT: " PROC-STRING. PERFORM 1000-PROC-STR. DISPLAY "OUTPUT: " OUTPUT-STRING. DISPLAY " ".
MOVE INPUT-STRING2 TO PROC-STRING. DISPLAY " INPUT: " PROC-STRING. PERFORM 1000-PROC-STR. DISPLAY "OUTPUT: " OUTPUT-STRING. DISPLAY " ".
GOBACK.
1000-PROC-STR SECTION. * INITIALIZE VARIABLES. MOVE 0 TO SPACE-COUNT. MOVE SPACES TO PARTS-WHOLE. MOVE SPACES TO OUTPUT-STRING. * REMOVE LEADING SPACES INSPECT PROC-STRING TALLYING SPACE-COUNT FOR LEADING SPACES. MOVE PROC-STRING (SPACE-COUNT + 1:80) TO PROC-STRING. * UNSTRING DATA UNSTRING PROC-STRING DELIMITED BY ALL SPACES INTO PARTS-TABLE (1) PARTS-TABLE (2) PARTS-TABLE (3) PARTS-TABLE (4) PARTS-TABLE (5) PARTS-TABLE (6) PARTS-TABLE (7) PARTS-TABLE (8) PARTS-TABLE (9) END-UNSTRING. * STRING DATA BACK STRING PARTS-TABLE (1) DELIMITED BY SPACES SPACE DELIMITED BY SIZE PARTS-TABLE (2) DELIMITED BY SPACES SPACE DELIMITED BY SIZE PARTS-TABLE (3) DELIMITED BY SPACES SPACE DELIMITED BY SIZE PARTS-TABLE (4) DELIMITED BY SPACES SPACE DELIMITED BY SIZE PARTS-TABLE (5) DELIMITED BY SPACES SPACE DELIMITED BY SIZE PARTS-TABLE (6) DELIMITED BY SPACES SPACE DELIMITED BY SIZE PARTS-TABLE (7) DELIMITED BY SPACES SPACE DELIMITED BY SIZE PARTS-TABLE (8) DELIMITED BY SPACES SPACE DELIMITED BY SIZE PARTS-TABLE (9) DELIMITED BY SPACES SPACE DELIMITED BY SIZE INTO OUTPUT-STRING END-STRING. Output is: CODE Input: a/c balace is $200.00 name is smith Output: a/c balace is $200.00 name is smith Input: a/c balace is $200.00 Output: a/c balace is $200.00 Measurement is not management. |
|
The output got mangled somewhere between copying and posting, it shouldn't have those additional lines. Measurement is not management. |
|
|
mikrom (Programmer) |
25 Dec 08 9:17 |
Hi Glenn9999, Before I wrote the piece of code I posted above, I tried it first to solve with UNSTRING but I used probably DELIMITED BY SPACE instead of DELIMITED BY ALL SPACES and so I got in end effect what I don't expected - a space in some table elements.  But the disadvantage with using STRING and UNSTRING is, that you need to know maximal possible number of words in the string. |
|
|
razalas (Programmer) |
7 Jan 09 12:44 |
anirbancthis subject has been dealt with numerous times in this forum. If you do a Search (see tab at top of this message thread, right next to Forum) for UNSTRING you will find many useful threads dealing with this topic. mikromQuote (mikrom):the disadvantage with using STRING and UNSTRING is, that you need to know maximal possible number of words in the string.
I disagree. You only need to know the maximum length of any input string you wish to handle. You can do it with 3 areas (input, temporary holding, output) where the temp and output areas are at least as large as the input field. CODE MOVE SPACES TO OUTDATA MOVE 1 TO POS-OUT MOVE 1 TO POS-IN PERFORM WITH TEST AFTER UNTIL POS-IN >= LENGTH OF INDATA OR POS-OUT >= LENGTH OF OUTDATA OR TEMP (1:LEN) = SPACES UNSTRING INDATA DELIMITED BY ALL SPACES OR ALL TAB-CHAR OR ALL LINE-FEED OR ALL FORM-FEED INTO TEMP DELIMITER IN DLM COUNT IN LEN POINTER POS-IN END-UNSTRING IF LEN > ZERO IF POS-OUT + LEN + 1 >= LENGTH OF OUTDATA PERFORM DISPLAY-OUTDATA END-IF STRING TEMP (1:LEN) DELIMITED BY SIZE DLM DELIMITED BY SIZE INTO OUTDATA POINTER POS-OUT END-STRING ELSE MOVE HIGH-VALUES TO TEMP MOVE 1 TO LEN END-IF END-PERFORM . * DISPLAY-OUTDATA. ADD 1 TO LINE-OUT DISPLAY OUTDATA LINE LINE-OUT POSITION COL-OUT MOVE SPACES TO OUTDATA MOVE 1 TO POS-OUT . Code what you mean, and mean what you code! But by all means post your code!
Razalas |
|
|
mikrom (Programmer) |
7 Jan 09 15:02 |
Hi razalas, Thanks for the suggestions. Your code is very interesting, for example I have never seen using OR with DELIMITED before. But I need to compile and debug your code, so I understand it better - if I only look at it now, it seems to be complicated for me |
|
|
razalas (Programmer) |
7 Jan 09 15:49 |
mikrom, sorry I was/am a bit rushed when I responded earlier so I didn't post the full program. It might be easier to understand if I put the working storage out there too. I'll try to do tonight after I get home. I was hoping the procedure division would be enough to shed some light on how to do this if you don't know in advance how many individual words you might have to expect. Code what you mean, and mean what you code! But by all means post your code!
Razalas |
|
|
mikrom (Programmer) |
7 Jan 09 16:38 |
razalas, It's not a big problem for me to add the working storage to the procedure division you posted here. But I don't have the COBOL compiler at my hands now, because here in Europe it's about 22.35 and I'm at home. I only have COBOL compiler at my work, so I can try your example first tomorrow.  But if you want to post the complete example it would be easier. |
|
I think your making this harder than it is. Tom CODE 000010**PROGRAM1 000020 IDENTIFICATION DIVISION. 000030 PROGRAM-ID. Program1 AS "Debug_Cobol_Applications_General.Program1". 000040 DATA DIVISION. 000050 WORKING-STORAGE SECTION. 000060 01 SUB1 PIC 999 VALUE 1. 000070 01 SUB2 PIC 999 VALUE 1. 000080 01 INPUT-DATA. 000090 05 FILLER PIC X(100) VALUE 000100 "THIS IS A TEST ". 000110 01 OUTPUT-DATA PIC X(100) VALUE SPACES. 000120 000130 PROCEDURE DIVISION. 000140 START-IT-ALL1. 000150 MOVE INPUT-DATA(SUB1:1) TO OUTPUT-DATA(SUB2:1) 000160 PERFORM 000170 VARYING SUB1 FROM 2 BY 1 000180 UNTIL SUB1 > 100 OR INPUT-DATA(SUB1:) = SPACES 000190 IF INPUT-DATA(SUB1:1) NOT = SPACES OR OUTPUT-DATA(SUB2:1) NOT = SPACES 000200 ADD 1 TO SUB2 000210 MOVE INPUT-DATA(SUB1:1) TO OUTPUT-DATA(SUB2:1) 000220 END-IF 000230 END-PERFORM. 000240 000250 DISPLAY "INPUT :" INPUT-DATA. 000260 DISPLAY "OUTPUT :" OUTPUT-DATA. 000270 STOP RUN. 000280 000290 000300 END PROGRAM PROGRAM1. 000310
|
|
You're quite right, TLeaders. That is the algorithm I have used over the years. Of course, back in the old days, we didn't have referance modification available to us, so we had to redefine the strings as arrays of bytes; but the basic algorithm remains the same. |
|
webrabbit
I know what you mean. Sometimes you just have to love these new fangeled gadgets.
Tom |
|
Quote (mikrom):But the disadvantage with using STRING and UNSTRING is, that you need to know maximal possible number of words in the string.
Not really. I learned a little trick as you will see in this and in another thread. Quote (webrabbit):Of course, back in the old days, we didn't have referance modification available to us, so we had to redefine the strings as arrays of bytes; but the basic algorithm remains the same.
Of course, the problem is the "new fangled gadgets" are what you have to use to make things efficient in the end. COBOL is very horrible when it comes to table access and reference modification. I've had time on programs be cut in half time-wise to go away from this kind of thing to the "new fangled gadgets". Although, this problem won't show much difference compared to some others. Not related to what I said, but here's another way to do it: CODE IDENTIFICATION DIVISION. PROGRAM-ID. NEWFILE1. ENVIRONMENT DIVISION. INPUT-OUTPUT SECTION. FILE-CONTROL. SELECT INFILE ASSIGN TO "INDATA.TXT" ORGANIZATION IS LINE SEQUENTIAL. SELECT OUTFILE ASSIGN TO "OUTDATA.TXT" ORGANIZATION IS LINE SEQUENTIAL. DATA DIVISION. FILE SECTION. FD INFILE Record Varying in Size from 1 to 80 Depending on WS-Char-Cnt BLOCK CONTAINS 0 RECORDS. 01 INFILE-REC. 05 Char Occurs 1 to 80 times Depending on WS-Char-Cnt. 10 Each-Char Pic X. FD OUTFILE BLOCK CONTAINS 0 RECORDS. 01 OUTFILE-REC PIC X(80).
WORKING-STORAGE SECTION. 01 TIMING-PROC. 04 Start-Time Pic 99/99/99/99. 04 End-Time Pic 99/99/99/99. 01 PROCESSING-VARIABLES. 04 WS-CHAR-CNT PIC 9(4) COMP-5. 04 PROC-STRING PIC X(80). 04 TV1 PIC X(80). 04 TV2 PIC X(80). 04 PV1 PIC S9(4) COMP-5. 04 EOF-DATA PIC X VALUE "N". 01 OUTPUT-VARIABLES. 04 OUTPUT-STRING PIC X(80).
PROCEDURE DIVISION. 0000-MAIN SECTION. Move Function Current-Date (9:8) To Start-Time.
OPEN INPUT INFILE OUTPUT OUTFILE. READ INFILE INTO PROC-STRING AT END MOVE "Y" TO EOF-DATA END-READ. PERFORM UNTIL EOF-DATA = "Y" PERFORM 1000-PROC-STR WRITE OUTFILE-REC FROM OUTPUT-STRING READ INFILE INTO PROC-STRING AT END MOVE "Y" TO EOF-DATA END-READ END-PERFORM. CLOSE INFILE OUTFILE. Move Function Current-Date (9:8) To END-Time. DISPLAY "END: " END-TIME. DISPLAY "START: " START-TIME. GOBACK.
1000-PROC-STR SECTION. MOVE 1 TO PV1. MOVE SPACES TO OUTPUT-STRING. PERFORM UNTIL PV1 > 80 UNSTRING PROC-STRING DELIMITED BY ALL SPACES INTO TV1 WITH POINTER PV1 END-UNSTRING MOVE SPACES TO TV2 STRING OUTPUT-STRING DELIMITED BY SPACES "*" DELIMITED BY SIZE TV1 DELIMITED BY SPACES INTO TV2 END-STRING MOVE TV2 TO OUTPUT-STRING END-PERFORM. INSPECT OUTPUT-STRING REPLACING ALL "*" BY " ". * REMOVE LEADING SPACES MOVE 0 TO PV1. INSPECT OUTPUT-STRING TALLYING PV1 FOR LEADING SPACES. MOVE OUTPUT-STRING (PV1 + 1:) TO OUTPUT-STRING. Measurement is not management. |
|
Glenn, you say that COBOL is horrible in table access and reference modification. My experience has been that this is not true, as long a you avoid stupid things like non-binary subscripts and pointers. Indices help too. I don's know about pc COBOL as I only know mainframe assembly, so I can't really comment on pc COBOL, but Liant's technical support say there's no problem there either. Perhaps you could document what you mean by "horrible.".
Your code fails if the input string contains an "*", or whatever other character you might use for a marker. Furthermore, you have both a String and an Unstring inside a Perform loop. Both of these statements have very high overhead, much more than referance modification could have. In addition, there is a great deal of redundant data movement inside the loop. I watched the data move around and it is very bewildering. |
|
Quote: Perhaps you could document what you mean by "horrible.".
I did in the next sentence. All table access in any COBOL I've touched is horrible compared to most other languages. This counts the list that you mentioned, which is the standard dogma that works for COBOL. COBOL (both mainframe and PC) just doesn't handle tables well. Let me relate to you another example of mine, which has nothing to do with STRING, UNSTRING and INSPECT, but still has something to do with table access. I got to playing around in some downtime when I was working with coding different sorts in COBOL and testing their execution time on the mainframe (IBM COBOL for this and that, etc). I found something curious, though. The sorts that, by traditional wisdom are the fastest (like quicksort), were actually quite slow within COBOL. I found this quite interesting, so I tested the algorithms further by counting different operations, and discovered something. The fastest algorithm, Combsort (3X faster in fact!), is the one that touches the table the least. And yes I was using indexes on all things. And yes, PC COBOL is just as consistent - you would think they would try to use the same algorithmic techniques that are used in the PC compilers where quicksort actually is the fastest. Quote: Your code fails if the input string contains an "*", or whatever other character you might use for a marker.
Any byte can be used there without a problem, even non-printable characters which would never appear in a standard text string. Not a problem with what was posted. Quote: Both of these statements have very high overhead, much more than referance modification could have.
Are you judging by what you think is happening by reading the source, or actually learning what's happening behind the scenes? Have you tested these things to see? Behind the scenes, STRING UNSTRING and INSPECT do things much more efficiently in most cases than what can be done in COBOL. Like I mentioned, this thread involves much simpler things than the case I found where going to those things in a program reduced the execution time by half. But I did test what was posted in this thread (as copied, no modifications) before I made my assertion on a copy of Fujitsu COBOL 3.0, by throwing a large number of text strings at them. Want to take a guess which one was faster? Hint: It wasn't what TLeaders posted. Measurement is not management. |
|
By "other languages" do you mean anything like Visual Basic? At one job, my boss asked me to see what I could do with a VB program that was taking half the day to run. I wrote a COBOL program (Micro Focus V3.5) which ran literally in the blink of an eye (it was done before one's finger could be lifted off the Enter key). Perhaps a C program would be faster. But then we didn't have a C compiler.
BTW, many languages don't manipulate the strings in a table, they manipulate the string pointers. In the past, I have written a COBOL program to do it that way, it was much faster. |
|
Well Glenn, you got me. I ran tests with RM/COBOL V11.01 and Micro Focus COBOL V 3.2.46 (very old) I ran three loops, each 90,000 times 1) your code 2) referance modification and 3) an empty loop.
MF COBOL 19.67 sec, 33.28 sec, .11 sec RM/COBOL 1.33 sec, 5.26 sec, .02 sec
So there's someting going on behind the scenes.
I left the mainframe world very shortly after STRING, UNSTRING, and referance modification were introduced, so I never had an oportunity to see how they were implemented there. Referance modification should have been implemented at a very low level, the addresssing schemae for IBM mainframes has included referance modification as an integral part since the 60s. |
|
|
 |
|