Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Building a string in a loop 1

Status
Not open for further replies.

LarrySteele

Programmer
May 18, 2004
318
US
I've been at this for a good couple of hours and I've surrendered.

Here's what I'm trying to do. I want to go through a loop n amount of times and build a string. Given an n[/n] of 5, I want to store the following: [tt]'School_1 Degree_1 School_2 Degree_2 ... School_5 Degree_5'[/tt]

I had something like this:
[tt]
DATA _NULL_;
DO I = 1 TO &IDX'
CALL SYMPUTX('CNT',I);
MY_STRING = MY_STRING || 'SCHOOL_&CNT DEGREE_&CNT';
END;
CALL SYMPUTX('MY_VAR',MY_STRING);
RUN;
[/tt]

When I ran this, I received the following:
[tt]
NOTE: Numeric values have been converted to character values at the places given
105:17
NOTE: Character values have been converted to numeric values at the places given
105:27
NOTE: Invalid numeric data, ' SCHOOL_&CNT DEGREE_&CNT', at line 105 column 27.
[/tt]

Line 105 is the MY_STRING=MY_STRING... line.

When I run this, I get the expected output:
[tt]
DATA _NULL_;
DO I = 1 TO &IDX'
CALL SYMPUTX('CNT',I);
MY_STRING = ' SCHOOL_&CNT DEGREE_&CNT';
END;
CALL SYMPUTX('MY_VAR',MY_STRING);
RUN;
[/tt]

The problem with the latter is that my output is ' SCHOOL_5 DEGREE_5'.

Just for fun, I tried this variation:
[tt]
DATA _NULL_;
DO I = 1 TO &IDX'
CALL SYMPUTX('CNT',I);
MY_STRING = 'SCHOOL_4 DEGREE_4' || ' SCHOOL_&CNT DEGREE_&CNT';
END;
CALL SYMPUTX('MY_VAR',MY_STRING);
RUN;
[/tt]

This version gave me the string I expected: 'SCHOOL_4 DEGREE_4 SCHOOL_5 DEGREE_5'. This tells me that the syntax of the string concatenation in my first version was correct. However, SAS was attempting to convert my string variable into a numeric variable and having a fit about it.

I tried wrapping the string with %STR(), but that didn't seem to change anything. I've tried Googling for some information, but I Couldn't think of anything useful to search on that didn't give me a billion false hits.

NOTE: We're using SAS (r) 9.1 (TS1M3) on z/OS (Read: this is on the mainframe).

Any assistance, suggestions, offerings would be appreciated. Answers would be doubly so.

TIA,
Larry



 
I accidently bumped into the answer. While searching for information on arrays, I found a post by Klaz2002:
Even though his post was unrelated to what I'm trying to do, there were enough clues for me to use.

First thing, was to define my variable as a 2000 character string to ensure that it did not get truncated. I found that's exactly what had been happening. Once I fixed that, things started to whip right into shape.

My next problem is that my index number included a number of spaces (e.g. 'SCHOOL_4' appeared as 'SCHOOL_ 4'. I created a one-character string to hold my loop index and used that to build my string - worked great.

Here's my final solution:
Code:
DATA _NULL_;
  /* THIS SELECTS THE COLUMNS WE WANT FOR OUR OUTPUT AND    */
  /* REARRANGES THE TRANSPOSED COLUMNS SO THEY ARE TOGETHER */
  /* BY SERIES RATHER THAN BY NAME                          */
  LENGTH FINAL_STRING $2000;
 
  /* BUILD STRING CONTAINING REPEATED CELLS */
  DO I = 1 TO &IDX;
    LENGTH CNT $1.;
    CNT = I;
    FINAL_STRING = TRIM(FINAL_STRING) ||
                   ' SCHOOL_' || TRIM(CNT) ||
                   ' DEGREE_' || TRIM(CNT) ||
                   ' MAJOR_' || TRIM(CNT) || 
                   ' GRAD_DATE_' || TRIM(CNT);
  END;
 
  /* BUILD STRING OF COLUMN NAMES BEFORE REPEATED CELLS */
  FINAL_STRING = 'LAST_NAME FIRST_NAME' ||
                 TRIM(FINAL_STRING);
  CALL SYMPUTX('MY_VAR',TRIM(FINAL_STRING));
RUN;


ODS CHTML FILE=FILEOUT  RS=NONE STYLE=SASDOCPRINTER
  HEADTEXT="<STYLE> TD {MSO-NUMBER-FORMAT:\@}</STYLE>"; 
  TITLE; /* TAKES OUT 'THE SAS SYSTEM' DEFAULT TITLE */
 
  PROC PRINT DATA=DATA_OUT NOOBS;
    VAR &MY_VAR;
  RUN;
ODS HTML CLOSE;

Hope this helps someone else trying to figure out how to group transposed columns by series rather than by name.

Cheers,
Larry
 
Its nice to see that my old post helped someone. Keep posting here and we will all benefit.
Klaz
 
IN your final_string variable you should use the following code to eliminate both the SAS Warning in the log and the spaces between words and numbers.

Code:
 FINAL_STRING = TRIM(FINAL_STRING) ||
                   ' SCHOOL_' || TRIM(left(put(CNT,8.))) ||
                   ' DEGREE_' || TRIM(left(put(CNT,8.)))  ||
                   ' MAJOR_' || TRIM(left(put(CNT,8.)))  || 
                   ' GRAD_DATE_' || TRIM(left(put(CNT,8.))) ;

I hope this helps you further.
Klaz
 
Klaz,

Thanks for the suggestion. Since CNT is defined as a one character string, there are no SAS warnings nor extra spaces.

However, I did try [tt]' SCHOOL_' || TRIM(LEFT(PUT(I,8.))) ||[/tt] to see what would happen. As I suspected, your suggestion worked just fine. I then tried the following: [tt]' SCHOOL_' || PUT(I,1.)||[/tt] and that worked as well.

Here's my modified DO loop:
Code:
  /* BUILD STRING CONTAINING REPEATED CELLS */
  DO I = 1 TO &IDX;
    FINAL_STRING = TRIM(FINAL_STRING) ||
                   ' SCHOOL_' || PUT(I,1.) ||
                   ' DEGREE_' || PUT(I,1.) ||
                   ' MAJOR_' || PUT(I,1.) || 
                   ' GRAD_DATE_' || PUT(I,1.);
  END;

This is great because you've helped eliminate an extra variable, and a few function calls. Plus, I think it's clearer what I'm appending the variables with.

Thanks for the tip!
Larry



 
If you're using SAS9.1, check out the new functions CATT and CATX.
CATX is my favourite...
Code:
  text1 = catx(' ',text1,text2,....,textn);
The first parameter is the delimiter to be added between the other parameters when they are concatenated together. They are all automatically TRIMed and LEFTed as well, saves a fair bit of coding. :)
Enjoy.



Chris
Business Analyst, Code Monkey, Data Wrangler.
SAS Guru.
 
Chris,

Thanks for the suggestion. Looks like it'd be great in many situations. Unfortunately, it doesn't work quite as well for mine.

I tried the following:
Code:
FINAL_STRING = CATX(' ',FINAL_STRING,  
                        'SCHOOL_' || I,      
                        'DEGREE_' || I,   
                        'MAJOR_' || I,   
                        'GRAD_DATE_' || I);
I still had to wrap I around a put statement, defining it as a single character string: [tt]PUT(I,1.)[/tt].

So while it won't really save a lot of typing in this instance, it's still a great tip. Here's some more info from SAS:
Cheers,
Larry
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top