输入一个表达式字符串求值

描述: 给定一个以字符串形式表示的算术表达式,计算该表达式的值。
表达式支持如下运算:“+、-、*、/”,其中“*”和“/”的优先级要高于“+”和“-”;
不需要考虑括号,且表达式之间没有空格;
例如:对于表达式"3-2+15*2",该表达式值为31.
思路:
1.找到连续的数字字符字串,并转化成整数。
2.算乘除
3.算加减

用双向链表实现


#include <iostream>
#include <string.h>
using namespace std;
typedef struct node 
{
	union intorchar
	{
		int a;
		char c;
	}IntChar;
	bool flag;
	struct node *next;
	struct node *pre;
}Node,*pNode;

int computer(char a[],int len)
{
	int sum=0;
	int k=1;
	pNode pnode =NULL;
	pNode pk=NULL;
	pNode pr=NULL;
	int i1,i2,i3;
	char *p_begin=NULL;
	char *p_end = NULL;
	for (int i=0;i<len;)//将字符串中连续的数字转换成一个字符,没有考虑
	{
		if(a[i]>='0' &&a[i]<<'9')
			if(p_begin ==NULL)
			{
				i1=0;
				
				p_begin =&a[i];
				p_end= p_begin;
				i++;
				for(int j=i;j<len;j++)
					if(a[j]>= '0'&&a[j]<= '9')
					{
						p_end++;
						i++;
					}
					else
						break;
				for(char *p=p_begin ; p<= p_end ; p++)//将字符串转变成整数
				{
					i1=i1*10+(int )((*p)-'0');
				}
				pk = new Node;
				pk->flag =true;
				pk->IntChar.a = i1;
				pk->next =NULL;
				if(NULL==pnode)
				{
					pr=pk;
					pnode =pk;
					pk->pre =NULL;
				}
				else
				{
					pr->next=pk;
					pk->pre =pr;
					pr= pk;
				}
				p_begin =NULL;
				p_end =NULL;
			}
			else
			{;}
		else
		{
			pk = new Node;
			pk->flag =false;
			pk->IntChar.c= a[i++];
			pk->next =NULL;
			if(NULL==pnode)
			{
				pr=pk;
				pnode =pk;
				pk->pre =NULL;
			}
			else
			{
				pr->next=pk;
				pk->pre = pr;
				pr= pk;
			}
		}
	}
	pk=pnode;
	while (pk)
	{
		if (true ==pk->flag )
		{
			cout<<pk->IntChar.a;
		}
		if (false ==pk->flag )
		{
			cout<<pk->IntChar.c;
		}
		pk=pk->next;
	}
	cout<<endl;

	pk=pnode;
	pNode pi=NULL;
	while(pk!=NULL)//找出* /并处理
	{
		if( false == pk->flag && '*'==pk->IntChar.c)
		{
			i1 = (int )pk->pre->IntChar.a;
			i2 = (int )pk->next->IntChar.a;
			i3 = i1*i2;
			pk->pre->IntChar.a =i3;
			if (pk->next->next != NULL)//防止越界
			{
				pk->pre->next =pk->next->next;
				pk->next->next->pre =pk->pre;
				pi= pk;
				pk=pk->next->next;
				delete pi->next;
				delete pi;
				pi= NULL;
			} 
			else
			{
				pk->pre->next= NULL;

				delete pk->next;
				delete pk;
				break;
			}
		}
		else if(false == pk->flag && '/'==pk->IntChar.c)
		{
			i1 = (int )pk->pre->IntChar.a;
			i2 = (int )pk->next->IntChar.a;
			i3 = i1/i2;
			pk->pre->IntChar.a =i3;
			if (pk->next->next != NULL)//防止越界
			{
				pk->pre->next =pk->next->next;
				pk->next->next->pre =pk->pre;
				pi= pk;
				pk=pk->next->next;
				delete pi->next;
				delete pi;
				pi= NULL;
			} 
			else
			{
				pk->pre->next= NULL;
				delete pk->next;
				delete pk;
				break;
			}
		}
		else
		{
			pk=pk->next;
		}
		
	}
	pk=pnode;
	while (pk)
	{
		if (true ==pk->flag )
		{
			cout<<pk->IntChar.a;
		}
		if (false ==pk->flag )
		{
			cout<<pk->IntChar.c;
		}
		pk=pk->next;
	}cout<<endl;
	//处理剩下 + -
	pk=pnode;
	while(pk!=NULL)//找出* /并处理
	{
		if( false == pk->flag && '+'==pk->IntChar.c)
		{
			i1 = (int )pk->pre->IntChar.a;
			i2 = (int )pk->next->IntChar.a;
			i3 = i1+i2;
			pk->pre->IntChar.a =i3;
			if (pk->next->next != NULL)//防止越界
			{
				pk->pre->next =pk->next->next;
				pk->next->next->pre =pk->pre;
				pi= pk;
				pk=pk->next->next;
				delete pi->next;
				delete pi;
				pi= NULL;
			} 
			else
			{
				pk->pre->next= NULL;
				delete pk->next;
				delete pk;
				break;
			}
		}
		else if(false == pk->flag && '-'==pk->IntChar.c)
		{
			i1 = (int )pk->pre->IntChar.a;
			i2 = (int )pk->next->IntChar.a;
			i3 = i1-i2;
			pk->pre->IntChar.a =i3;
			if (pk->next->next != NULL)//防止越界
			{
				pk->pre->next =pk->next->next;
				pk->next->next->pre =pk->pre;
				pi= pk;
				pk=pk->next->next;
				delete pi->next;
				delete pi;
				pi= NULL;
			} 
			else
			{
				pk->pre->next= NULL;
				delete pk->next;
				delete pk;
				break;
			}
		}
		else
		{
			pk=pk->next;
		}	
	}
	pk=pnode;
	while (pk)
	{
		if (true ==pk->flag )
		{
			cout<<pk->IntChar.a;
		}
		if (false ==pk->flag )
		{
			cout<<pk->IntChar.c;
		}
		pk=pk->next;
		
	}cout<<endl;
	sum= pnode->IntChar.a;
	delete pnode;
	return sum;
}
int main()
{
	int sum=0;
	char str[]="3-2+15*20/5";
	sum= computer(str,strlen(str));
	cout<<"sum = "<<sum<<endl;
	return 0;
}


