PrintfScanf.st
changeset 4452 9b6b7249be74
parent 4441 592237602835
child 4471 54c49f28673c
--- a/PrintfScanf.st	Mon Jul 03 10:21:50 2017 +0200
+++ b/PrintfScanf.st	Mon Jul 03 15:39:44 2017 +0200
@@ -46,6 +46,12 @@
 
         no need for the singleton - classes are already singletons ready to use exactly for that.
         (no need to use C++/Java patterns here in Smalltalk)
+
+    Caveat:
+        the behavior when the format-width is less than the preferred default precision is suboptimal;
+        it leads to problems when trying to format tables into columns...
+        For now: always use with width.precision formats to enforce the width.
+        The current behavior (generating longer strings like printf does) may change in the future.
 "
 !
 
@@ -343,8 +349,8 @@
         char := formatStream peek
     ].
 
-    char == $l ifTrue:[
-        "Ignore long specifier."
+    ((char == $l) or:[char == $L]) ifTrue:[
+        "Ignore long specifier (l, L and ll)."
         formatStream next.  
         char := formatStream peek.
         char == $l ifTrue:[
@@ -371,7 +377,7 @@
         char == $g ifTrue: [ 
             self absPrintFloat:arg on: argString digits: precision + 1 ].
         char == $f ifTrue: [ 
-            self absDecimalPrintFloat:arg on: argString digits: precision + arg abs log10 + 1].
+            self absDecimalPrintFloat:arg on: argString digits: precision + (arg asFloat abs log10 ceiling asInteger) "+ 1"].
         char == $e ifTrue: [
             self absScientificPrintFloat:arg on: argString digits: precision + 1].
         argString := argString contents.
@@ -445,13 +451,13 @@
         pound ifTrue: [arg := '0b', arg]
     ].
 
-    precision := precision ? arg size.
-    ljust ifTrue: [outStream nextPutAll: (arg copyFrom: 1 to: precision)].
+    precision := (precision ? arg size) min: arg size.
+    ljust ifTrue: [precision > 0 ifTrue:[ outStream nextPutAll: (arg copyFrom: 1 to: precision)]].
     width - precision timesRepeat: [outStream nextPut: pad].
-    ljust ifFalse: [outStream nextPutAll: (arg copyFrom: 1 to: precision)].
+    ljust ifFalse: [precision > 0 ifTrue:[ outStream nextPutAll: (arg copyFrom: 1 to: precision)]].
     ^ formatStream next
 
-    "Modified: / 21-06-2017 / 13:36:49 / cg"
+    "Modified (format): / 03-07-2017 / 15:24:00 / cg"
 !
 
 printf:formatString argument:arg 
@@ -632,6 +638,7 @@
      self printf:'%20.10f\n' on:Transcript arguments: { 0.0 asLongFloat log10  }
      self printf:'%20.10f\n' on:Transcript arguments: { 0.0 asQDouble log10  }
 
+     self printf:'%20.10f\n' on:Transcript arguments: { Float NaN   }
      self printf:'%20.10f\n' on:Transcript arguments: { DomainError ignoreIn:[ -1.0 log10 ]   }
      self printf:'%20.10f\n' on:Transcript arguments: { DomainError ignoreIn:[ -1.0 asShortFloat log10 ]  }
      self printf:'%20.10f\n' on:Transcript arguments: { DomainError ignoreIn:[ -1.0 asLongFloat log10]   }
@@ -660,8 +667,8 @@
 
     "x is myself normalized to (1.0, 10.0), exp is my exponent"
     exp := absVal < 1.0 
-            ifTrue:[ (10.0 / absVal) log10 floor negated ] 
-            ifFalse:[ absVal log10 floor].
+            ifTrue:[ (10.0 / absVal asFloat) log10 floor negated ] 
+            ifFalse:[ absVal asFloat log10 floor].
 
     exp := exp asInteger.
     x := absVal / (10.0 raisedTo:exp).
@@ -703,7 +710,7 @@
         ]
     ]
 
-    "Modified: / 21-06-2017 / 13:29:07 / cg"
+    "Modified: / 03-07-2017 / 14:13:31 / cg"
 !
 
 absPrintFloat:aFloat on:aStream digits:digits