Formatting numbers

Share your advanced PureBasic knowledge/code with the community.
AlGonzalez
User
User
Posts: 53
Joined: Sun Feb 15, 2004 6:04 am
Location: Easley, SC, USA

Formatting numbers

Post by AlGonzalez »

Code updated for 5.20+

Here is my first attempt at a procedure to format numbers with commas, currency symbols, etc.:

Code: Select all

;===============================================================
; PureBasic routines to format numbers
;
;
; Version 1.0    2004 Mar 05      initial release for PureBasic
;
; EMail: support@nomscon.com
; URL: http://www.nomscon.com
;
;-- License/Terms and Conditions -------------------------------
; This code is free for all to use without acknowledging the
; author, Alberto Gonzalez. Use this code as you see fit. By
; using or compiling this code or derivative thereof, you are
; consenting to hold the author, Alberto Gonzalez, harmless
; for all effects or side-effects of its use.
;
; In other words, this code works for me, but you are using it
; at your own risk.
;
; All support of this code will be provided (or not provided)
; at the discretion of the author and with no guarantee as to
; the accuracy or timeliness of any response. But I'll do my
; best.
;===============================================================

Enumeration     
  ; flags used by nsFormat... procedures
  #NSFORMAT_TRIM = 1
  #NSFORMAT_ZEROPAD = 2
EndEnumeration

Structure nsFormatPrefsStruct
  ; Store the Mask and Output preferences used by the nsFormat... procedures
  CurrencySymbol.s
  DecimalSymbol.s
  GroupingSymbol.s
  NegativeSymbol.s
  
  LocateCurrencySymbolAtEnd.b
  LocateNegativeSymbolAtEnd.b
  
  Initialized.b
EndStructure

Global nsFormatMaskPrefs.nsFormatPrefsStruct
Global nsFormatOutputPrefs.nsFormatPrefsStruct

Procedure nsFormatInit()
  ; Set default values as used in the U.S.A.
  nsFormatMaskPrefs\CurrencySymbol = "$"
  nsFormatMaskPrefs\DecimalSymbol = "."
  nsFormatMaskPrefs\GroupingSymbol = ","
  nsFormatMaskPrefs\NegativeSymbol = "-"
  
  nsFormatMaskPrefs\LocateCurrencySymbolAtEnd = #False
  nsFormatMaskPrefs\LocateNegativeSymbolAtEnd = #False
  
  nsFormatMaskPrefs\Initialized = #True
  
  ; TODO: respect the user's regional settings
  nsFormatOutputPrefs\CurrencySymbol = "$"
  nsFormatOutputPrefs\DecimalSymbol = "."
  nsFormatOutputPrefs\GroupingSymbol = ","
  nsFormatOutputPrefs\NegativeSymbol = "-"
  
  nsFormatOutputPrefs\LocateCurrencySymbolAtEnd = #False
  nsFormatOutputPrefs\LocateNegativeSymbolAtEnd = #False
  
  nsFormatOutputPrefs\Initialized = #True
EndProcedure