下面是别人做的:

#include <iostream>
#include <string>
#include <stack>

using namespace std;


void cal(char * a){  
    int len = strlen(a);  
    stack<int> s1;  
    stack<char> s2;  
    int k = 0;  
    int sum =0;  
    int sum1 = 0;  
    int count =0;  
	
    while(k <= len){
		
		//把字符串中数字转化成整形存入数组
        if(a[k] <= '9' && a[k] >= '0')
		{  
			sum = 0;  
			while(a[k]<= '9' && a[k] >= '0' )
			{  
				sum = sum * 10 + a[k] - '0';  
				++k;  
			}  
			s1.push(sum);  
        }
		
		else
		{  
			if(!s2.empty())
			{  
                if(s2.top() == '*')
				{  
                    s2.pop();  
                    int number1 = s1.top();  
                    s1.pop();  
                    int number2 = s1.top();  
                    s1.pop();  
                    int tt = 0;  
                    tt = number2 * number1;  
                    s1.push(tt);  
                }
				else if(s2.top() == '/'){  
                    s2.pop();  
                    int number1 = s1.top();  
                    s1.pop();  
                    int number2 = s1.top();  
                    s1.pop();  
                    int tt = 0;  
                    tt = number2 / number1;  
                    s1.push(tt);  
                }  
            }  
            if(k != len){  
                s2.push(a[k]);  
				
            }  
            ++k;  
        }  
    }  
	
	
    sum1 = s1.top();  
    s1.pop();  
    char ch;  
    int temp;  
    while(!s2.empty()){  
        ch = s2.top();  
        temp = s1.top();  
        s1.pop();  
        s2.pop();  
        if(ch == '+'){  
            sum1 = temp + sum1;  
        }else if(ch == '-'){  
            sum1 = temp - sum1;  
        }  
    }  
    cout<<sum1<<endl;  
	
}  


