Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/306.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 测试C++;98字符串是科学记数法中的数字_C++_C++03 - Fatal编程技术网

C++ 测试C++;98字符串是科学记数法中的数字

C++ 测试C++;98字符串是科学记数法中的数字,c++,c++03,C++,C++03,我有一个字符串变量,它可以是以下三种情况之一: 数 科学记数法中的数字 正文 在案例1和案例3中,我不想做任何事情并传递数据。但在第二种情况下,我需要把它转换成一个正则数。如果我总是简单地将变量转换为一个正则数,那么当它包含实际文本时,它将变为“0”。所以我需要知道字符串是否是科学记数法中的数字。显然,肮脏的答案是这样一种算法: .123 .123E3 123. 123.E+3 只要看到数字,就可以遍历字符串。如果遇到的第一个字母是“e”或“e”,后面跟着“+”或“-”或更多的数字,那么它就是

我有一个
字符串
变量,它可以是以下三种情况之一:

  • 科学记数法中的数字
  • 正文
  • 在案例1和案例3中,我不想做任何事情并传递数据。但在第二种情况下,我需要把它转换成一个正则数。如果我总是简单地将变量转换为一个正则数,那么当它包含实际文本时,它将变为“0”。所以我需要知道字符串是否是科学记数法中的数字。显然,肮脏的答案是这样一种算法:

    .123
    .123E3
    123.
    123.E+3
    
    只要看到数字,就可以遍历字符串。如果遇到的第一个字母是“e”或“e”,后面跟着“+”或“-”或更多的数字,那么它就是科学记数法中的数字,否则它只是一个常规数字或文本

    但是我认为在C++98中有更好的方法来实现这一点(没有boost)。有什么内置的方法可以帮助您吗?即使它只是一个尝试/抓住的东西

    编辑问题已关闭,因为它被假定为家庭作业。这不是家庭作业。因此,它应该重新开放。另外,为了澄清,由于技术限制,我不得不使用C++98

    根据我最初的想法,我画了一个建议的有限状态automota(“other”表示没有为给定状态指定的所有字符)。我相信这是正确的

    应接受的一些示例输入:

    1.453e-8
    0.05843E5
    8.43e6
    5.2342E-7
    
    应失败的一些示例输入:

    hello
    03HX_12
    8432
    8432E
    e-8
    fail-83e1
    

    您的自动机的主要问题在于规格/要求方面:它要求小数点两侧有一个或多个数字,拒绝这样的输入:

    .123
    .123E3
    123.
    123.E+3
    
    目前尚不清楚是否应拒绝这些建议;一些编程语言允许这些形式。拒绝没有尾数的东西可能是个好主意,不过:

    .
    .E+03
    
    如果这不是故意的,而是遗漏了需求,那么必须调整状态机。因为现在元素是可选的,所以修复状态机的最简单方法是让它成为非确定性(NFA图)。这只会带来不必要的困难。因为您最终还是要编写代码,所以使用特别的过程代码最容易处理这个问题

    与传统自动机的形式化处理相比,特殊过程代码的优势在于前瞻性:它可以像自动机一样在不消耗输入的情况下偷看下一个字符,并且基于前瞻性,它可以决定是否消耗该字符,而不依赖于在多个代码路径之间的转换。换句话说,伪代码:

    have_digits_flag = false
    
    while (string begins with a digit character) {
       have_digits_flag = true
       consume digit character 
    }
    
    if (!string begins with a decimal point)
       goto bad;
    consume decimal point
    
    while (string begins with digit) {
      consume digit
      have_digits_flag = true;
    }
    
    if (!have_digits_flag)
      goto bad; // we scanned just a decimal point not flanked by digits!
    
    if (string begins with e or E) {
       consume character
       if (string begins with + or -)
         consume character
       if (!string begins with digit)
         goto bad;
       while (string begins with digit)
         consume character
    }
    
    if (string is empty)
      return true;
    
    // oops, trailing junk
    
    bad:
      return false;
    
    “stringstart with”操作显然必须是安全的,以防字符串为空。空字符串根本不满足任何字符的“字符串以开头”谓词

    如何实现“消费角色”取决于您。您可以从
    std::string
    对象中删除一个字符,或者在其中移动一个迭代器以指示输入位置

    这种方法的缺点是效率不高。在这里,这也许无关紧要,但一般来说,临时代码会遇到一个问题,即它会针对前瞻性测试多个案例。在一个复杂的模式中,这些可能是很多的。一个表驱动的自动机永远不需要第二次查看任何输入符号。

    使用一个非常好的状态机来解析数字。它不太严格,但不接受像“e”或“-.e2”这样的垃圾

    它是:

    • “-”,或
    • 没什么

    • “0”,或
    • (一位数字[1-9],后跟零或多个[0-9])

    • (“.”后跟一个或多个[0-9]),或
    • 没什么

    • ((('e'或'e'),后跟(+'或'-'或无),后跟零或更多[0-9]),或
    • 没什么
    如果希望更正式地查看指定的格式,请参阅

    这就是我在JSON数字解析器中所做的(我支持允许全范围64位整数的扩展格式,JSON规范说整数不能可靠地位于-2^53+1到2^53-1范围之外):

    模板
    静态输入提取器编号(变量和结果、输入st、输入en);
    

    模板
    inputitJSONParser::extractNumber(变量和结果、inputitST、inputitEN)
    {
    如果(st==en)
    parseError(“输入结束时的预期数字”);
    向量文本;
    自动接受=[&]{
    如果(st==en)
    parseError(“输入结束时的预期数字”);
    text.emplace_back(*st++);
    };
    //-?(?:0 |[1-9][0-9]*)(?:\[0-9]+)(?:[eE][+-]?[0-9]+)?
    //A、B、C、D、E
    bool isFloatingPoint=false;
    如果(*st='-'))
    {
    //A
    接受();
    }
    如果(*st==“0”)
    {
    //B
    接受();
    }
    否则如果(标准::isdigit(*st,cLocale))
    {
    //C
    做
    {
    接受();
    }
    while(st!=en&std::isdigit(*st,cLocale));
    }
    其他的
    {
    解析错误(“无效数字”);
    }
    如果(st!=en&&*st=='。)
    {
    接受();
    isFloatingPoint=true;
    //D
    while(st!=en&std::isdigit(*st,cLocale))
    接受();
    }
    如果(st!=en&(*st=='E'| |*st=='E'))
    {
    isFloatingPoint=true;
    //E
    接受();
    if(st!=en&(*st='+'| |*st=='-'))
    接受();
    if(st==en | |!std::isdigit(*st,cLocale))
    解析错误(“无效数字”);
    while(st!=en&std::isdigit(*st,cLocale))
    接受();
    }
    文本。向后放置(0);
    如果(isFloatingPoint)
    赋值(std::atof(text.data());
    其他的
    赋值(std::int64_t(std::atol(text.data()));
    返回st;
    }
    
    我不得不稍微调整一下,因为周围的实现确保
    st
    不会等于
    en
    on
    template<typename InputIt,
             typename V = typename 
                std::iterator_traits<InputIt>::value_type>
    static InputIt extractNumber(Variant& result, InputIt st, InputIt en);
    
    template<typename InputIt, typename V>
    InputIt JsonParser::extractNumber(Variant& result, InputIt st, InputIt en)
    {
        if (st == en)
            parseError("Expected number at end of input");
    
        std::vector<V> text;
    
        auto accept = [&] {
            if (st == en)
                parseError("Expected number at end of input");
            text.emplace_back(*st++);
        };
    
        // -?(?:0|[1-9][0-9]*)(?:\.[0-9]+)?(?:[eE][+-]?[0-9]+)?
        // A    B C              D            E
    
        bool isFloatingPoint = false;
    
        if (*st == '-')
        {
            // A
            accept();
        }
    
        if (*st == '0')
        {
            // B
            accept();
        }
        else if (std::isdigit(*st, cLocale))
        {
            // C
            do
            {
                accept();
            }
            while (st != en && std::isdigit(*st, cLocale));
        }
        else
        {
            parseError("Invalid number");
        }
    
        if (st != en && *st == '.')
        {
            accept();
    
            isFloatingPoint = true;
    
            // D
            while (st != en && std::isdigit(*st, cLocale))
                accept();
        }
    
        if (st != en && (*st == 'E' || *st == 'e'))
        {
            isFloatingPoint = true;
    
            // E
            accept();
    
            if (st != en && (*st == '+' || *st == '-'))
                accept();
    
            if (st == en || !std::isdigit(*st, cLocale))
                parseError("Invalid number");
    
            while (st != en && std::isdigit(*st, cLocale))
                accept();
        }
    
        text.emplace_back(0);
    
        if (isFloatingPoint)
            result.assign(std::atof(text.data()));
        else
            result.assign(std::int64_t(std::atoll(text.data())));
    
        return st;
    }
    
    bool is_valid(std::string src){
        std::stringstream ss;
        ss << src;
        double d=0;
        ss >> d; 
        if (ss){
           return true;
        }
        else{
           return false;
        }
    }
    
    bool is_scientific_notation(string input) {
        int state = 0;
        for (string::size_type i = 0; i < input.size(); i++) {
            char character = input.at(i);
            //cout << character << endl;
            switch(state) {
                case 0: {
                    // state 0: accept on '. or' '-' or digit
                    if (character == '.') {
                        state = 3;
                    } else if (character == '-') {
                        state = 1;
                    } else if (isdigit(character)) {
                        state = 2;
                    } else {
                        goto reject; // reject 
                    }
                    break;
                }
                case 1: {
                    // state 1: accept on '. or digit
                    if (character == '.') {
                        state = 3;
                    } else if (isdigit(character)) {
                        state = 2;
                    } else {
                        goto reject; // reject 
                    }
                    break;
                }
                case 2: {
                    // state 2: accept on '.' or 'e' or 'E' digit
                    if (character == '.') {
                        state = 4;
                    } else if ((character == 'e') || (character == 'E')) {
                        state = 5;
                    } else if (isdigit(character)) {
                        state = 2;
                    } else {
                        goto reject; // reject 
                    }
                    break;
                }
                case 3: {
                    // state 3: accept on digit
                    if (isdigit(character)) {
                        state = 4;  
                    } else {
                        goto reject; // reject 
                    }
                    break;
                }
                case 4: {
                    // state 4: accept on 'e' or 'E' or digit
                    if ((character == 'e') || (character == 'E')) {
                        state = 5;
                    } else if (isdigit(character)) {
                        state = 4;  
                    } else {
                        goto reject; // reject 
                    }
                    break;
                }
                case 5: {
                    // state 5: accept on '+' or '-' or digit
                    if ((character == '+') || (character == '-')) {
                        state = 6;
                    } else if (isdigit(character)) {
                        state = 6;  
                    } else {
                        goto reject; // reject 
                    }
                    break;
                }
                case 6: {
                    // state 6: accept on digit
                    if (isdigit(character)) {
                        state = 6;  
                    } else {
                        goto reject; // reject 
                    }
                    break;
                }
            }
        }
        if (state == 6) {
            return true;
        } else {
            reject:
                return false;
        }
    }
    
    // is_scientific_notation should return true
    cout << ((is_scientific_notation("269E-9")) ? ("pass") : ("fail")) << endl;
    cout << ((is_scientific_notation("269E9")) ? ("pass") : ("fail")) << endl;
    cout << ((is_scientific_notation("269e-9")) ? ("pass") : ("fail")) << endl;
    cout << ((is_scientific_notation("1.453e-8")) ? ("pass") : ("fail")) << endl;
    cout << ((is_scientific_notation("8.43e+6")) ? ("pass") : ("fail")) << endl;
    cout << ((is_scientific_notation("5.2342E-7")) ? ("pass") : ("fail")) << endl;
    cout << ((is_scientific_notation(".2342E-7")) ? ("pass") : ("fail")) << endl;
    cout << ((is_scientific_notation("8.e+2")) ? ("pass") : ("fail")) << endl;
    cout << ((is_scientific_notation("-853.4E-2")) ? ("pass") : ("fail")) << endl;
    
    // is_scientific_notation should return false
    cout << ((is_scientific_notation("hello")) ? ("fail") : ("pass")) << endl;
    cout << ((is_scientific_notation("03HX_12")) ? ("fail") : ("pass")) << endl;
    cout << ((is_scientific_notation("8432")) ? ("fail") : ("pass")) << endl;
    cout << ((is_scientific_notation("8432E")) ? ("fail") : ("pass")) << endl;
    cout << ((is_scientific_notation("fail-83e1")) ? ("fail") : ("pass")) << endl;
    cout << ((is_scientific_notation(".e8")) ? ("fail") : ("pass")) << endl;
    cout << ((is_scientific_notation("E-8")) ? ("fail") : ("pass")) << endl;
    cout << ((is_scientific_notation("2e.2")) ? ("fail") : ("pass")) << endl;
    cout << ((is_scientific_notation("-E3")) ? ("fail") : ("pass")) << endl;
    
    pass
    pass
    pass
    pass
    pass
    pass
    pass
    pass
    pass
    pass
    pass
    pass
    pass
    pass
    pass
    pass
    pass
    pass