### Bookstore

 Computer Math and Games in Pascal (preview) Lazarus Handbook

### Author Topic: Convert from Integer to String (Base Ten only)  (Read 1444 times)

#### WackaMold

• Newbie
• Posts: 3
##### Convert from Integer to String (Base Ten only)
« on: May 03, 2021, 12:09:45 am »
This function makes the EXE 1K bytes larger than just calling Str(). It started as an alternative to itoa() "Integer To Ascii". Not yet tested with zero, negative values, nor large values.

Code: Pascal  [Select][+][-]
1. function StrReverse( strVal : string ) : string; // return the string with characters in reverse order
2. var
3.   strRtn : string = ''; // function result
4.   idxStr : integer    ; // indexer
5.   chrCur : char       ; // current character
6. begin
7.   for idxStr := Byte(Length(strVal)) DownTo 1 do begin // scan all characters in the string in reverse order
8.   // Byte() conversion avoids Warning: (4048) Type size mismatch, possible loss of data / range check error
9.     chrCur := strVal[idxStr];                    // get current character
10.     strRtn := strRtn + chrCur;                   // append it to the output
11.   end;                                           // done scanning
12.   StrReverse := strRtn;                          // pass result back to caller
13. end; // StrReverse
14.
15. function StrFrmInt( prmInt : integer ) : string; // convert from Integer to String, in base-ten only
16. var
17.   strRtn : string = ''          ; // function result
18.   ptrTmp : byte                 ; // value of current integer-digit
19.   chrTmp : char                 ; // char  of current string -digit
20. begin
21.   while prmInt > 0 do begin       // eat all of caller's integer value, from ones-place to largest-place
22.     ptrTmp :=      prmInt Mod 10; // get value of current last digit
23.     ptrTmp :=      ptrTmp  +  48; // convert from zero-based to '0'-based
24.     chrTmp := Chr( ptrTmp )     ; // convert from byte-digit to character-digit
25.     strRtn := strRtn + chrTmp   ; // append character-digit to result
26.     prmInt :=      prmInt Div 10; // drop last digit from caller's integer
27.   end                           ; // done eating caller's integer value
28.   strRtn := StrReverse( strRtn ); // convert our characters from [ones-place through largest-place] to [largest-place through ones-place]
29.
30.   Result := strRtn              ; // pass result back to caller
31. end; // StrFrmInt
32.

#### mangakissa

• Hero Member
• Posts: 1116
##### Re: Convert from Integer to String (Base Ten only)
« Reply #1 on: May 03, 2021, 11:18:55 am »
So, what's the problem?
Lazarus 2.06 (64b) / FPC 3.0.4 / Windows 10
stucked on Delphi 10.3.1

#### marcov

• Global Moderator
• Hero Member
• Posts: 9337
• FPC developer.
##### Re: Convert from Integer to String (Base Ten only)
« Reply #2 on: May 03, 2021, 11:34:55 am »
In case you are an embedded user (*) where it might matter, string support is higher level than plain pointers and chars. Rewrite them using pchar might save you some bytes if you really need them.

(*) and by embedded I mean anything with less than 256k effective storage for programs. RPI is not embedded by this definition.

#### engkin

• Hero Member
• Posts: 2819
##### Re: Convert from Integer to String (Base Ten only)
« Reply #3 on: May 03, 2021, 12:44:49 pm »
You don't need StrReverse function. Just change the order of this line:
Code: Pascal  [Select][+][-]
1.     strRtn := strRtn + chrTmp;
to
Code: Pascal  [Select][+][-]
1.     strRtn :=  chrTmp + strRtn;

#### Bart

• Hero Member
• Posts: 4283
##### Re: Convert from Integer to String (Base Ten only)
« Reply #4 on: May 03, 2021, 12:46:12 pm »
Your routine to reverse the string is a bit suboptimal.
FreePascal has a ReverseString function in strutils unit.
If you cannot (or do not want to) include that unit, simply copy the code from there.
Alternatively (see also my website, which has some other "suboptimal" ones as well, but this one is OK):
Code: Pascal  [Select][+][-]
1. function ReverseString(const S: String): String;
2. var i,j: LongInt;
3. begin
4.   j := Length(S);
5.   Setlength(Result,j);
6.   i := 1;
7.   while i <= j do //Actually this is faster than a for loop
8.   begin
9.     result[i] := S[j-i+1];
10.     inc(i);
11.   end;
12. end;

Why can't or won't you sue the Str() function?

Bart

#### y.ivanov

• Full Member
• Posts: 132
##### Re: Convert from Integer to String (Base Ten only)
« Reply #5 on: May 03, 2021, 01:44:06 pm »
Just a side question - why is it necessary to make a string ltr and then reverse? Is there any subtle reason I am not aware of?

