zoukankan      html  css  js  c++  java
  • 第20题:表示数值的字符串

    题目描述

    请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串"+100","5e2","-123","3.1416"和"-1E-16"都表示数值。 但是"12e","1a3.14","1.2.3","+-5"和"12e+4.3"都不是。

    测试用例:

    
        Test("Test1", "100", true);
        Test("Test2", "123.45e+6", true);
        Test("Test3", "+500", true);
        Test("Test4", "5e2", true);
        Test("Test5", "3.1416", true);
        Test("Test6", "600.", true);
        Test("Test7", "-.123", true);
        Test("Test8", "-1E-16", true);
        Test("Test9", "1.79769313486232E+308", true);
    
        printf("
    
    ");
    
        Test("Test10", "12e", false);
        Test("Test11", "1a3.14", false);
        Test("Test12", "1+23", false);
        Test("Test13", "1.2.3", false);
        Test("Test14", "+-5", false);
        Test("Test15", "12e+5.4", false);
        Test("Test16", ".", false);
        Test("Test17", ".e1", false);
        Test("Test18", "e1", false);
        Test("Test19", "+.", false);
        Test("Test20", "", false);
        Test("Test21", nullptr, false);

    思路:

    1.形如A[.[B]][e|EC]或.[B][e|EC]的都来表示数值,其中AC为有符号整型,B为无符号整型

    2.小数点前后,只要有一个整型即可,且小数点后的整型是无符号整型。
    3.指数前后必须要都有有符号整型。
    4.字符串里不能有除了0-9的其它字符。

    第一遍

                           
    // 整数的格式可以用[+|-]B表示, 其中B为无符号整数
    bool scanInteger(const char** str) 
    {
    	//1.如果前面有[+|-]号,往后移一位
    	if (**str == '+' || **str == '-')
    		(*str)++;//注意这里(*str) 要打括号 ++比*优先级高。
    
    	//2.返回无整形扫描
    	return scanUnsignedInteger(str);
    }
    
    bool scanUnsignedInteger(const char** str)
    {
    	//1.定义before指针,指向str第一个字符
    	const char* before = *str;
    	//2.如果*str不为空,且是数字的话,进行下一个字符
    	while (*str&&**str >= '0'&&**str <= '9')
    		(*str)++;
    	//3.如果有数字字符的话,就返回真,否则返回假
    	return before < *str ? true : false;
    }
    
    // 数字的格式可以用A[.[B]][e|EC]或者.B[e|EC]表示,其中A和C都是
    // 整数(可以有正负号,也可以没有),而B是一个无符号整数
    bool isNumeric(const char* str)
    {
    	//1.如果为空
    	if (!str)
    		return false;
    
    	//2.判断第一个字符是否是数值,A  
    	bool numeric = scanInteger(&str);
    
    	//3.如果遇到小数点 . 用||,因为小数点有三种情况,1.1/0.1/1.0
    	if (*str == '.')
    	{
    		//3.1 str++成为左值,因为要取地址
    		str++;
    		//3.2 细节:不用return 更新numeric的值
    		numeric= scanUnsignedInteger(&str) || numeric  ;//细节:先扫描小数位B,是否为unsigned,因为如果numeric==ture就不会扫描小数位了
    	}
    
    	//4.如果遇到指数e|E ,用&&,因为指数前后必须都要是数字, e2,1e是错的
    	if (*str == 'e' || *str == 'E')
    	{
    		str++;
    		numeric= numeric&&scanInteger(&str);
    	}
    
    	//5.返回是否为数值numeric,且已经扫描到了''
    	return numeric&&*str=='';
    }

    bug

    1.左值:问题描述:
    想给一个指向int型的指针赋值,以下为代码,就会在第三行报错“表达式必须为左值或者函数操作符”

    int *P;
    int a;
    p=&(a+2);

    改写成以下代码就不会报错了

    int *P;
    int a,b;
    b=a+2;
    p=&b;


    问题分析:
    分析一下为什么第一种写法就是错的, 究其原因就是取地址操作符&必须作用于一个左值,而(a+2)明显是一个表达式,不是一个合法的左值,当然要报错了。

    左值与右值这两概念是从 c 中传承而来的,在 c 中,左值既能够出现在等号左边也能出现在等号右边,右值则是只能出现在等号右边。右值就是一个临时变量(没有在程序中申明),只有临时的地址空间,左值是在程序中具体定义了的,有其地址空间。换句话说,使用取地址符&对某个值取地址,左值能够得到地址,而右值不能得到地址! 

    2.||的顺序

     //3.2 细节:不用return 更新numeric的值
            numeric= scanUnsignedInteger(&str) || numeric  ;//细节:先扫描小数位B,是否为unsigned,因为如果numeric==ture就不会扫描小数位了

    3.函数返回值,不能直接返回numeric,还要检查是否到了字符串末尾

    //5.返回是否为数值numeric,且已经扫描到了''
        return numeric&&*str=='';

     第二遍

    class Solution {
    public:
        
        //形如A[.[B]][e|EC]或.[B][e|EC]的都来表示数值,其中AC为有符号整型,B为无符号整型
        //小数点前后,只要有一个整型即可,且小数点后的整型是无符号整型。
        //指数前后必须要都有有符号整型。
        //字符串里不能有除了0-9的其它字符。
        bool scanUnsignedInt(const char** str)
        {
            //1.定义before指针char*保存原来的str
            const char* before = *str;
            //2.如果**str不为结束符,**str的值在0-9,继续往下指
            while(**str!=''&&**str>='0'&&**str<='9')
                (*str)++;
            //3.比较*str和before的位置,判断是否存在数字,返回
            return before<*str?true:false;
        }
        bool scanInt(const char** str)
        {
            //1.如果有正负号,str往后指一个
            if(**str=='+' || **str == '-')
                (*str)++;
            //2.返回扫描无符号整数
            return scanUnsignedInt(str);
        }
        
        bool isNumeric(const char* string)
        {
            //1.判断是否为nullptr
            if(!string)
                return false;
            
            //2.定义标志numeric,表达是否为数字,首先扫描带符号的数值
            bool numeric=scanInt( &string);
            
            //3. 如果遇到小数,小数点后的B应该为无符号整形,小数点前后只要有一个数字就行,所以numeric用||重新赋值,
            //其中||的顺序是:scanUnsigned函数在前,因为numeric为真,就不会判断scanUnsigned函数的值了
            if(*string=='.')
            {
                string++;
                numeric=scanUnsignedInt(&string)||numeric;
            }
            //4.如果遇到指数,指数的前后都应该有数字,所以用&&
            if(*string=='e'||*string=='E')
            {
                string++;
                numeric=scanInt(&string)&&numeric;
            }
            //5.返回numeric,且string扫描到了结束符
            return numeric&&*string=='';
            
        }
    
    };

    网友的

    class Solution {
    public:
        bool isNumeric(char* str) {
            // 标记符号、小数点、e是否出现过
            bool sign = false, decimal = false, hasE = false;
            for (int i = 0; i < strlen(str); i++) {
                if (str[i] == 'e' || str[i] == 'E') {
                    if (i == strlen(str)-1) return false; // e后面一定要接数字
                    if (hasE) return false;  // 不能同时存在两个e
                    hasE = true;
                } else if (str[i] == '+' || str[i] == '-') {
                    // 第二次出现+-符号,则必须紧接在e之后
                    if (sign && str[i-1] != 'e' && str[i-1] != 'E') return false;
                    // 第一次出现+-符号,且不是在字符串开头,则也必须紧接在e之后
                    if (!sign && i > 0 && str[i-1] != 'e' && str[i-1] != 'E') return false;
                    sign = true;
                } else if (str[i] == '.') {
                  // e后面不能接小数点,小数点不能出现两次
                    if (hasE || decimal) return false;
                    decimal = true;
                } else if (str[i] < '0' || str[i] > '9') // 不合法字符
                    return false;
            }
            return true;
        }
    };

    编译原理中自动机(你是魔鬼吗?

    class Solution {
    public:
        bool isNumeric(char* string)
        {
            int i = 0;
            if(string[i]=='+' || string[i]=='-' || IsNum(string[i])){
                while(string[++i]!='' && IsNum(string[i]));
                if(string[i]=='.'){
                    if(IsNum(string[++i])){
                        while(string[++i]!='' && IsNum(string[i]));
                        if(string[i]=='e'||string[i]=='E'){
                            i++;
                            if(string[i]=='+' || string[i]=='-' || IsNum(string[i])){
                                while(string[++i]!='' && IsNum(string[i]));
                                if(string[i]=='') return true;
                                else return false;
                            }else return false;
                        }else if(string[i]=='') return true;
                        else return false;
                    }else if(string[++i]=='') return true;
                    else return false;
                }else if(string[i]=='e'||string[i]=='E'){
                    i++;
                    if(string[i]=='+' || string[i]=='-' || IsNum(string[i])){
                        while(string[++i]!='' && IsNum(string[i]));
                        if(string[i]=='') return true;
                        else return false;
                    }else return false;
                }else if(string[i]=='') return true;
                else return false;           
            }else return false;
        }
         
        bool IsNum(char ch)
        {
            if(ch<'0'||ch>'9') return false;
            else return true;
        }
    };

    正则表达式(魔鬼

    //正则表达式解法
    public class Solution {
        public boolean isNumeric(char[] str) {
            String string = String.valueOf(str);
            return string.matches("[\+\-]?\d*(\.\d+)?([eE][\+\-]?\d+)?");
        }
    }
    /*
    以下对正则进行解释:
    [\+\-]?            -> 正或负符号出现与否
    \d*                 -> 整数部分是否出现,如-.34 或 +3.34均符合
    (\.\d+)?           -> 如果出现小数点,那么小数点后面必须有数字;
                            否则一起不出现
    ([eE][\+\-]?\d+)? -> 如果存在指数部分,那么e或E肯定出现,+或-可以不出现,
                            紧接着必须跟着整数;或者整个部分都不出现
    */
     
     
    //参见剑指offer
    public class Solution {
        private int index = 0;
      
        public boolean isNumeric(char[] str) {
            if (str.length < 1)
                return false;
             
            boolean flag = scanInteger(str);
             
            if (index < str.length && str[index] == '.') {
                index++;
                flag = scanUnsignedInteger(str) || flag;
            }
             
            if (index < str.length && (str[index] == 'E' || str[index] == 'e')) {
                index++;
                flag = flag && scanInteger(str);
            }
             
            return flag && index == str.length;
             
        }
         
        private boolean scanInteger(char[] str) {
            if (index < str.length && (str[index] == '+' || str[index] == '-') )
                index++;
            return scanUnsignedInteger(str);
             
        }
         
        private boolean scanUnsignedInteger(char[] str) {
            int start = index;
            while (index < str.length && str[index] >= '0' && str[index] <= '9')
                index++;
            return start < index; //是否存在整数
        }
    }
    
  • 相关阅读:
    [恢]hdu 2002
    [恢]hdu 2001
    [恢]hdu 2003
    [恢]hdu 1000
    ActionButton的处理流程 天龙packet
    ogre visibleflag
    Scaleform Gfx的Demo
    cegui 自定义控件
    PixWin
    在Ogre中加载自己的资源包
  • 原文地址:https://www.cnblogs.com/lightmare/p/10398761.html
Copyright © 2011-2022 走看看