Determining if a string is a double

前端 未结 5 685
伪装坚强ぢ
伪装坚强ぢ 2020-12-19 01:38

I would like to see if a string contains a double as its sole contents. In other words, if it could possibly be the output of the following function:

string          


        
相关标签:
5条回答
  • 2020-12-19 02:08

    You've been offered C-style and boost alternatives, but in the style of your doubleToString implementation:

    bool is_double(const std::string& s)
    {
        std::istringstream iss(s);
        double d;
        return iss >> d >> std::ws && iss.eof();
    }
    

    Here, you're checking iss >> d returns iss, which will only evaluate to true in a boolean context if the streaming was successful. The check for nothing but whitespace before eof() ensures there's no trailing garbage.

    If you want to consider leading and trailing whitespace garbage too:

        return iss >> std::nowkipws >> d && iss.eof();
    

    This can be generalised into a boolean-returning test similar to boost's lexical_cast<>...

    template <typename T>
    bool is_ws(const std::string& s)
    {
        std::istringstream iss(s);
        T x;
        return iss >> x >> std::ws && iss.eof();
    }
    
    template <typename T>
    bool is(const std::string& s)
    {
        std::istringstream iss(s);
        T x;
        return iss >> std::noskipws >> x && iss.eof();
    }
    
    ...
    if (is<double>("3.14E0")) ...
    if (is<std::string>("hello world")) ...; // note: NOT a single string
                                             // as streaming tokenises at
                                             // whitespace by default...
    

    You can specialise the template for any type-specific behaviours you'd like, such as:

    template <>
    bool is<std::string>(const std::string& s)
    {
        return true;
    }
    
    0 讨论(0)
  • 2020-12-19 02:25

    Since no one else has mentioned it: the obvious solution is you want to know whether a string has a given syntax is to use regular expressions. I'm not sure that it's the best solution in this case, since the regular expression for a legal double is fairly complex (and thus easy to get wrong). And your specification is somewhat vague: do you want to accept any string which can be parsed (by >> for example) as a legal double, or only strings can be returned by your doubleToString function? If the former, the simplest solution is probably to convert the string to a double, making sure that there is no error and you have consumed all of the characters (Martin's solution, except that it's silly to make it a template until you need to). If the latter, the easiest solution is to reconvert the double you've found back into a string, using your function, and compare the two strings. (Just to make the difference clear: Martin's function will return true for things like "&nbsp;&nbsp;1.0", "1E2", ".00000000001" and "3.14159265358979323846264338327950288419716939937", which your function will never generate.)

    0 讨论(0)
  • 2020-12-19 02:26

    You can use the Boost lexical_cast to check whether a string contains double or not.

    #include <boost/lexical_cast.hpp> 
    ....
    using boost::lexical_cast; 
    using boost::bad_lexical_cast; 
    ....
    template<typename T> bool isValid(const string& num) { 
       bool flag = true; 
       try { 
          T tmp = lexical_cast<T>(num); 
       } 
       catch (bad_lexical_cast &e) { 
          flag = false; 
       } 
       return flag; 
    } 
    
    int main(){
      // ....
     if (isValid<double>(str))
         cout << "valid double." << endl; 
     else 
         cout << "NOT a valid double." << endl;
      //....
    }
    
    0 讨论(0)
  • 2020-12-19 02:26

    Or use streams directly:

    #include <string>
    #include <sstream>
    #include <iostream>
    
    template<typename T>
    bool isValid(std::string const& num)
    {
        T  value;
        std::stringstream stream(num);
        stream >> value;
    
        // If the stream is already in the error state peak will not change it.
        // Otherwise stream should be good and there should be no more data
        // thus resulting in a peek returning an EOF
        return (stream) &&
               stream.peek() == std::char_traits<typename std::stringstream::char_type>::eof();
    }
    
    int main()
    {
        isValid<double>("55");
    }
    
    0 讨论(0)
  • 2020-12-19 02:27

    You want the strtod function.

    bool isOnlyDouble(const char* str)
    {
        char* endptr = 0;
        strtod(str, &endptr);
    
        if(*endptr != '\0' || endptr == str)
            return false;
        return true;
    }
    
    0 讨论(0)
提交回复
热议问题