#### engkin

• Hero Member
• Posts: 2819
##### Re: Convert from Integer to String (Base Ten only)
« Reply #6 on: May 03, 2021, 01:47:37 pm »
@Bart, Because of Unicode I wouldn't call it ReverseString,

@y.ivanov, I don't think so. See my previous post.

#### y.ivanov

• Full Member
• Posts: 132
##### Re: Convert from Integer to String (Base Ten only)
« Reply #7 on: May 03, 2021, 01:56:48 pm »
@engkin
My question is partially because your previous post, partially because I reviewed some C library sources for itoa() and I what I saw was that some implementations really do reversing. And so I suspected reason I'm unfamiliar with.

#### engkin

• Hero Member
• Posts: 2819
##### Re: Convert from Integer to String (Base Ten only)
« Reply #8 on: May 03, 2021, 02:05:00 pm »
In this case probably it is speed.

#### WackaMold

• Newbie
• Posts: 3
##### Re: Convert from Integer to String (Base Ten only)
« Reply #9 on: May 03, 2021, 08:36:05 pm »
Quote
You don't need StrReverse().

Code: [Select]
`[Del] strRtn := strRtn + chrTmp; // ap pend character-digit to result[Ins] strRtn := chrTmp + strRtn; // prepend character-digit to result`
Thank you, this saved another 1K.

Quote
Why not use Str()?
On the off chance of shrinking the EXE further, without the extra effort of trying a function written in assember. Using StrUtils or SysUtils or untStrings added far too much unused code, making the EXE more than twice larger. Speed is not a concern in this case, but might be useful in other cases.

#### winni

• Hero Member
• Posts: 2418
##### Re: Convert from Integer to String (Base Ten only)
« Reply #10 on: May 03, 2021, 09:32:12 pm »
Hi!

Str () is part of the system unit - so no additional code is added.

As Bart said: use Str()

Winni

#### y.ivanov

• Full Member
• Posts: 132
##### Re: Convert from Integer to String (Base Ten only)
« Reply #11 on: May 03, 2021, 11:46:42 pm »
If you want a slight reduction you can consider using ShortString instead of String.

Your function is incorrect for zero and negative.

As markov suggested, you should use PChar if the code size is critical.
Here is example implementation for base 10 (not reentrant).

Code: Pascal  [Select][+][-]
1. function StrFrmInt(prmInt: Integer): PChar;
2. const
3.   Buf: array[0..22] of Char = '';
4. var
5.   I, Sign: Integer;
6. begin
7.   if prmInt < 0 then
8.     Sign := -1 else
9.     Sign := 1;
10.   Buf[High(Buf)] := #0;
11.   I := Pred(High(Buf));
12.   repeat
13.     Buf[I] := Char(48 + prmInt mod 10 * Sign);
14.     prmInt := prmInt div 10;
15.     Dec(I);
16.   until (prmInt = 0) or (I < 1);
17.   if Sign < 0 then
18.   begin
19.     Buf[I] := '-';
20.     Dec(I);
21.   end;
22.   Result := PChar(@Buf[Succ(I)]);
23. end;
24.

#### WackaMold

• Newbie
• Posts: 3
##### Re: Convert from Integer to String (Base Ten only)
« Reply #12 on: May 09, 2021, 02:36:49 pm »
Cool. This version ignores Sign and has comments. It's good for only non-negative values.
Code: [Select]
`function StrFrmInt( intPrm : Integer ) : PChar; // convert from non-negative Integer to String, in base-ten only. Adds 2Kconst  bufStr : array[ 0..22 ] of Char = ''            ; // null-terminated string; eats 32 bytesvar  idxBuf : Integer                                ; // indexer into string bufferbegin  intPrm :=               Abs    ( intPrm        ); // convert negative values to positive  bufStr[         High( bufStr ) ] := #0          ; // put string-terminator in last position  idxBuf := Pred( High( bufStr ) )                ; // point to next-to-        last position  repeat                                            // process loop    bufStr[ idxBuf ] := Char( 48 + intPrm Mod 10 ); // shift ones-place from integer-digit to character-digit; put that in buffer's current position    intPrm :=             Integer( intPrm Div 10 ); // drop ones-place from caller's integer; typecast suppresses Warning 4048 'Type size mismatch, possible loss of data / range check error'    Dec( idxBuf )                                 ; // point to preceding buffer position  until( intPrm = 0 ) Or ( idxBuf < 1 )           ; // done when [caller's integer is eaten up] or [we have run out of positions to fill]  Result := PChar( @bufStr[ Succ( idxBuf ) ] )    ; // return a string-pointer to the character after the current buffer positionend; // StrFrmInt`