changeset 14077:b6eeeb67fa3f stable

str2double: return NaN for things like "1 2 3 4" (bug #34713). * str2double.cc (single_num, extract_num): Skip spaces as needed. (str2double1): Don't skip all spaces.
author John W. Eaton <jwe@octave.org>
date Tue, 20 Dec 2011 18:06:07 -0500
parents 9aff66860e03
children 941d19370065
files src/DLD-FUNCTIONS/str2double.cc
diffstat 1 files changed, 54 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/src/DLD-FUNCTIONS/str2double.cc
+++ b/src/DLD-FUNCTIONS/str2double.cc
@@ -46,6 +46,14 @@
 single_num (std::istringstream& is, double& num)
 {
   char c = is.peek ();
+
+  // Skip spaces.
+  while (isspace (c))
+    {
+      is.get ();
+      c = is.peek ();
+    }
+
   if (c == 'I')
     {
       // It's infinity.
@@ -93,6 +101,14 @@
   have_sign = imag = false;
 
   char c = is.peek ();
+
+  // Skip leading spaces.
+  while (isspace (c))
+    {
+      is.get ();
+      c = is.peek ();
+    }
+
   bool negative = false;
 
   // Accept leading sign.
@@ -104,12 +120,27 @@
       have_sign = true;
     }
 
+  // Skip spaces after sign.
+  while (isspace (c))
+    {
+      is.get ();
+      c = is.peek ();
+    }
+
   // It's i*num or just i.
   if (is_imag_unit (c))
     {
       c = is.get ();
       imag = true;
       char cn = is.peek ();
+
+      // Skip spaces after imaginary unit.
+      while (isspace (cn))
+        {
+          is.get ();
+          cn = is.peek ();
+        }
+
       if (cn == '*')
         {
           // Multiplier follows, we extract it as a number.
@@ -126,14 +157,31 @@
       if (is.good ())
         {
           c = is.peek ();
+
+          // Skip spaces after number.
+          while (isspace (c))
+            {
+              is.get ();
+              c = is.peek ();
+            }
+
           if (c == '*')
             {
               is.get ();
-              c = is.get ();
+              c = is.peek ();
+
+              // Skip spaces after operator.
+              while (isspace (c))
+                {
+                  is.get ();
+                  c = is.peek ();
+                }
+
               if (is_imag_unit (c))
                 {
                   imag = true;
-                  is.peek ();
+                  is.get ();
+                  is.peek (); // Sets eof bit.
                 }
               else
                 is.setstate (std::ios::failbit); // indicate that read has failed.
@@ -142,7 +190,7 @@
             {
               imag = true;
               is.get ();
-              is.peek ();
+              is.peek (); // Sets eof bit.
             }
         }
     }
@@ -181,14 +229,12 @@
 
   std::string str = str_arg;
 
+  // FIXME -- removing all commas does too much...
   std::string::iterator se = str.end ();
-
-  // Remove commas (thousand separators) and spaces.
   se = std::remove (str.begin (), se, ',');
-  se = std::remove (str.begin (), se, ' ');
   str.erase (se, str.end ());
+  std::istringstream is (str);
 
-  std::istringstream is (str);
   double num;
   bool i1, i2, s1, s2;
 
@@ -305,6 +351,7 @@
 %!assert (str2double (["2 + j";"1.25e-3";"-05"]), [2+i; 1.25e-3; -5])
 %!assert (str2double ({"2 + j","1.25e-3","-05"}), [2+i, 1.25e-3, -5])
 %!assert (str2double (1), NaN)
+%!assert (str2double ("1 2 3 4"), NaN)
 %!assert (str2double ("Hello World"), NaN)
 %!assert (str2double ("NaN"), NaN)
 %!assert (str2double ("NA"), NA)