Procedure.s nsFormatLong(value, mask.s, flags)
  Protected valStr.s, result.s
  valStr = Str(value)
  
  If nsFormatMaskPrefs\Initialized = 0 Or nsFormatOutputPrefs\Initialized = 0
    nsFormatInit()
  EndIf
  
  If Len(mask)
    Protected isCurrency.b, isNegative.b, isPercent.b
    
    If FindString(mask, nsFormatMaskPrefs\CurrencySymbol, 1)
      isCurrency = #True
      mask = RemoveString(mask, nsFormatMaskPrefs\CurrencySymbol)
    EndIf
    If FindString(valStr, nsFormatMaskPrefs\NegativeSymbol, 1)
      isNegative = #True
      valStr = RemoveString(valStr, nsFormatMaskPrefs\NegativeSymbol)
    EndIf
    If FindString(mask, "%", 1)
      isPercent = #True
      mask = RemoveString(mask, "%")
    EndIf
    
    If Len(mask)
      Protected valIndex, startIndex, i, c
      valIndex = Len(valStr)
      startIndex = Len(mask)
      
      result = Space(Len(mask))
      
      ; Handle decimal if any
      i = FindString(mask, nsFormatMaskPrefs\DecimalSymbol, 1)
      If i > 0
        ; No decimals in integers so just copy to result
        PokeB(@result + i - 1, Asc(nsFormatOutputPrefs\DecimalSymbol))
        PokeS(@result + i, PeekS(@mask + i))
        ReplaceString(result, "#", "0", 2)
        startIndex = i - 1
      EndIf
      
      For i = startIndex To 1 Step -1
        c = PeekB(@mask + i - 1)
        If (Chr(c) = "#" Or Chr(c) = "0")
          If valIndex > 0
            PokeB(@result + i - 1, PeekB(@valStr + valIndex - 1))
            valIndex = valIndex - 1
          Else
            If (flags & #NSFORMAT_ZEROPAD)
              PokeB(@result + i -1, Asc("0"))
            Else
              PokeB(@result + i -1, Asc(" "))
            EndIf
          EndIf
        Else
          If Chr(c) = nsFormatMaskPrefs\GroupingSymbol
            c = Asc(nsFormatOutputPrefs\GroupingSymbol)
          EndIf
          PokeB(@result + i - 1, c)
        EndIf
      Next
      
      If valIndex > 0
        ; prepend the rest of the number
        result = Space(valIndex) + result
        While valIndex > 0
          PokeB(@result + valIndex - 1, PeekB(@valStr + valIndex - 1))
          valIndex = valIndex - 1
        Wend
      EndIf
      
      ; Replace with blanks any extraneous grouping symbols from start of number
      If FindString(result, " " + nsFormatMaskPrefs\GroupingSymbol, 1)
        ReplaceString(result, " " + nsFormatMaskPrefs\GroupingSymbol, " " + Space(Len(nsFormatMaskPrefs\GroupingSymbol)), 2)
      EndIf
      
      If (flags & #NSFORMAT_TRIM)
        result = Trim(result)
      EndIf
    EndIf
    
    ; attach appropriate symbols
    If isPercent : result = result + "%" : EndIf
    If isCurrency
      If nsFormatOutputPrefs\LocateCurrencySymbolAtEnd <> #False
        result = result + nsFormatOutputPrefs\CurrencySymbol
      Else
        result = nsFormatOutputPrefs\CurrencySymbol + result
      EndIf
    EndIf
    If isNegative
      If nsFormatOutputPrefs\LocateNegativeSymbolAtEnd <> #False
        result = result + "-"
      Else
        result = "-" + result
      EndIf
    EndIf
    
  Else
    result = valStr
  EndIf
  
  ProcedureReturn result
EndProcedure

Procedure.s nsFormatFloat(value.f, mask.s, flags)
  ; TODO: tbd
EndProcedure

Procedure Main()
  If OpenConsole()
    nsFormatInit()      ; Initialize Mask and Output Preferences
    
    l = 2147483647
    
    ConsoleColor(7,0)
    ClearConsole()
    ConsoleColor(11,0)
    PrintN(">>> Sample Outpur for nsFormat... procedures <<<")
    PrintN("Long Value to Format: " + Str(l))
    PrintN("Variable name is " + Chr(34) + "l" + Chr(34))
    
    row = 5
    col = 56
    
    ConsoleColor(12,0)
    ConsoleLocate(0, row)
    PrintN("           Commands                                           Results")
    PrintN("====================================================    =====================") 
    row + 2
    
    ConsoleColor(10,0)
    Print("nsFormatLong(l," + Chr(34) + " ###,###,###,###" + Chr(34) + ",0)")
    ConsoleLocate(col, row) : row + 1
    ConsoleColor(14,0)
    PrintN(nsFormatLong(l, " ###,###,###,###", 0))
    
    ConsoleColor(10,0)
    Print("nsFormatLong(l," + Chr(34) + " ###,###,###,###" + Chr(34) + ",#NSFORMAT_ZEROPAD)")
    ConsoleLocate(col, row) : row + 1
    ConsoleColor(14,0)
    PrintN(nsFormatLong(l, " ###,###,###,###", #NSFORMAT_ZEROPAD))
    
    ConsoleColor(10,0)
    Print("nsFormatLong(l," + Chr(34) + " ###,###,###,###.###" + Chr(34) + ",0)")
    ConsoleLocate(col, row) : row + 1
    ConsoleColor(14,0)
    PrintN(nsFormatLong(l, " ###,###,###,###.###", 0))
    
    ConsoleColor(10,0)
    Print("nsFormatLong(l," + Chr(34) + "$###,###,###,###" + Chr(34) + ",0)")
    ConsoleLocate(col, row) : row + 1
    ConsoleColor(14,0)
    PrintN(nsFormatLong(l, "$###,###,###,###", 0))
    
    ConsoleColor(10,0)
    Print("nsFormatLong(l," + Chr(34) + "$###,###,###,###" + Chr(34) + ",#NSFORMAT_TRIM)")
    ConsoleLocate(col, row) : row + 1
    ConsoleColor(14,0)
    PrintN(nsFormatLong(l, "$###,###,###,###", #NSFORMAT_TRIM))
    
    ConsoleColor(10,0)
    Print("nsFormatLong(l," + Chr(34) + "$###,###,###,###" + Chr(34) + ",#NSFORMAT_ZEROPAD)")
    ConsoleLocate(col, row) : row + 1
    ConsoleColor(14,0)
    PrintN(nsFormatLong(l, "$###,###,###,###", #NSFORMAT_ZEROPAD))
    
    row + 3
    ConsoleColor(10,0)
    PrintN("")
    PrintN("nsFormatOutputPrefs\CurrencySymbol = " + Chr(34) + " USD" + Chr(34))
    PrintN("nsFormatOutputPrefs\LocateCurrencySymbolAtEnd = 1")
    PrintN("nsFormatLong(l," + Chr(34) + "$ ###,###,###,###" + Chr(34) + ",0)")
    ConsoleLocate(col, row) : row + 1
    nsFormatOutputPrefs\CurrencySymbol = " USD"
    nsFormatOutputPrefs\LocateCurrencySymbolAtEnd = 1
    ConsoleColor(14,0)
    PrintN(nsFormatLong(l, "$ ###,###,###,###", 0))
    
    ConsoleColor(11,0)
    ConsoleLocate(0, row + 2)
    Print("Press Enter when done: ")
    Input()
    CloseConsole()
  EndIf
EndProcedure

Main()
End
It includes some sample output to the console.

Please watch for any lines that may have wrapped.

I hope someone finds this useful.

Any comments and especially corrections will be appreciated.
User avatar
Paul
PureBasic Expert
PureBasic Expert
Posts: 1286
Joined: Fri Apr 25, 2003 4:34 pm
Location: Canada
Contact:

Post by Paul »

Windows also makes it easy to format numbers if you don't want to do a lot of typing :)

Code: Select all

value.f=7923.446

dollar.s=""
GetCurrencyFormat_(0,0,StrF(value,2),0,@dollar,10)

Debug dollar
And you can play with the CURRENCYFMT structure to customize the output.


Enjoy!
Image Image
AlGonzalez
User
User
Posts: 53
Joined: Sun Feb 15, 2004 6:04 am
Location: Easley, SC, USA

Post by AlGonzalez »

Paul wrote:Windows also makes it easy to format numbers if you don't want to do a lot of typing :)
Yeah! Well were you a couple of days ago? :evil:

Just kidding - thanks for the heads up - will save me "SOME" time and effort.
Post Reply