精华内容
下载资源
问答
  • Delphi字 符 正 则 表 达 的 一 段 示 例 代 码
  • 字符算术表达式求值

    千次阅读 2018-08-25 11:06:24
    * 算术表达式求值 该类是一个能够解释给定字符所表达的运算并计算得到结果的程序 * * 控制台输入一个需要计算的算术表达式:由左右括号、运算符、算术表达式组成的表达式 运算优先级有括号()确定。运算符支持....

      算术表达式求值,控制台输入一个需要计算的算术表达式:由左右括号、运算符、算术表达式组成的表达式 运算优先级有括号()确定。运算符支持+、-、*和接收一个参数的算术平方根。

    /**
     * 算术表达式求值 该类是一个能够解释给定字符串所表达的运算并计算得到结果的程序
     * 
     * 控制台输入一个需要计算的算术表达式:由左右括号、运算符、算术表达式组成的表达式 运算优先级有括号()确定。运算符支持+、-、*和接收一个参数的算术平方根。
     * 计算过程: 用两个栈:一个栈存运算符,一个存操作数 运算式忽略左括号 将操作数压栈 将运算符压栈
     * 在遇到右括号时,弹出一个运算符,弹出所需数量的操作数,并将运算符合操作数的运算结果压入操作数栈
     * 最后操作数栈中存的即是 表达式的值
     */
    public class Evaluate {
        public static void main(String[] args) {
            // 运算符栈
            Stack<String> ops = new Stack<>();
            // 操作数栈
            Stack<Double> vals = new Stack<>();
            System.out.println("请输入算术表达式 一个字符一行:");
            Scanner scanner = new Scanner(System.in);
            while (scanner.hasNext()) { // ctrl+z结束
                String s = scanner.next().trim();
                // 如果是字符 压入运算符栈中
                if (s.equals("(")) ;
                else if (s.equals("+")) {
                    ops.push(s);
                } 
                else if (s.equals("*")) {
                    ops.push(s);
                } else if (s.equals("/")) {
                    ops.push(s);
                } else if (s.equals("sqrt")) {
                    ops.push(s);
                } else if (s.equals(")")) {
                    String op = ops.pop();
                    double val = vals.pop();
                    if (op.equals("+"))
                        val = vals.pop() + val;
                    else if (op.equals("-"))
                        val = vals.pop() - val;
                    else if (op.equals("*"))
                        val = vals.pop() * val;
                    else if (op.equals("/")) {
                        if (val == 0) {
                            System.out.println("被除数为0");
                            return;
                        }
                        val = vals.pop() / val;
                    } else if (op.equals("sqrt"))
                        val = Math.sqrt(val);
                    vals.push(val);
                } else { // 若既不是运算符也不是括号,则将它作为double压入栈
                    vals.push(Double.parseDouble(s));
                }
            }
            System.out.println(vals.pop());
        }
    }
    
    展开全文
  • 将字符表达式,进行加减乘除等逻辑运算,进行逻辑运算。 1.中缀转后缀。 2.后缀求值。
  • 在程序设计中,可能碰到需要对字符数学表达式求值的问题,常用的方法是解析表达式,生成二叉树,然后进行计算。...程序解析字符串表达式,将其转换为逆波兰,然后生成表达式二叉树,最后计算表达式值。
  • 波兰、逆波兰表达式求值

    万次阅读 多人点赞 2018-12-30 11:22:11
     《数据结构》中关于栈的解释经常会涉及到逆波兰式,波兰式,中缀式表达式的求值问题。但是,十分惭愧,整个大一阶段, 数据结构的课程没有上够5节,没有意识要学习,吃亏真的很大,只能现在恶补了。废话不说了,...

    波兰式、逆波兰式与表达式求值

      《数据结构》中关于栈的解释经常会涉及到逆波兰式,波兰式,中缀式表达式的求值问题。但是,十分惭愧,整个大一阶段,

    数据结构的课程没有上够5节,没有意识要学习,吃亏真的很大,只能现在恶补了。废话不说了,进入正题。

     

    1. 中缀表达式

           人类最熟悉的一种表达式1+2,(1+2)*3,3+4*2+4等等都是中缀表示法。对于人们来说,也是最直观的一种求值方式,先算括号里的,
    然后算乘除,最后算加减,但是,计算机处理中缀表达式却并不方便,因为没有一种简单的数据结构可以方便从一个表达式中间抽出
    一部分算完结果,再放进去,然后继续后面的计算(链表也许可以,但是,代价也是不菲)。
           在介绍前缀,后缀表达式之前,我想先通过我们最熟悉的中缀表达式画出一棵语法树来直观认识前后缀表达式。以A+B*(C-D)-E*F为例:

    则中缀表达式得名于它是由相应的语法树的中序遍历的结果得到的。

     

     

    2. 前缀缀表达式

     

      前缀表达式又叫做波兰式。同样的道理,表达式的前缀表达式是由相应的语法树的前序遍历的结果得到的。

    如上图的前缀表达式为- + A * B - C D * E F

    由前缀表达式求出结果有下面两种思路:

      1.从左至右扫描表达式,如果一个操作符后面跟着两个操作数时,则计算,然后将结果作为操作数替换(这个操作符和两个操作数),

    重复此步骤,直至所有操作符处理完毕。如-+A*B-CD*EF,扫描到-CD时,会计算C-D=C',表达式变成:-+A*BC'*EF

    继续扫描到*BC',计算B*C'=B',表达式变成:-+AB'*EF,继续+AB',依此类推。

      2.由1.知,要多遍扫描表达式,并且需要将3个字符替换成1个,比较繁锁,我们可以用一个栈S2来实现计算,扫描从右往左进行,

    如果扫描到操作数,则压进S2,如果扫描到操作符,则从S2弹出两个操作数进行相应的操作,并将结果压进S2(S2的个数出2个进1个),

    当扫描结束后,S2的栈顶就是表达式结果。

     

    3. 后缀表达式

      后缀表达式又叫做逆波兰式。它是由相应的语法树的后序遍历的结果得到的。如上图的后缀表达式为:

    A B C D - * + E F * -

    由前缀表达式求出结果十分方便,只需要用一个栈实现:

    我们可以用一个栈S2来实现计算,扫描从左往右进行,如果扫描到操作数,则压进S2,如果扫描到操作符,则从S2弹出两个操作数

    进行相应的操作,并将结果压进S2(S2的个数出2个进1个),当扫描结束后,S2的栈顶就是表达式结果。后缀表达式和前缀表达式看

    起来就像一对逆过程,实际上并不是这样子,因为字符读取的时候都是从左往右的,所以,前缀表达式往往需要用两个栈来计算,

    其中一个栈用来预处理:将字符串倒序压进栈中。

     

    4. 中缀表达式转换成后缀表达式

      既然中缀表达式对于计算机的运算并不便利,而前缀后缀表达式的计算相对简单方便。因此,找到一种途径将中缀表达式

    转换成前缀后缀表达式就十分重要。实际上,二者的转换算法看起来也很像一个逆过程。因此,我们着重讨论中缀转后缀。

    从理论上讲,已知一棵二叉树的中序遍历序列,要求出它的后序遍历序列是不唯一的,即文法是有多义性的。但是,在这

    里加上了优先级这一限制条件,转换就变得唯一了。

     

    算法:中缀表达式转换成后缀表达式

    输入:中缀表达式串

    输出:后缀表达式串

    PROCESS BEGIN:

       1.从左往右扫描中缀表达式串s,对于每一个操作数或操作符,执行以下操作;

                    2.IF (扫描到的s[i]是操作数DATA)

             将s[i]添加到输出串中;

                   3.IF (扫描到的s[i]是开括号'(')

                            将s[i]压栈;

                   4.WHILE (扫描到的s[i]是操作符OP)

                           IF (栈为空 或 栈顶为'(' 或 扫描到的操作符优先级比栈顶操作符高)

                                 将s[i]压栈;

                                 BREAK;

                           ELSE

                                 出栈至输出串中

                   5.IF (扫描到的s[i]是闭括号')')

                           栈中运算符逐个出栈并输出,直到遇到开括号'(';

                           开括号'('出栈并丢弃;

                   6.返回第1.步

             7.WHILE (扫描结束而栈中还有操作符)

                            操作符出栈并加到输出串中

    PROCESS END

     

    4. 中缀表达式转换成前缀表达式

      中缀表达式转换成前缀表达式和中缀表达式转换成后缀表达式十分类似,只需要将扫描方向由前往后变成由后往前,

    将'('改为')',')'改为'(',注意其中一个判断优先级的地方需要由>=变成>.

      至此,理论基础已经讲完了,用一道OJ题目来客观认识一下会比较好理解。HDU2127

    Polish notation

    Time Limit: 10000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 112    Accepted Submission(s): 32

    Problem Description

    Now, give you a string of standard arithmetic expressions, please tell me the Polish notation and the value of expressions.

    Input

    There're have multi-case. Every case put in one line, the expressions just contain some positive integers(all less than 100, the number of integers less than 20), bi-operand operators(only have 3 kinds : +,-,*) and some brackets'(',')'.
    you can assume the expressions was valid.

    Output

    Each case output the Polish notation in first line, and the result of expressions was output in second line.
    all of the answers are no any spaces and blank line.the answer will be not exceed the 64-signed integer.

    Sample Input

     

    1+2-3*(4-5) 1+2*(3-4)-5*6

    Sample Output

     

    Case 1: - + 1 2 * 3 - 4 5 6 Case 2: - + 1 * 2 - 3 4 * 5 6 -31

    Author

    威士忌

    Source

    HDU 2007-10 Programming Contest

     

    解释:

      网上很少这道题的题解,我先写一个吧,前面题目扯了一堆废话(我全删掉了),只有一句最重要的:给你中缀表达式,求出它的波兰式并计算出

    结果。题目是很裸的将中缀表达式转换成前缀表达式,再进行计算出结果,可以直接套上面的算法。但是,这里有一些点易错点需要注意:

         1.转化后的前缀表达式需要留一个空格

      2.因为数字并不是1位的,因为数字<100,有可能有两位,所以,不能只读取一个字符做为数字,需要读取所有的数字,具体看代码对数字的处理

      3.要注意有可能超过int的范围,一开始就想当然地用int,结果WA,还要注意将字符串转化为__int64

    #include <iostream>
    #include <string>
    #include <algorithm>
    using namespace std;
    
    char stack[500];					//定义顺序栈,其中top==0表示栈为空;
    int top;							//栈顶指针,为0表示栈为空;
    char output[500], input[500];		//波兰式
    int outLen;
    
    int priority(char op)				//判断运算符级别函数;其中* /的级别为2,+ -的级别为1;
    {
    	if (op=='+' || op=='-')
    		return 1;
    	if (op=='*' || op=='/')
    		return 2;
    	else
    		return 0;
    }
    
    bool isOperator(char op)				//判断输入串中的字符是不是操作符,如果是返回true
    {
    	return (op=='+' || op=='-' || op=='*' || op=='/');
    }
    
    void Polish(char *s,int len)			//将一个中缀串转换为前缀串,
    {
    	memset(output,'\0',sizeof output);	//输出串
    	outLen = 0;
    	for (int i=len-1; i >= 0; --i)		//1)求输入串的逆序。
    	{
    		if (isdigit(s[i]))				//经验见:http://blog.csdn.net/linraise/article/details/18566319#comments
    		{
    			output[outLen++] = s[i];	//3)假如是操作数,把它添加到输出串中。
    			while (i-1 >= 0 && isdigit(s[i-1]))
    			{
    				output[outLen++] = s[i-1];
    				--i;
    			}
    			output[outLen++] = ' ';		//空格隔开
    		}
    		if (s[i]==')')				    //4)假如是闭括号,将它压栈。
    		{
    			++top;
    			stack[top] = s[i];
    		}
    		while (isOperator(s[i]))		//5)如果是运算符,执行算法对应操作;
    		{												//>=很重要
    			if (top==0 || stack[top]==')' || priority(s[i]) >= priority(stack[top])) //空栈||或者栈顶为)||新来的元素优先级更高
    			{
    				++top;
    				stack[top] = s[i];
    				break;
    			}
    			else
    			{
    				output[outLen++] = stack[top];
    				output[outLen++] = ' ';
    				--top;
    			}
    		}
    		if (s[i]=='(')					//6)假如是开括号,栈中运算符逐个出栈并输出,直到遇到闭括号。闭括号出栈并丢弃。
    		{
    			while (stack[top]!=')')
    			{
    				output[outLen++] = stack[top];
    				output[outLen++] = ' ';
    				--top;
    			}
    			--top;	// 此时stack[top]==')',跳过)
    		}
    		//7)假如输入还未完毕,跳转到步骤2。
    	}
    	while (top!=0)						//8)假如输入完毕,栈中剩余的所有操作符出栈并加到输出串中。
    	{
    		output[outLen++] = stack[top];
    		output[outLen++] = ' ';
    		--top;
    	}
    }
    
    char DstBuf[200];
    char* OP(char* op1,char* op2,char op)
    {
    	__int64 res = 0;
    	if (op=='+')
    		res = _atoi64(op1) + _atoi64(op2);
    	else if (op=='-')
    		res = _atoi64(op1) - _atoi64(op2);
    	else if (op=='*')
    		res = _atoi64(op1) * _atoi64(op2);
    	else if (op=='/')
    		res = _atoi64(op1) / _atoi64(op2);
    	_i64toa(res,DstBuf,10);
    	return DstBuf;
    }
    
    char cSt1[200][80], cSt2[200][80];
    __int64 calc(char *s)				//波兰式需要用两个栈,逆波兰式只需要一个栈
    {
    	int top1=0, top2=0, i;
    	for (i=0; s[i]; ++i)
    	{
    		if (s[i] && s[i] != ' ')
    		{
    			++top1;
    			sscanf(s+i,"%s",cSt1[top1]);		//初始化其中一个栈
    			while (s[i] && s[i] != ' ')
    				++i;
    		}
    	}
    	while (top1 != 0)	//栈不空
    	{
    		if (!isdigit(cSt1[top1][0]))	//是操作符
    		{
    			OP(cSt2[top2], cSt2[top2-1], cSt1[top1][0]);
    			memcpy(cSt2[top2-1],DstBuf,sizeof DstBuf);
    			--top2;						//操作数栈:出栈俩,进栈一
    			--top1;						//操作符出栈
    		}
    		else
    		{
    			++top2;						//数进操作数栈
    			memcpy(cSt2[top2],cSt1[top1],sizeof cSt1[top1]);
    			--top1;						//操作符出栈
    		}
    	}
    	return _atoi64(cSt2[1]);
    }
    int main()
    {
    #ifndef ONLINE_JUDGE
    	freopen("2.txt","r",stdin);
    #endif
    
    	int T = 1;
    	while (gets(input))
    	{
    		Polish(input, strlen(input));
    		reverse(output,output+outLen-1);
    		output[outLen-1] = '\0';
    		printf("Case %d:\n%s\n",T++,output);
    		printf("%I64d\n",calc(output));
    	}
    	return 0;
    }

    做完了波兰式,再看一个逆波兰式的题:HDU1237
    这道是裸的逆波兰,只是简化版本的,我用上面的算法往上一交,结果WA,测试了一下这个用例1 - 3 + 4,结果输出-6,显然是优先级顺序没有处理好,

    改了一下prirority就行了

    更简单的做法可以看这里,本质上是简化了的逆波兰式解法。

    #include <iostream>
    #include <string>
    #include <algorithm>
    using namespace std;
    
    char stack[500];					//定义顺序栈,其中top==0表示栈为空;
    int top;							//栈顶指针,为0表示栈为空;
    char output[500], input[500];		//波兰式
    int outLen;
    
    int priority(char op)				//判断运算符级别函数;其中* /的级别为2,+ -的级别为1;
    {
    	if (op=='+' || op=='-')
    		return 1;
    	if (op=='*' || op=='/')
    		return 2;
    	else
    		return 0;
    }
    
    bool isOperator(char op)				//判断输入串中的字符是不是操作符,如果是返回true
    {
    	return (op=='+' || op=='-' || op=='*' || op=='/');
    }
    
    void rePolish(char *s,int len)			//将一个中缀串转换为后缀串,
    {
    	memset(output,'\0',sizeof output);	//输出串
    	outLen = 0;
    	for (int i=0; i < len; ++i)			//1)求输入串的逆序。
    	{
    		if (isdigit(s[i]))				//经验见:http://blog.csdn.net/linraise/article/details/18566319#comments
    		{
    			output[outLen++] = s[i];		//3)假如是操作数,把它添加到输出串中。
    			while (i+1 < len && isdigit(s[i+1]))
    			{
    				output[outLen++] = s[i+1];
    				++i;
    			}
    			output[outLen++] = ' ';		//空格隔开
    		}
    		if (s[i]=='(')					//4)假如是闭括号,将它压栈。
    		{
    			++top;
    			stack[top] = s[i];
    		}
    		while (isOperator(s[i]))		//5)如果是运算符,执行算法对应操作;
    		{
    			if (top==0 || stack[top]=='(' || priority(s[i]) > priority(stack[top])) //空栈||或者栈顶为)||新来的元素优先级更高
    			{
    				++top;
    				stack[top] = s[i];
    				break;
    			}
    			else
    			{
    				output[outLen++] = stack[top];
    				output[outLen++] = ' ';
    				--top;
    			}
    		}
    		if (s[i]==')')					//6)假如是开括号,栈中运算符逐个出栈并输出,直到遇到闭括号。闭括号出栈并丢弃。
    		{
    			while (stack[top]!='(')
    			{
    				output[outLen++] = stack[top];
    				output[outLen++] = ' ';
    				--top;
    			}
    			--top;	// 此时stack[top]==')',跳过)
    		}
    		//7)假如输入还未完毕,跳转到步骤2。
    	}
    	while (top!=0)						//8)假如输入完毕,栈中剩余的所有操作符出栈并加到输出串中。
    	{
    		output[outLen++] = stack[top];
    		output[outLen++] = ' ';
    		--top;
    	}
    }
    
    double OP(double op1,double op2,char op)
    {
    	double res = 0;
    	if (op=='+')
    		res = op1 + op2;
    	else if (op=='-')
    		res = op1 - op2;
    	else if (op=='*')
    		res = op1 * op2;
    	else if (op=='/')
    		res = op1 / op2;
    	return res;
    }
    
    double cSt1[200];
    double calc(char *s)				//波兰式需要用两个栈,逆波兰式只需要一个栈
    {
    	char dst[80];
    	int top1=0, i;
    	for (i=0; s[i]; ++i)
    	{
    		if (s[i] && s[i] != ' ')
    		{
    			sscanf(s+i,"%s",dst);
    			if (isdigit(dst[0]))
    			{
    				++top1;
    				cSt1[top1] = atof(dst);		//进栈
    			}
    			else
    			{
    				cSt1[top1-1] = OP(cSt1[top1-1], cSt1[top1], dst[0]);
    			//	memcpy(cSt1[top1-1],DstBuf,sizeof DstBuf);
    				--top1;						//操作数栈:出栈俩,进栈一
    			}
    			while (s[i] && s[i] != ' ')
    				++i;
    		}
    	}
    	return cSt1[1];
    }
    int main()
    {
    #ifndef ONLINE_JUDGE
    	freopen("2.txt","r",stdin);
    #endif
    
    	int T = 1;
    	while (gets(input) && strcmp(input,"0"))
    	{
    		rePolish(input, strlen(input));
    
    		output[outLen-1] = '\0';
    //		printf("Case %d:\n%s\n",T++,output);
    		printf("%.2lf\n",calc(output));
    	}
    	return 0;
    }
    //测试用例:1 - 3 + 4


     

    展开全文
  • 第十三章 字符 正则表达式

    千次阅读 2016-09-06 10:05:15
    正则表达式提供了一种完全通用的方式,能够解决各种字符处理相关的问题:匹配、选择、编辑以及验证。Java中的字符操作集中于String、StringBuffer、StringTokenizer类。与正则表达式相比,它

    导语

    • 正则表达式是一种强大而灵活的文本处理工具。
    • 使用正则表达式,我们能以编程的方式,构造复杂的文本模式,并对输入的字符串进行搜索。一旦匹配这些模式的部分,就可以对它们进行处理。
    • 正则表达式提供了一种完全通用的方式,能够解决各种字符串处理相关的问题匹配、选择、编辑以及验证。
    • Java中的字符串操作集中于String、StringBuffer、StringTokenizer类。与正则表达式相比,它们只提供简单的功能。

    1.基础

    • 一般来说,正则表达式就是以某种方式来描述字符串。“如果一个字符串中含有这些东西,那么它就是我正在找的东西”。
    • 正则表达式中,用\d表示一位数字。
    • 反斜杠:在其他语言中,\\表示“我想要在正则表达式中插入一个普通的反斜线,它没有任何意义”

      在java中,\\表示“插入一个正则表达式的反斜线,所以其后的字符具有特殊的意义”。
      eg:表示一个整数,那么正则表达式应该是\\d,如果插入一个普通的反斜线,则应该是\\\\,
      不过换行和制表符之类的东西只需使用单反斜线:\n\t。
    • 要表示“一个或多个之前的表达式”,应该使用+。所以如果要表示可能有一个负号,后面跟着一位或多位数字。-?\\d+,\\d是之前的表达式
    • 表示或者没有这个字符的意思。
      public class IntegerMatch {
          public static void main(String[] args) {
              //String的matches方法内可以放一个正则表达式,他会跟前面的字符串进行匹配
              System.out.println("-1234".matches("-?\\d+"));//  可能有一个-号,后面跟着多个数字吗
              System.out.println("5678".matches("-?\\d+"));//  可能有一个-号,后面跟着多个数字吗
              System.out.println("5678".matches("-\\d+"));// 有一个-号,后面跟着多个数字吗 -数字数字数字 \\d数字
              System.out.println("+110".matches("-?\\d+"));
              System.out.println("+119".matches("(-|\\+)?\\d+"));//可能有一个+或-号,后面跟着多个数字
          }
      }
      /**
      true
      true
      false
      false
      true
       */
      
      |线表示或操作。括号有分组的功能
      (-|\\+)?
      这个正则表达式中,表示字符串的起始字符可能是一个-或+,或二者皆没有(因为后面跟着?修饰符,可能没有)
      因为+在正则表达式中有特殊的意义,所以使用\\将其转义,使之成为表达式中一个普通的字符串。
    • split()方法
      1. split()方法是一个正则表达式工具类。将字符串从正则表达式匹配的地方切开。

        public class Splitting {
        	public static String knights = 
        			"Then, when you have found the shrubbery, you must " +
        	"cut down the mightiest tree in the forest..."
        					+"with...a herring";
        	public static void split(String regex){
        		System.out.println(Arrays.toString(knights.split(regex)));
        	}
        	public static void main(String[] args) {
        		split(" ");//根据空格来分割字符串,匹配到空格就切开字符串,放入一个数组。
        		split("\\W+");// \\W代表非单词字符,它将标点都删除了,匹配到非单词字符,就切开字符串,放入一个数组
        		split("n\\W+");// 字母n后面跟个一个或多个非单词字符 ,这个正则表达式表示(n非单词字符非单词字符.......),匹配到就切开
        	}
        }
        /**
        [Then,, when, you, have, found, the, shrubbery,, you, must, cut, down, the, mightiest, tree, in, the, forest...with...a, herring]
        [Then, when, you, have, found, the, shrubbery, you, must, cut, down, the, mightiest, tree, in, the, forest, with, a, herring]
        [The, whe, you have found the shrubbery, you must cut dow, the mightiest tree i, the forest...with...a herring]
         */
      2. String.split()还有一个重载版本,允许限制字符串的分割的次数。
    • Replace()方法
      1. 只替换正则表达式第一个匹配的字符串,或替换所有匹配到的地方。
        public class Replacing {
        	static String s = Splitting.knights;
        	public static void main(String[] args) {
        		System.out.println(s);
        		System.out.println(s.replaceFirst("f\\w+", "汉字"));//\w小写 表示一个单词字符
        		System.out.println(s.replaceAll("shrubbery|three|herring", "汉字"));//将这几个字符全部替换掉
        	}
        }
        /**
        Then, when you have found the shrubbery, you must cut down the mightiest tree in the forest...with...a herring
        Then, when you have 汉字 the shrubbery, you must cut down the mightiest tree in the forest...with...a herring
        Then, when you have found the 汉字, you must cut down the mightiest tree in the forest...with...a 汉字
         */ 
        

    2.创建正则表达式(具体看书吧)

    • 正则表达式的完整构造自列表,请参考java.util.regex包中的Pattern类。
      public class Rudolph {
      	public static void main(String[] args) {
      		for(String pattern : new String[]{"Rudolph",
      				"[rR]udolph","[rR][aeiou][a-z]ol.*",
      				"R.*"})
      			System.out.println("Rudolph".matches(pattern));
      	}
      }
      /**
      true
      true
      true
      true
       */ 
      

    3.量词

    • 量词描述了一个模式吸收输入文本的方式:
      1. 贪婪型:贪婪表达式会为所有可能的模式发现尽可能多的匹配。假定我们的模式仅能匹配第一个可能的字符串组,如果表达式是贪婪的,那么它就会继续往下匹配。
      2. 勉强型:用问号来指定,这个量词匹配满足模式所需的最少字符数。因此也称作懒惰的、最少匹配的、非贪婪的、或不贪婪的。
      3. 占有型:这种类型的量词只有Java语言中才可用,并且更高级。当正则表达式被应用与字符串时,它会产生相当多的状态,以便在匹配失败时可以会说。而“占有的”量词并不保存这些中间状态,以防止他们回溯。他们常常用于防止正则表达式失控,因此可以使正则表达式执行起来更有效。


    • 表达式X通常必须用圆括号括起来,以便它能够按照我们期望的效果去执行。
      eg:abe+   匹配一个或多个abc序列,但这样是匹配ab,后面跟随一个或多个c,必须要(abc)+
    • 接口CharSequence从CharBuffer、String、StringBuffer、StringBuilder类中抽象出字符序列的一般化定义。
      多数正则表达式都接受CharSequence类型的参数。

    4.Pattern和Matcher(构造功能强大的正则表达式对象)

    • 构造功能强大的正则表达式对象。
      public class TestRegularExpression {
          public static void main(String[] args) {
              if (args.length < 2) {
                  System.out.println("Usage:\njava TestRegularExpression " + "characterSequence regularExpression+");
                  System.exit(0);
              }
              System.out.println("Input: \"" + args[0] + "\"");
              for (String arg : args) {
                  System.out.println("Regular expression: \"" + arg + "\"");
                  //compile 编译要匹配的字符串 ,编译要匹配的正则表达式
                  Pattern p = Pattern.compile(arg);
                  //matcher 匹配compile内的字符串 输入matcher的字符串是否匹配上面的正则表达式 并生成一个matcher对象
                  Matcher m = p.matcher(args[0]);
                  while (m.find()) {//判断是否还有下一个匹配到的
                      //输出匹配字符串和开始结束位置
                      System.out.println("Match \"" + m.group() + "\" at position " + m.start() + "-" + (m.end() - 1));
                  }
              }
          }
      }
      /**
      Match "abcabcabc" at position 0-8
      Regular expression: "abc"
      Match "abc" at position 0-2
      Match "abc" at position 3-5
      Match "abc" at position 6-8
      Regular expression: "abc+"
      Match "abc" at position 0-2
      Match "abc" at position 3-5
      Match "abc" at position 6-8
       */
      eclipse 怎样在运行时输入数据:右键->Run As -> Run Configuration ->在argument内输入参数,这样main方法内args[]就有值啦。

    • Pattern表示编译后的正则表达式,这样就不需要我们写正则表达式了(如 “\\x+”等),Pattern会为我们自动生成。

    5.static boolean matches(String regex, CharSequence input)

    • 用以检查regex是否匹配整个Charsequence 类型的input参数。


    6.Match.find()方法

    • Matcher.find()方法可用来在CharSequence中查找多个匹配项。
    • public class Finding {
      	public static void main(String[] args) {
      		Matcher m = Pattern.compile("\\w+")//传入compile方法一个正则表达式 (\\w+表示 多个单词字符)
      				//传入要对上面正则表达式进行匹配的字符串,根据单词进行匹配
      				.matcher("Evening is full of the linnet's wings");
      		/**
      		 * find()方法,用来在CharSequence中查找多个匹配正则表达式的“字符段” ,
      		 * 比如这个例子,就是查找多个单词字符的字符段,存在下一个匹配就一直while循环下去
      		 */
      		while(m.find())//像迭代器那样
      			//m.group()用来获取匹配到的字符段 这里是CharSequence中匹配到的单词字符
      			System.out.print(m.group() + " ");
      		System.out.println();
      		int i = 0;
      		while(m.find(i)){//i表示字符串中字符的位置,并以其作为索引的起点。
      			System.out.print(m.group() + " ");
      			i++;
      		}
      	}
      }
      /**
      Evening is full of the linnet s wings 
      Evening vening ening ning ing ng g is is s full full ull ll l of of f the the he e linnet linnet innet nnet net et t s s wings wings ings ngs gs s 
       */
      
    • 模式\\w+将字符串划分为单词。find()像迭代器那样遍历输入的字符串。m.group()用于配合其输出。
    • 第二个find()能够接受一个整数作为参数,该整数表示字符串中字符的位置,并以其作为搜索的起点。
      从输出可以看出,find(i)会不断的重新设定搜索的起始位置。

    7.组(Groups)Mather.group()方法

    • 组是用括号划分的正则表达式,可以根据编号来引用某个组。组号为0表示整个表达式,组号1表示被第一个括号括起来的组,以此类推。
      eg:A(B(C))D 中有三个组,组0是ABCD,组1是BC,组2是C
    • public int groupCount()返回改匹配器的模式中的分组数目,第0组不包括在内。
    • public String group()返回前一次匹配操作(例如find())的第0组(整个匹配).
    • public String group(int i)返回前一次匹配操作期间指定的组号,如果匹配成功,但是指定的组没有匹配输入字符串的任何部分,则返回null。
    • public int start(int group)返回在前一次匹配操作中寻找到的组的起始索引,
    • public int end(int group)返回在前一次匹配操作中寻找到的组的最后一个字符索引加一的值。
      public class Groups {
      	public static void main(String[] args) {
      		Pattern p = Pattern.compile("(\\d+,)(\\d+)");
      		String s = "123,456-34,345";
      		Matcher m = p.matcher(s);
      		while (m.find()) {//匹配到的字符串循环,首先会招到第一个,然后匹配到的第二个,第三个·····
      			System.out.println("m.group():" + m.group()); // 打印匹配期间的大组(整个匹配)
      			System.out.println("m.group(1):" + m.group(1)); // 打印匹配期间的组1
      			System.out.println("m.group(2):" + m.group(2)); // 打印匹配期间的组2
      			System.out.println();
      		}
      		System.out.println("捕获个数:m.groupCount()" + m.groupCount());
      	}
      }
      /**
      m.group():123,456
      m.group(1):123,
      m.group(2):456
      
      m.group():34,345
      m.group(1):34,
      m.group(2):345
      
      捕获个数:m.groupCount()2
       */


    8.start()和end() 【lookingAt()和matches() 和find()方法区别】

    • 匹配操作成功之后,start()方法返回先前匹配的起始位置的索引,end()方法返回所匹配的最后字符的索引加一的值。
      匹配操作失败后调用抛出IllegalStateException。
    1. find()方法可以在输入任意位置定位正则表达式。
    2. lookingAt()和matches()只有在正则表达式与输入的最开始处就开始匹配时才会成功。
    3. matches()方法只有在整个输入都匹配正则表达式时才会成功。
    4. lookingAt()只要输入的第一部分匹配就会成功。
    5. public class StartEnd2 {
      	public static void main(String[] args) {
      		String content = "123-456,789:102";
      		Pattern p = Pattern.compile("\\d+");
      		Matcher m = p.matcher(content);
      		while(m.find()){//查找多个匹配项,像迭代器的next方法
      		    System.out.println("find(): " + m.group() + " start at " + m.start() + " end at " + (m.end() - 1));
      		}
      		if(m.lookingAt()){//第一部分匹配就可成功
      		    System.out.println("lookingAt(): " + m.group() + " start at " + m.start() + " end at " + (m.end() - 1));
      		}
      		if(m.matches()){//全都匹配才能成功
      		    System.out.println("matches(): " + m.group() + " start at " + m.start() + " end at " + (m.end() - 1));
      		}
      	}
      }
      /**
      find(): 456 start at 1 end at 3
      find(): 789 start at 5 end at 7
      find(): 102 start at 9 end at 11
       */
      

    9.Pattern标记

    • Pattern Pattern.complile(String regex, int flg),它接受一个标记参数,以调整匹配的行为。其中flg来自于Pattern中的常量。
    • 在这些标记中CASE_INSENSITIVE,MULTILINE COMMENTS非常重要
      public class ReFlags {
      	public static void main(String[] args) {
      		//表达式^和$分别匹配匹配一行的开始和结束
      		Pattern p = Pattern.compile("^java",Pattern.CASE_INSENSITIVE|Pattern.MULTILINE);
      		Matcher m = p.matcher("java has regex\njava has regex\n"+
      								"JAVA has pretty good regular expressions\n"+
      								"Regular expressions are in java");
      		while(m.find())
      			System.out.println(m.group());
      	}
      }
      /**
      java
      java
      JAVA
       */

    10.split()方法

    • 将输入的字符串断开成字符串对象数组,断开边界由正则表达式确定。
      public class SplitDemo {
      	public static void main(String[] args) {
      		String input = "This!!unusual use!of exclamation!!points";
      		//断成对象数组,用Arrays转成 list并输出
      		System.out.println(Arrays.toString(Pattern.compile("!!").split(input)));
      		System.out.println(Arrays.toString(Pattern.compile("!!").split(input, 2)));
      	}
      }
      /**
      [This, unusual use!of exclamation, points]
      [This, unusual use!of exclamation, points]
       */

    11.替换操作

    1. replaceFirst(String replancement)以参数字符串replancement替换掉第一个匹配成功的部分。
    2. replaceAll(String replancement)以参数字符串replancement替换掉所有匹配成功的部分。
    3. appendReplacement(StringBuffer sbuf, String replancement)执行渐进的替换。允许调用其他方法来生成或处理replacement参数,使你能够以编程的方式将目标分割成组,从而具备更强大的替换功能。
    4. appendTail(StringBuffer sbuf),在执行了一次或多次appendReplacement()之后调用,可以将输入字符串余下的部分复制到sbuf中
      public class TheReplacements {
      	public static void main(String[] args) {
      		Pattern p = Pattern.compile("a*b");
      		// 获取 matcher 对象
      		Matcher m = p.matcher("aabfooaabfooabfoobcasab");
      		StringBuffer sb = new StringBuffer();
      		while (m.find()) {
      			m.appendReplacement(sb, "-");//渐进式替换,将m匹配到的字符端替成“-”
      		}
      		m.appendTail(sb);//把余下的字符串复制到sb中
      		System.out.println(sb.toString());
      		String s = "123123,456";
      		System.out.println("s:" + s);
      		s = s.replaceFirst("23", "--");
      		System.out.println("replaceFirst:" + s);
      		s = s.replaceAll("2", "-");
      		System.out.println("replaceAll:" + s);
      	}
      }
      /**
      -foo-foo-foo-cas-
      s:123123,456
      replaceFirst:1--123,456
      replaceAll:1--1-3,456
      */
      

    12.rese()方法

    • 将现有的Mather对象应用于一个新的字符序列。
      public class Resetting {
      	public static void main(String[] args) {
      		Matcher m = Pattern.compile("[frb][aiu][gx]")
      				.matcher("fix the rug with bags");
      		while(m.find())
      			System.out.print(m.group() + " ");
      		System.out.println();
      		m.reset("fix the rig with rags");//将matcher应用于第二个字符串
      		while(m.find())
      			System.out.print(m.group() + " ");
      	}
      }
      /**
      fix rug bag 
      fix rig rag 
      */
      

    13.正则表达式与java I/O

    • 使用正则表达式在一个文件中进行搜索匹配操作。输出的是匹配的部分以及匹配部分在行中的位置。

    。。。。。。。。。。。。。。。。。。。。这儿还有好多先空着


    14.扫描输入

    • 从文件或标准输入读取数据非常痛苦。解决办法是读取其中一行文本,对其进行分词,然后使用Integer、Double等类的各种解析方法解析数据:
      public class SimpleRead {
      	public static BufferedReader input = new BufferedReader(new StringReader("Sir Robin of Camelot\n22 1.61803"));
      	public static void main(String[] args) {
      		try {
      			System.out.println("What is your name?");
      			String name = input.readLine();//读取一行 并转换为String
      			System.out.println(name);
      			System.out.println("How old are you? What is your favorite double ?");
      			System.out.println("(input: <age> <double>)");
      			String numbers = input.readLine();//读取第二行
      			System.out.println(numbers);
      			String[] numArray = numbers.split(" ");//遇空格符分开字符串 分词
      			int age = Integer.parseInt(numArray[0]);//解析成integer
      			double favorite = Double.parseDouble(numArray[1]);//解析成double
      			System.out.format("Hi %s.\n", name);//匹配格式输出
      			System.out.format("In 5 years you will be %d.\n", age + 5);
      			System.out.format("My favorite double is %f.", favorite/2);
      		} catch (IOException e) {
      			System.err.println("I/O exception");
      		}
      	}
      }
      /**
      What is your name?
      Sir Robin of Camelot
      How old are you? What is your favorite double ?
      (input: <age> <double>)
      22 1.61803
      Hi Sir Robin of Camelot.
      In 5 years you will be 27.
      My favorite double is 0.809015.
      */
    • readLine()读取一行输入转为String对象,如果每一行对应一个输入值可行,但如果两个输入值在同一行,必须分解这一行,获取到两个不等的输入值。
    • Scanner:
      public class BetterRead {
      	public static void main(String[] args) {
      		BufferedReader input = new BufferedReader(new StringReader("Sir Robin of Camelot\n22 1.61803"));
      		Scanner stdin  = new Scanner(SimpleRead.input);//放入Scanner中
      		System.out.println("What is your name?");
      		String name = stdin.nextLine();//读取一行
      		System.out.println(name);
      		System.out.println("How old are you? What is your favorite double?");
      		System.out.println("(input: <age> <double>)");
      		int age = stdin.nextInt();//读取下一行中的int型值
      		double favorite  = stdin.nextDouble();//读取下一行中的double值
      		System.out.println(age);
      		System.out.println(favorite);
      		System.out.format("Hi %s.\n", name);//匹配格式输出
      		System.out.format("In 5 years you will be %d.\n", age + 5);
      		System.out.format("My favorite double is %f.", favorite/2);
      	}
      }
      /**
      What is your name?
      Sir Robin of Camelot
      How old are you? What is your favorite double?
      (input: <age> <double>)
      22
      1.61803
      Hi Sir Robin of Camelot.
      In 5 years you will be 27.
      My favorite double is 0.809015.
       */
      1. scanner的构造器可以接受任何类型的输入对象,包括File InputStream String或者 Readable.
        它将所有的输入、分词以及翻译操作都隐藏在不同类型的next方法中。所有的next方法,只有在找到一个完整的分词之后才会返回。
      2. hasNext,用以判断下一个输入分词是否所需的类型。
    • Scanner定界符:默认情况下,Scanner根据空格字符对输入进行分词,但可以使用正则表达式制定自己所需的定界符。

      public class ScannerDelimiter {
      	public static void main(String[] args) {
      		Scanner scanner = new Scanner("12, 42, 54, 99, 21");
      		scanner.useDelimiter("\\s*,\\s*");//自己的正则表达式,设定定界符
      		while(scanner.hasNextInt())
      			System.out.println(scanner.nextInt());
      	}
      }

    15.用正则表达式扫描

    • public class ThreatAnalyzer {
      	static String threatData = 
      			"58.27.82.161@02/10/2005\n"+
      					"204.45.234.40@02/10/2005\n"+
      					"58.27.82.161@02/10/2005\n"+
      					"58.27.82.161@02/11/2005\n"+
      					"58.27.82.161@02/12/2005\n"+
      					"58.27.82.161@02/12/2005\n";
      	public static void main(String[] args) {
      		//定义一个扫描类
      		Scanner scanner = new Scanner(threatData);
      		String pattern = "(\\d+[.]\\d+[.]\\d+[.]\\d+)@"
      				+ "(\\d{2}/\\d{2}/\\d{4})";
      		while(scanner.hasNext(pattern)){
      			scanner.next(pattern);//找到下一个匹配部分,依次为第二组 第三组
      			MatchResult mathc = scanner.match();//调用match获得匹配结果
      			String ip = mathc.group(1);//获得第一组的数据
      			String date = mathc.group(2);//获得第二组的数据
      			System.out.format("Thread on %s from %s\n", date,ip);//格式化输出
      		}
      	}
      }
      /**
       Thread on 02/10/2005 from 58.27.82.161
      Thread on 02/10/2005 from 204.45.234.40
      Thread on 02/10/2005 from 58.27.82.161
      Thread on 02/11/2005 from 58.27.82.161
      Thread on 02/12/2005 from 58.27.82.161
      Thread on 02/12/2005 from 58.27.82.161
       */
      
      注意:next()仅仅针对下一个输入分词进行匹配,如果你的正则表达式中含有定界符,那永远都不可能匹配成功。

    16.StringTokenizer

    • 一个已经废弃的类,在以前使用他来对字符串进行分词。






























































































    展开全文
  • 计算数学表达式原理 采用c#实现 很实用 //a.建立两个栈:第一个位操作数栈,第二个操作符符栈!(将栈定义为string类型) //b.对数字来说是无条件压入数字栈中. //c.而对符号来说,只有当前栈顶元素的优先值小于扫到的...
  • C#实现将字符作为表达式运算

    千次阅读 2018-04-11 09:14:51
    曾经有个需求,要把一段字符串表达式作为C#的一段语句来执行。或者直接在sql中存储上不同的含参数的工时如180+20*(n-4)。查出来之后带入参数计算。又好比在win7计算器中粘贴一个表达式,直接输出了结果。碰到这个...
           曾经有个需求,要把一段字符串表达式作为C#的一段语句来执行。或者直接在sql中存储上不同的含参数的工时如 180+20*(n-4)。查出来之后带入参数计算。又好比在win7计算器中粘贴一个表达式,直接输出了结果。
    碰到这个问题,查了一下网上的资料,发现有以下几种适合我的方案:
    1.把表达式用字符串的各种函数拆分出来数字和小括号和运算符的组合。然后去运算(即自己写一个类和函数)
    2.采用T-sql脚本计算。在oracle中 select  180+20*(10-4) from dual;  在sqlserver中  select  180+20*(10-4) 即可。
    3.使用 JavaScript脚本函数中的eval方法。(常见)

    使用.Net组件
    /* 需将Microsoft.JScript 和Microsoft.Vsa加入参考并引用Microsoft.JScript */
    public   object  EvalExpress( string  sExpression)
     
    {
                Microsoft.JScript.Vsa.VsaEngine ve 
    = Microsoft.JScript.Vsa.VsaEngine.CreateEngine();
                
    return Microsoft.JScript.Eval.JScriptEvaluate(sExpression, ve);
    }
    或者使用.Com组件
    /* 需引用com组件 microsoft  script control
    public   object  EvalExpress( string  sExpression)
     
    {
              
    MSScriptControl.ScriptControl scc = new MSScriptControl.ScriptControl();
                scc.Eval( sExpression );

    }   

        EvalExpress这个方法便可以将sExpression作为表达式执行,运行结果返回是object,但是根据参数内容不同,可以转换成bool、int、string等。
           不过既然是使用脚本引擎来执行的,速度不会太好。而且这两个组件在VS05中提示已过时,但是在提示信息和MSDN中没找到替代方案。

    展开全文
  • java 字符 详细实例代码 字符检索 可改变字符 字符生成器 日期和时间字符格式化
  • 字符转加减乘除表达式字符转加减乘除表达式字符转加减乘除表达式字符转加减乘除表达式字符转加减乘除表达式字符转加减乘除表达式字符转加减乘除表达式字符转加减乘除表达式字符转加减乘除表达式...
  • 描述: 给定一个以字符形式表示的算术表达式,计算该表达式的值。 表达式支持如下运算:“+、-、*、/”,其中“*”和“/”的优先级要高于“+”和“-”; 不需要考虑括号,且表达式之间没有空格; 例如:对于表达式...
  • Java 字符算术表达式求值

    万次阅读 2012-09-05 19:48:11
    import java.util.ArrayList; import java.util.Stack; /** * * @author yhh * */ public class Calculate { ... * 将字符转化成List * @param str * @return */ public ArrayList getStringList(Strin
  • 什么是正则表达式

    千次阅读 2019-01-31 17:09:50
    最近看了一篇关于正则表达式的学习笔记,觉得讲的非常好,更有图形化的神器相助,想不学会都难,所以想转给大家看看。 话说不是开发为啥要学正则表达式...1.什么是正则表达式 正则表达式,又称正规表示、正规表...
  • 上回讲了如何计算后缀表达式,其实真正的难点在于如何将一个正常的字符串表达式(中缀表达式)变成一个后缀表达式。如将6 * ( 5 + ( 2 + 3) * 8 + 3)变为6 5 2 3 + 8 * + 3 + * 逆波兰表达式,它的语法规定,表达式...
  • C语言 计算给定字符串表达式的值

    千次阅读 2020-06-13 09:36:08
    C语言 计算给定字符串表达式的值 可以包括加减乘除运算以及括号运算 代码 #include<stdio.h> #include<string.h> #define maxn 100005 char s[maxn],infixList[maxn][10]; char suffix[maxn][10]...
  • 实现符号 + - * / max min (),输出逆波兰和结果,输入为整数,输出为整数,其中max/min表达式为max(2,4)。表达式总会得出有效数值且不存在除数为 0 的情况
  • Java 中中运运行行字字符符串串表表达达式式的的方方法法 这篇文章主要介绍了Java 中运行字符串表达式的方法,本文通过实例代码给大家介绍的非常详细具有一 的参考 借鉴价值需要的朋友可以参考下 在日常的开发中偶尔...
  • 匹配字符-正则表达式

    千次阅读 2017-07-17 13:25:27
    1. 正则表达式规则 1.1 普通字符 ... 字母、数字、汉字、下划线、以及后边章节中...表达式中的普通字符,在匹配一个字符的时候,匹配与之相同的一个字符。  举例1:表达式 "c",在匹配字符 "abcde" 时,
  • Java 中计算字符串表达式的值

    万次阅读 2018-08-25 10:54:44
    Java 中计算字符串表达式的值 在 Java 中计算字符数值表达式可以用 javax.script.ScriptEngine#eval(java.lang.String),通过调用 JavaScript 来计算 import javax.script.ScriptEngine; import javax.script...
  • linux交互命令(左)和py文件(右)的运行结果会有不同:     左图,因为我cmd设置了gbk编码格式,所以u是s用gbk解码后的unicode对象,配套的解编码才能使原中文字符在print下正常显示,所以再用gbk编码;右图,py...
  • 字符操作-正则表达式

    千次阅读 2015-12-23 14:52:40
    正则表达式使用单个字符来描述、匹配一系列符合某个句法规则的字符。在很多文本编辑器里,正则表达式通常被用来检索、替换那些符合某个模式的文本。 许多程序设计语言都支持利用正则表达式进行字符操作。...
  • 本题源自leetcode 592 ...思路: 1 求分数表达式,用istringstream 类读输入的表达式。  2 求表达式的结果。 3 除以最大公约数(简化) 代码: string fractionAddition(string expres
  • 由于我对正则不是很清楚,我想求取把字符 “str, DGK, rDJK, DJKl,DGK , end” 替换为 “str, MSN, rDJK, DJKl,MSN , end” 求匹配的写法。 [Ctrl+A 全选 注:如需引入外部Js需刷新才能执行] ...
  • 字符串表达式求值对于python而言,有一个很方便的方法:eval(),可以直接求出得到结果,这里我想利用python手写实现一个,即利用stack和中缀表达式转后缀表达式方法来求 中缀表达式转后缀表达式 发现这个方法的人...
  • 算术表达式的前缀、中缀、后缀相互转换

    万次阅读 多人点赞 2016-11-28 21:01:06
    中缀表达式(中缀记法) 中缀表达式是一种通用的算术或逻辑公式表示方法,操作符以中缀形式处于操作数的中间。中缀表达式是人们常用的算术表示方法。 虽然人的大脑很容易理解与...前缀表达式(前缀记法、波兰) 前
  • JAVA实现字符串表达式求值

    千次阅读 2015-08-12 00:04:11
    问题描述:根据用户输入的字符串表达式求出等式的结果 包括+ -*/和() 原理就是利用栈构建出表达式的后缀并求出最后的结果值 一、构建后缀表达式 构建的过程及原理就是:构建一个操作符栈,和一个后缀栈,...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 202,755
精华内容 81,102
关键字:

串式表达式是什么