代码之家  ›  专栏  ›  技术社区  ›  Drew

在C++中使用IttrugString进行字符串到双转换的意外结果

  •  1
  • Drew  · 技术社区  · 17 年前

    我目前正在尝试使用一个字符串(“0.1”),并在Xcode上用C++在GC4.2中转换为双。

    我正在使用一个我从中获取的函数 another question ,但当我尝试使用该函数时,我根据gdb的输入是(字符串)“0.1”,但我的输出是(双)2.1220023981051542E-314。

    这是我直接复制的代码片段:

    double strToDouble(std::string const &numberString)
    {
        istringstream inStream(numberString);
        double doubleValue;
        inStream >> doubleValue;
        if(!(inStream && (inStream >> std::ws).eof()))
        {
            return 0.0;  
        }
    
        return doubleValue;
    };
    

    我使用的是C++而不是Obj-C,因为它可能最终需要在A*NIX或Windows机器上编译。

    我自然是一个PHP程序员,但我需要加快一些数字运算速度,所以我是用编译语言来实现的。大学已经很久没有处理过一门低级语言了,所以,如果有人有想法的话,我们会非常感激…

    Drew J. Sonne。

    完整代码:

    #include <iostream>
    #include <vector>
    #include <string>
    #include <sstream>
    using namespace std;
    
    /*
     * @var delimiters the string to define a break by
     * @var str the string to break
     * @var tokens where to store the broken string parts.
     */
    void explode(const string& delimiters, const string& str, vector<string>& tokens)
    {
        // Skip delimiters at beginning.
        string::size_type lastPos = str.find_first_not_of(delimiters, 0);
        // Find first "non-delimiter".
        string::size_type pos     = str.find_first_of(delimiters, lastPos);
    
        while (string::npos != pos || string::npos != lastPos)
        {
            // Found a token, add it to the vector.
            tokens.push_back(str.substr(lastPos, pos - lastPos));
            // Skip delimiters.  Note the "not_of"
            lastPos = str.find_first_not_of(delimiters, pos);
            // Find next "non-delimiter"
            pos = str.find_first_of(delimiters, lastPos);
        }
    };
    
    /*
     * @var numberString double to be converted as a string.
     */
    double strToDouble(std::string const &numberString)
    {
        istringstream inStream(numberString);
        double doubleValue;
        inStream >> doubleValue;
        if(!(inStream && (inStream >> std::ws).eof()))
        {
            return 0.0;  
        }
    
        return doubleValue;
    };
    
    class Cluster {
    private:
        vector<double> latStore;
        vector<double> lngStore;
    public:
        Cluster(int,string,string);
    };
    
    /*
     * @var latString a comma seperated list of doubles for the latitudes.
     * @var lngString a comma separated list of doubles for the longitudes.
     */
    Cluster::Cluster(int newLocationLength, string latString, string lngString)
    {
        // mark our vectors
        vector<string> latStoreString;
        vector<string> lngStoreString;
    
        // Explode our input strings.
        explode(",", latString, latStoreString);
        explode(",", lngString, lngStoreString);
    
        for( int i = 0; i < latStoreString.size(); i++)
        {
            // Grab the latitude and store it.
            string tempLat = latStoreString[i];
            double latDouble = strToDouble(tempLat);
            latStore.push_back( strToDouble(tempLat) );
    
            // Grab the longitude and store it.
            string tempLng = lngStoreString[i];
            lngStore.push_back( strToDouble(tempLng) );
        }
    }
    
    int main (int argc, char * const argv[]) {
    
        Cluster *rect = new Cluster("0.1,0.4","0.1,0.4");
    
        return 0;
    }
    
    6 回复  |  直到 17 年前
        1
  •  2
  •   Community Mohan Dere    9 年前

    这可能是由STL调试模式引起的。删除目标预处理器宏生成设置中的调试宏。

    C++ Debug builds broke in Snow Leopard X-Code

        2
  •  0
  •   Myles    17 年前

    为什么不使用atof()? link

        3
  •  0
  •   Roger Orr    17 年前

    我看不出你的代码片段有什么问题。你能给我看看你用的代码吗 输出 结果

        4
  •  0
  •   Alex McCarthy David Norman    17 年前

    正如Myles建议的那样,atof()可能更简单。可以通过调用c_str()成员函数将字符串对象转换为c字符串:

    double result = atof(inputString.c_str()); // 0.0 if a double couldn't be read
    

    以下是更多信息: http://www.cplusplus.com/reference/clibrary/cstdlib/atof/

        5
  •  0
  •   Stephen Newell    17 年前
    #include <iostream>
    #include <sstream>
    
    double strToDouble(std::string const &numberString)
    {
        std::istringstream inStream(numberString);
        double doubleValue;
        std::cout << doubleValue << '\n';
        inStream >> doubleValue;
        if(!(inStream && (inStream >> std::ws).eof()))
        {
            return 0.0;  
        }
    
        return doubleValue;
    };
    
    int main()
    {
        std::cout << strToDouble("0.1") << '\n';
    
        return 0;
    }
    

    上面的代码给出了以下输出:
    -2.36907E-39
    0.1条

    您在返回前是否偶然检查了DoubleValue的值?


    Cluster::Cluster(string latString, string lngString)
    {
        // mark our vectors
        vector<string> latStoreString;
        vector<string> lngStoreString;
    
        // Explode our input strings.
        explode(",", latString, latStoreString);
        explode(",", lngString, lngStoreString);
    
        for( int i = 0; i < latStoreString.size(); i++)
        {
            // Grab the latitude and store it.
            string tempLat = latStoreString[i];
            std::cout << "tempLat=" << tempLat << '\n';
            double latDouble = strToDouble(tempLat);
            std::cout << "latDouble=" << latDouble << '\n';
            latStore.push_back( strToDouble(tempLat) );
    
            // Grab the longitude and store it.
            string tempLng = lngStoreString[i];
            lngStore.push_back( strToDouble(tempLng) );
        }
    }
    
    int main (int argc, char * const argv[]) {
    
        Cluster *rect = new Cluster("0.1,0.4","0.1,0.4");
    
        return 0;
    }
    

    输出:
    TEMPPLAT=0.1
    拉丁双=0.1
    TEMPPLAT=0.4
    拉丁双=0.4

    您能用这些修改运行代码吗(您没有在ctor中使用in t参数,所以我刚刚删除了它)。我还使用valgrind运行了您的代码,没有错误(只有内存泄漏)。

        6
  •  0
  •   Jagannath    17 年前

    看起来你没有得到你的请求问题的答案。其他人建议使用atof()。如果您想在实现中解决这个问题,那么请看下面的代码。不要使用向量分解方法,而是使用向量来避免冗余代码。我也修改了strtodouble中的代码。

    void explode(const string& delimiters, const string& str, vector<double>& tokens)
    {    
         // Skip delimiters at beginning.   
         string::size_type lastPos = str.find_first_not_of(delimiters, 0);   
         // Find first "non-delimiter".    
         string::size_type pos = str.find_first_of(delimiters, lastPos);
         while (string::npos != pos || string::npos != lastPos)   
         {        
                  // Found a token, add it to the vector.       
                 string temp = str.substr(lastPos, pos - lastPos);
                 tokens.push_back(strToDouble(temp));    
                 // Skip delimiters.  Note the "not_of"        
                lastPos = str.find_first_not_of(delimiters, pos);        
                // Find next "non-delimiter"        
                pos = str.find_first_of(delimiters, lastPos);    
         }
    }
    
    double strToDouble(std::string const &numberString)
    {  
       istringstream inStream(numberString);    
       int pos = numberString.find_first_not_of("1234567890.", 0);
    
       if (string::npos != pos)
       {
           return 0.0;
       }
       else
       {
          double doubleValue;   
          inStream >> doubleValue;        
          return doubleValue;
      }
    }