int main()
{
	double sum;
	
	char *a="11+2+18/3/2";
	cal(a);
}


因各个项目中需要使用根据字符串计算数,这里写出一个算法,专门计算字符串。配有大量常用公式。只有一个人方法,直接调用即可。 类名:CustomMath 函数名:Calculations(string value) 说明:解算式表达式字符串 表达式中包含的符号或函数: truncate, ceiling,floor,round,log10, sign,sinh,sqrt, asin,atan,cosh, tanh, sin,cos,tan ,abs,acos, exp,log,max,min,pow,mod,+,-,*,/,',',(,) 函数说明:(不区分大小写) truncate(num) 计算指定数的整数部分 truncate(1.23)=1 ceiling (num) 返回大于或等于指定的双精度浮点数的最小整数 ceiling(1.23)=2 floor(num) 返回小于或等于指定双精度浮点数的最大整数 floor(1.23)=1 round(num) 将双精度浮点舍入为最接近的整数 round(1.23)=1 round(num,num1) 将小数按指定的小数位数舍入 round(1.23,1)=1.2 log10(num) 返回指定数字以 10 为底的对数 log10(10)=1 sign(num) 返回表示数字符号的 sign(1.23)=1 sinh(num) 返回指定角度的双曲正弦 sinh(1.23)=1.5644 sqrt(num) 返回指定数字的平方根 sqrt(9)=3 sqrt(num,num1) 返回指定数字的num1根 sqrt(27,3)=3 asin(num) 返回正弦为指定数字的角度 asin(0.5)=PI/6 atan(num) 返回正切为指定数字的角度 atan(1)=45 cosh(num) 返回指定角度的双曲余弦 cosh(1.23)=1.8567 tanh(num) 返回指定角度的双曲正切 tanh(1.23)=0.8425 sin(num) 返回指定角度的正弦 sin(PI/6)=0.5 cos(num) 返回指定角度的余弦 sin(PI/3)=0.5 tan(num) 返回指定角度的余切 sin(PI/4)=1 abs(num) 返回数字的绝对 abs(-12)=12 acos(num) 返回余弦为指定数字的角度 acos(0.5)=PI/3 exp(num) 返回 e 的指定次幂 exp(1)=2.718 log(num) 返回指定数字的自然对数(底为 e) log(e)=1 log(num,num1) 返回指定数字在使用指定底时的对数 log(e,e)=1 max(num,um1) 返回最大 max(1,2)=2 min(num,num1) 返回最小 min(1,2)=1 pow(num,num1) 返回指定数字的指定次幂 pow(2,2)=4 mod(num,num1) 返回余数 mod(3,2)=1 常量: PI :3.14159265358979323846 E :2.7182818284590452354 YEAR :当前年份 MONTH :当前月份 DAY : 当前日 HOUR :当前时 MINUTE :当前分 SECOND :当前秒 RANDOM 一个随机数(0-1 之间) 实例 系统计算:1+2*3/4-0.5=2 函数计算:1+2*3/4-0.5=2 调用方式:CustomMath.Calculations("1+2*3/4-0.5") 系统计算:(1+2)*3/4-0.5=1.75 函数计算:(1+2)*3/4-0.5=1.75 调用方式:CustomMath.Calculations("(1+2)*3/4-0.5") 系统计算:(sin(pi)+sqrt(3+5*7+(2+8/4*5+2)))/6=1.20185042515466 公式计算:(sin(pi)+sqrt(3+5*7+(2+8/4*5+2)))/6=1.20185042515466 调用方式:CustomMath.Calculations("(sin(pi)+sqrt(3+5*7+(2+8/4*5+2)))/6") 系统计算:sin(pow(3,2)/4)+3.5-9*sqrt(81)=-76.7219268031121 函数计算:sin(pow(3,2)/4)+3.5-9*sqrt(81)=-76.7219268031121 调用方式:CustomMath.Calculations("sin(pow(3,2)/4)+3.5-9*sqrt(81)")
<think>好的,我现在需要解决用户的问题:如何在Java中统计一个字符串中出现特定子字符串的次数。让我仔细想想该怎么处理这个问题。 首先,用户的需很明确,就是统计某个子字符串在源字符串中出现的次数。我需要回忆一下Java中处理字符串的相关方法。通常,处理这类问题的方法可能有几种。例如,可以使用循环配合indexOf方法,或者使用正则表达式,甚至可能用Java 8的流来处理,不过后者可能比较复杂。 让我先考虑使用indexOf的方法。这种方法的基本思路是,在源字符串中不断查找目标子字符串的位置,每找到一次,就增加计数器,然后从找到的位置之后继续查找,直到找不到为止。例如,初始位置从0开始,每次找到子字符串后,新的起始位置应该是当前找到的位置加上子字符串的长度,这样可以避免重叠的情况。比如,在字符串"ababa"中查找"aba",如果允许重叠的话,会有两个结果,但如果每次跳过找到的位置加上子字符串长度,那么只会找到一个。不过用户可能想要的是统计所有可能的出现次数,包括重叠的情况,所以需要明确是否需要考虑重叠。但通常情况下,统计的是非重叠的次数。这一点可能需要向用户说明,但用户的问题中没有特别说明,可能需要假设是默认的非重叠统计。不过,用户可能希望两种方式都能处理,或者至少明确如何处理。 接下来,如何实现这个循环。首先,检查输入是否合理,比如子字符串是否为空,或者源字符串是否为空,避免出现错误。例如,如果子字符串长度大于源字符串,直接返回0。否则,初始化一个计数器count为0,然后初始化位置变量index为0。然后进入循环,使用indexOf方法,每次从index的位置开始查找,找到后count加1,然后更新index为找到的位置加上子字符串的长度。循环继续直到indexOf返回-1,表示没有更多的匹配。 例如,源字符串是"ababab",子字符串是"ab",那么第一次找到位置0,count变为1,index更新为0+2=2。第二次在位置2找到,count变为2,index变为4。第三次在位置4找到,count变为3,index变为6,此时源字符串长度是6,所以结束循环。总共有3次出现。这是正确的。 那如果子字符串是"aba",在源字符串"ababa"中,非重叠的话,第一次找到位置0,index变为3,然后在位置3找到,总共有两次。但如果是允许重叠,比如每次移动1位的话,那么可能会有不同的结果。但根据通常的做法,可能用户需要的是非重叠的情况。不过,这里可能需要明确,但用户的问题中没有说明,所以可能需要按常规处理方式,即非重叠的情况。 接下来,编写代码的大致步骤: 1. 定义方法,参数为源字符串str和子字符串subStr。 2. 检查subStr是否为空或长度为0,或者源字符串为空,此时返回0。 3. 初始化count为0,index为0。 4. 循环中,每次使用str.indexOf(subStr, index),如果结果为-1,退出循环。 5. 否则,count加1,index更新为找到的位置加上subStr的长度。 6. 循环结束后返回count。 例如,代码可能如下: public static int countOccurrences(String str, String subStr) { if (subStr.isEmpty() || str.isEmpty() || subStr.length() > str.length()) { return 0; } int count = 0; int index = 0; while (index <= str.length() - subStr.length()) { int foundIndex = str.indexOf(subStr, index); if (foundIndex == -1) { break; } count++; index = foundIndex + subStr.length(); } return count; } 不过需要测试一些边界情况,例如子字符串出现在末尾的情况,或者刚好在中间的情况。 另一种方法是使用split方法,将源字符串按子字符串分割,然后数组的长度减1就是出现的次数。例如: public static int countOccurrencesSplit(String str, String subStr) { if (subStr.isEmpty() || str.isEmpty()) { return 0; } String[] parts = str.split(Pattern.quote(subStr), -1); return parts.length - 1; } 但这种方法需要注意,split方法使用的是正则表达式,所以如果子字符串中有特殊字符,如.或者$等,需要用Pattern.quote()来转义。同时,split的第二个参数是限制分割次数,设为-1表示不限制,但这样可能会分割所有出现的地方。不过,这种方法可能无法正确处理重叠的情况,因为split会消耗掉子字符串,所以如果子字符串是"aa",在字符串"aaaa"中,split会分割成["", "", "", ""],所以长度-1是3次出现。而用indexOf的方法的话,假设子字符串长度为2,每次找到位置0,然后index变为2,找到位置2,总共有两次。所以两种方法结果可能不同。这说明split的方法统计的是所有可能的非重叠出现的次数,而indexOf的方法也是如此。那为什么会得到不同的结果? 比如,在"aaaa"中,子字符串"aa": 使用indexOf方法,第一次找到0,index变为2,第二次找到2,count=2,index变为4,循环结束。所以返回2次。 而split方法,split(subStr, -1),分割后的数组是 ["", "", ""],所以数组长度是3,减去1得到2次。这时候两者的结果一致。那可能我之前的例子中的测试错误? 可能我之前的例子中,split后的数组长度是3,所以返回2,这和indexOf的方法得到的次数是一致的。比如,字符串是"ababab",split用"ab"分割,得到["", "", "", ""],长度4,减去1得到3次,和indexOf方法一致。那这种情况下split方法似乎可行。但需要考虑特殊情况,例如当子字符串出现在开头或结尾的情况。 例如,字符串是"ababa",子字符串是"aba"。split("aba")的话,分割成["", "ba"],数组长度是2,所以次数是1。而用indexOf方法的话,第一次在0找到,index变为3,然后在位置3,源字符串长度是5,剩下的是"ba",无法再找到,所以count是1。split方法返回的是正确的。 那在这种情况下,split方法可能有效。但需要注意的是,split处理的是正则表达式,所以必须对子字符串进行转义,否则如果子字符串中有正则的元字符,会导致错误。例如,子字符串是".",这时候split(".")会分割成每个字符之间的空,这显然不正确。因此,在使用split方法时,必须用Pattern.quote(subStr)来转义子字符串中的特殊字符。 所以,split方法可以工作,但需要注意转义,并且在处理某些情况下可能与预期不同吗?比如,当子字符串是空字符串时,split会抛出异常,所以在代码中必须处理这种情况。例如,用户传入空的子字符串,应该直接返回0,或者在方法开始处处理。 例如,用户可能调用countOccurrences("abc", ""),这时候应该返回0,因为空字符串无法有效统计。或者根据Java中的定义,字符串中空字符串出现的次数是length+1次?例如,"abc"中,空字符串出现的位置是0,1,2,3,共四次。所以需要明确如何处理这种情况。但根据用户的问题,用户可能希望统计的是非空子字符串的出现次数,所以可能在方法开始时检查子字符串是否为空,如果是的话返回0。 综上,两种方法都可以,但需要考虑不同的情况: indexOf方法: 优点:直接,不需要处理正则表达式的问题,容易控制是否允许重叠(如果需要允许重叠,可以将index更新为foundIndex +1,而不是加上子字符串长度)。 缺点:需要手动处理循环。 split方法: 优点:代码简洁。 缺点:需要处理正则表达式转义,且无法处理重叠的情况。例如,如果用户希望统计重叠出现的次数,例如在"aaaa"中统计"aa"的次数,如果允许重叠的话,应该出现3次(在位置0,1,2),但split方法会得到非重叠的2次,而indexOf方法如果每次更新index为foundIndex+1,则可以统计到3次。因此,是否需要处理重叠的情况需要明确。 用户的问题中没有说明是否要考虑重叠的情况,所以可能需要提供两种方法,或者明确说明。 回到用户的问题,用户可能只是需要统计常规的非重叠次数,因此indexOf方法是更可靠的选择,同时可以处理不同情况。 此外,还有一种方法是使用正则表达式,通过Matcher的find方法,每次查找子字符串的出现,此时同样需要考虑是否允许重叠。例如: public static int countOccurrencesRegex(String str, String subStr) { if (subStr.isEmpty() || str.isEmpty()) { return 0; } Pattern pattern = Pattern.compile(Pattern.quote(subStr)); Matcher matcher = pattern.matcher(str); int count = 0; while (matcher.find()) { count++; } return count; } 这种方法同样是非重叠的,因为每次find会自动跳过后面的字符。例如,在"aaaa"中找"aa",会找到0和2的位置,count为2次。而如果允许重叠,这种方法无法直接实现,需要调整正则表达式,例如使用正向预查或者其他方式,但可能比较复杂。 因此,如果用户需要统计所有可能的出现次数,包括重叠的情况,则需要另一种处理方式。例如,每次移动一个字符: public static int countOverlapping(String str, String subStr) { if (subStr.isEmpty() || str.isEmpty() || subStr.length() > str.length()) { return 0; } int count = 0; int index = 0; while (index <= str.length() - subStr.length()) { int foundIndex = str.indexOf(subStr, index); if (foundIndex == -1) { break; } count++; index = foundIndex + 1; // 每次移动一个字符,而不是子字符串长度 } return count; } 例如,在"aaaa"中找"aa",index从0开始,找到0,count=1,index=1。找到1,count=2,index=2。找到2,count=3,index=3。此时,str.length() - subStr.length() =4-2=2,所以循环条件为index <=2。当index=3时,不满足循环条件,结束。总共有3次。这与预期重叠的情况一致。 因此,用户的问题可能需要明确是否需要处理重叠的情况,但通常默认是非重叠的。所以在回答时,应该说明这两种情况,并给出相应的代码示例。 总结可能的解决方案: 1. 使用indexOf方法,非重叠统计:每次移动子字符串长度。 2. 使用indexOf方法,允许重叠统计:每次移动1个字符。 3. 使用split方法,但需要注意转义问题。 4. 使用正则表达式Matcher的find方法。 接下来,编写示例代码,并解释不同方法之间的差异,以及如何选择。 另外,需要考虑边界情况,例如: - 源字符串或子字符串为空。 - 子字符串长度大于源字符串。 - 多次出现,包括在开头、中间、结尾。 - 子字符串包含特殊正则字符的情况,比如"."或者"*"等。 在split方法中,必须使用Pattern.quote(subStr)来转义子字符串中的特殊字符,否则会抛出异常或得到错误结果。 例如,当subStr是"."时,split(".")会把字符串按任意字符分割,导致错误。因此必须使用Pattern.compile(Pattern.quote(subStr))或者split(Pattern.quote(subStr))。 因此,在split方法的代码中,应该这样写: String[] parts = str.split(Pattern.quote(subStr), -1); 这样才能正确分割。 因此,在回答用户的问题时,应该提供几种方法,并说明它们的区别,尤其是是否处理重叠的情况,以及如何处理正则表达式中的特殊字符。 最后,还需要考虑效率问题。对于较大的字符串,不同的方法可能有不同的性能表现。例如,使用indexOf的方法可能更高效,因为直接操作字符串,而split方法可能需要创建数组,正则表达式可能有额外的开销。 综上,回答的结构应该是: 1. 问题分析:统计子字符串出现的次数,考虑是否重叠。 2. 方法一:使用indexOf的非重叠统计。 3. 方法二:使用indexOf允许重叠的统计。 4. 方法三:使用split方法(注意转义)。 5. 方法四:使用正则表达式Matcher。 6. 说明各种方法的适用场景,注意事项(如处理空字符串、特殊字符等)。 7. 提供示例代码,并测试案例。 例如,用户需要统计"ababab"中"ab"的次数,结果应为3次。在重叠的情况下,如"aaaa"中"aa",非重叠得到2次,重叠得到3次。 最后,提醒用户注意输入的有效性检查,如子字符串为空的情况,避免程序出错。</think>要统计一个字符串中特定子字符串的出现次数,可以采用以下几种方法。以下将分步骤介绍每种方法的实现及其适用场景。 --- ### **方法一:使用 `indexOf` 方法(非重叠统计)** 此方法通过循环查找子字符串的位置,每次跳过已找到的子字符串长度,避免重叠。 ```java public static int countOccurrences(String str, String subStr) { if (subStr.isEmpty() || str.isEmpty() || subStr.length() > str.length()) { return 0; } int count = 0; int index = 0; while (index <= str.length() - subStr.length()) { int foundIndex = str.indexOf(subStr, index); if (foundIndex == -1) { break; } count++; index = foundIndex + subStr.length(); // 跳过当前子字符串长度 } return count; } ``` **示例**: - `countOccurrences("ababab", "ab")` 返回 `3`。 - `countOccurrences("aaaa", "aa")` 返回 `2`(非重叠)。 --- ### **方法二:允许重叠的统计** 若需统计重叠出现的次数,每次仅移动一个字符: ```java public static int countOverlapping(String str, String subStr) { if (subStr.isEmpty() || str.isEmpty() || subStr.length() > str.length()) { return 0; } int count = 0; int index = 0; while (index <= str.length() - subStr.length()) { int foundIndex = str.indexOf(subStr, index); if (foundIndex == -1) { break; } count++; index = foundIndex + 1; // 仅移动一个字符 } return count; } ``` **示例**: - `countOverlapping("aaaa", "aa")` 返回 `3`(允许重叠)。 --- ### **方法三:使用 `split` 方法** 通过分割字符串统计次数,注意处理正则表达式中的特殊字符: ```java import java.util.regex.Pattern; public static int countWithSplit(String str, String subStr) { if (subStr.isEmpty() || str.isEmpty()) { return 0; } String[] parts = str.split(Pattern.quote(subStr), -1); // 转义特殊字符 return parts.length - 1; } ``` **示例**: - `countWithSplit("ababab", "ab")` 返回 `3`。 - `countWithSplit("a.b.c", ".")` 正确处理特殊字符,返回 `2`。 --- ### **方法四:正则表达式匹配** 使用 `Matcher` 类查找所有匹配项: ```java import java.util.regex.*; public static int countWithRegex(String str, String subStr) { if (subStr.isEmpty() || str.isEmpty()) { return 0; } Pattern pattern = Pattern.compile(Pattern.quote(subStr)); // 转义特殊字符 Matcher matcher = pattern.matcher(str); int count = 0; while (matcher.find()) { count++; } return count; } ``` **示例**: - `countWithRegex("ababab", "ab")` 返回 `3`。 --- ### **注意事项** 1. **空字符串处理**:子字符串为空或长度大于源字符串时,直接返回 `0`。 2. **特殊字符**:若子字符串包含正则元字符(如 `.`、`*`),需用 `Pattern.quote()` 转义。 3. **性能**:`indexOf` 方法效率较高,适合处理大文本。 --- ### **测试用例** ```java public static void main(String[] args) { System.out.println(countOccurrences("ababab", "ab")); // 3 System.out.println(countOverlapping("aaaa", "aa")); // 3 System.out.println(countWithSplit("a.b.c", ".")); // 2 System.out.println(countWithRegex("hello$$world", "$")); // 2 } ``` 根据需选择合适的方法,注意是否需要重叠统计及特殊字符处理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值