ibmi-brunch-learn

Announcement

Collapse
No announcement yet.

Convert Number to Char

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Convert Number to Char

    I'm trying to convert a number to character removing zeros from the beginning of the number and the end of decimal parts.
    I found this solutions, What do you think about it? Do I forget something?

    Code:
    **free                                              
           Ctl-Opt                                      
             dftactgrp(*no) actgrp('QILE')              
             bnddir('QC2LE' :'AL400MNUV2')              
             option(*nounref :*srcstmt :*nodebugio)     
             datfmt(*iso) timfmt(*iso)                  
             decedit('.')                               
             debug                                      
             alwnull(*usrctl);                          
    
           Dcl-Pr DspLongTextMsg  ExtPgm('QUILNGTX');   
              Text Char(65535) Const options(*varsize); 
              Length Int(10) Const;                     
              MsgId  Char(7) Const;                     
              QualMsgF Char(20) Const;                  
              ErrorCode Char(32767) Options(*varsize);  
           End-Pr;                                      
    
           DCL-DS ErrorCode Qualified;                  
              BytesProv  Int(10) inz(0);                
              BytesAvail Int(10) inz(0);                
           END-DS;                                      
    
           Dcl-s CharField Varchar(30);    
           Dcl-s WorkField Zoned(20: 6);   
    
           Dcl-s LogMsg VarChar(640000);   
           //------------------------------
           WorkField = 10.0;               
           Exsr DectoChar;                 
    
           WorkField = 1234;               
           Exsr DectoChar;                 
    
           WorkField = -11.34;             
           Exsr DectoChar;                 
    
           WorkField = -01.550;            
           Exsr DectoChar;                 
    
           WorkField = -00.670888;         
           Exsr DectoChar;                 
    
           *Inlr = *On;                    
           //------------------------------
           Begsr DecToChar;                
             CharField = %TrimR(%TrimR(%Char(WorkField) :'0') :'.');          
             CharField = %ScanRpl('.' :'0.' :CharField :1 :1);                
             CharField = %ScanRpl('-.' :'-0.' :CharField :1 :2);              
             LogMsg = CharField + ' Len=' + %Char(%len(CharField));           
             DspLongTextMsg(LogMsg : %Len(LogMsg) :*blanks :'' : ErrorCode);  
    
           EndSr;

    Many thanks.

  • #2
    I think all you need is this:
    CharField = %TrimR(%TrimR(%Char(WorkField) :'0') :'.');

    Examples:
    120.450 to '120.45'
    -120.450 to '-120.45'
    0.0 = empty string
    100.00 to '100'
    -100.00 to '-100'
    -.10 to '-.1'
    -.01 to '-.01'

    Why do you need these?
    CharField = %ScanRpl('.' :'0.' :CharField :1 :1); // inserts a zero before decimal point? 123.45 becomes 1230.45? .123 becomes 0.123? You don't want leading zeros, right?
    CharField = %ScanRpl('-.' :'-0.' :CharField :1 :2); // You don't want leading zeros, right?

    Ringer

    Comment


    • #3
      Oh, and disregard this comment, my mistake:
      "inserts a zero before decimal point? 123.45 becomes 1230.45? "

      Comment


      • #4
        Really it's a bit complicated, because in my case I don't have a Char field in input but a subfield of a datastructure, so I found these article:
        Note: The code accompanying this article is available for download here. Sometimes a reader of this august publication asks me about a problem that I don’t face, and I reply with an academic answer. But when I face the same problem, my interest ceases to be academic, and I look for a more practical solution.


        And I arrange my program in this way:

        Code:
               Ctl-Opt
                 dftactgrp(*no) actgrp('QILE')
                 bnddir('QC2LE' )
                 option(*nounref :*srcstmt :*nodebugio)
                 datfmt(*iso) timfmt(*iso)
                 decedit('.')
                 debug
                 alwnull(*usrctl);
        
               Dcl-Pr DspLongTextMsg  ExtPgm('QUILNGTX');
                  Text Char(65535) Const options(*varsize);
                  Length Int(10) Const;
                  MsgId  Char(7) Const;
                  QualMsgF Char(20) Const;
                  ErrorCode Char(32767) Options(*varsize);
               End-Pr;
        
               DCL-DS ErrorCode Qualified;
                  BytesProv  Int(10) inz(0);
                  BytesAvail Int(10) inz(0);
               END-DS;
        
               Dcl-s String    Varchar(256) Template;
               Dcl-s DecPos    Int(10);
               Dcl-s NullError Int(5);
               Dcl-s Sign      VarChar(1);
               Dcl-s CharField Like(String);
        
               Dcl-s LogMsg VarChar(640000);
               Dcl-Ds Message;
                 Campo1  Char(10) Inz('AAA');
                 Campo2  Zoned(6 :0)  Inz(-1000);
                 Campo3  Zoned(15 :6) Inz(-0.123456);
                 Campo4  Zoned(15 :6) Inz(-0.123000);
                 Campo5  Zoned(15 :6) Inz(0111.123400);
               End-Ds;
               //---------------------------------------------------------------
               Dcl-c NullValue      const(-1);
               Dcl-c NonNullValue   const(0);
               Dcl-c MinusSign      const('-');
               Dcl-c DecimalPoint   const('.');
               Dcl-c EmptyString    const('');
        
               //---------------------------------------------------------------
        
               DecPos = 0;
               CharField = ZonedToChar(%SubSt(Message :11 :6) :DecPos :NullError);
        
               LogMsg = CharField + ' Len=' + %Char(%len(CharField));
               DspLongTextMsg(LogMsg : %Len(LogMsg) :*blanks :'' : ErrorCode);
        
               DecPos = 6;
               CharField = ZonedToChar(%SubSt(Message :17 :15) :DecPos :NullError);
        
               LogMsg = CharField + ' Len=' + %Char(%len(CharField));
               DspLongTextMsg(LogMsg : %Len(LogMsg) :*blanks :'' : ErrorCode);
        
               DecPos = 6;
               CharField = ZonedToChar(%SubSt(Message :32 :15) :DecPos :NullError);
        
               LogMsg = CharField + ' Len=' + %Char(%len(CharField));
               DspLongTextMsg(LogMsg : %Len(LogMsg) :*blanks :'' : ErrorCode);
        
               DecPos = 6;
               CharField = ZonedToChar(%SubSt(Message :47 :15) :DecPos :NullError);
        
               LogMsg = CharField + ' Len=' + %Char(%len(CharField));
               DspLongTextMsg(LogMsg : %Len(LogMsg) :*blanks :'' : ErrorCode);
        
               *Inlr = *On;
               //---------------------------------------------------------------
        
               Dcl-proc ZonedToChar;
               Dcl-pi ZonedToChar Like(String);
                 InString    Like(String) Const;
                 InDecPos    Int(10);
                 OuNull      Int(5);
               End-Pi ZonedToChar;
        
               Dcl-s WorkString Like(String);
               Dcl-s TestZone   Char(1);
               Dcl-s WorkZoned  Zoned(20 :10);
               //---------------------------------------------------------------
        
                 monitor;
                    ouNull = NonNullValue;
                    if inString = *blanks;
                       return '0';
                    endif;
        
                    WorkString = %trim(inString);
                    dow inDecPos >= %len(WorkString);
                       WorkString = '0' + WorkString;
                    enddo;
        
                    TestZone = %bitand(%subst(WorkString:%len(WorkString):1):
                                        x'f0');
                    select;
                       when TestZone = x'f0'
                         or TestZone = x'a0'
                         or TestZone = x'c0'
                         or TestZone = x'e0';
                          Sign = EmptyString;
                       when TestZone = x'd0'
                         or TestZone = x'b0';
                          Sign = MinusSign;
                          %subst(WorkString: %len(WorkString): 1) =
                             %BitOr(%Subst(WorkString :%len(WorkString) :1):  x'f0');
                       other;
                          ouNull = NullValue;
                    endsl;
        
                    if inDecPos > *zero;
                      WorkZoned = %Dec(Sign +
                                   %subst(WorkString :1 :%len(WorkString) - inDecPos) +
                                   DecimalPoint +
                                   %subst(WorkString :%len(WorkString) - inDecPos + 1)
                                   :30 :10);
                    else;
                      WorkZoned = %Dec(Sign + WorkString :30 :10);
                    endif;
        
                    WorkString = %TrimR( %TrimR( %Char(WorkZoned) :'0') :'.');
                    WorkString = %ScanRpl('.'  :'0.'  :WorkString :1 :1);
                    WorkString = %ScanRpl('-.' :'-0.' :WorkString :1 :2);
        
                 on-error;
                    ouNull = NullValue;
                 endmon;
        
                 Return WorkString;
        
               End-Proc;
        If you have new suggestion please advice.
        Many thanks.

        Comment


        • #5
          I'm not sure why using a DS subfield complicates things? You can just pass the subfield to your sub-procedure. Why are you trying to substring it out and pass it as a character? It just massively complicates the code and makes no sense.
          Code:
          CharField = ZonedToChar(Campo2 :DecPos :NullError);
          Or better, convert the original subroutine to a procedure and use that - it was far more understandable:

          Comment


          • #6
            Originally posted by CRinger400 View Post
            Why do you need these?
            CharField = %ScanRpl('.' :'0.' :CharField :1 :1); // inserts a zero before decimal point? 123.45 becomes 1230.45? .123 becomes 0.123? You don't want leading zeros, right?
            CharField = %ScanRpl('-.' :'-0.' :CharField :1 :2); // You don't want leading zeros, right?

            Ringer
            I suspect the reason for those bits is to add a leading zero if there is no integer part (e.g. OP probably needs 0.123 instead of .123 which the %Char will produce). Same for -.123. The OP would need to confirm that.
            Last edited by john.sev99; August 17, 2017, 03:32 PM.

            Comment


            • #7
              Is in my program I receive a Datastructure in input, and I have to concatenate the value of this into a string, and the number have to be expressed like -0.123 and not -.123, I don't know why the %char remove the first zero before the dot.
              What's the OP?
              Many thanks.
              Bye

              Comment


              • #8
                OP = Original Poster.

                Originally posted by paolinosal View Post
                Is in my program I receive a Datastructure in input, and I have to concatenate the value of this into a string
                I still don't understand why you are extracting it that way. Is there a reason your RPG program doesn't use a DS defined the same as the data being received?

                Comment


                • #9
                  If you'd like to use embedded SQL, just check the VARCHAR_FORMAT scalar function(https://www.ibm.com/support/knowledg...arformat.htm)?

                  The following statement should do what you want:
                  Code:
                  Exec SQL  Set :YourCharVar = RTrim(VarChar_Format(:YourNumVar, '99999999999999.000000'), '.0')) ;
                  Birgitta

                  Comment

                  Working...
                  X