精华内容
下载资源
问答
  • 算术和关系运算符相等运算符关系运算符赋值运算符复合赋值运算符下标运算符递增和递减运算符区分前置和后置运算符显式地调用后置运算符成员访问运算符函数调用运算符含有状态的函数对象类lambda是函数对象表示lambda...

    基本概念

    如果一个运算符函数是成员函数,则它的第一个(左侧)运算对象绑定到隐式的this指针上,因此,成员运算符函数的(显式)参数数量比运算符的运算对象总数少一个。

    对于一个运算符函数来说,它或者是类的成员,或者至少含有一个类类型的参数:

    错误,不能为int重定义内置的运算符
    int operator+(int,int);
    

    我们可以重载大多数运算符,但不是全部。我们只能重载已有的运算符,而无权发明新的运算符号。
    在这里插入图片描述
    对于一个重载的运算符来说,其优先级和结合律与对应的内置运算符保持一致。

    直接调用一个重载的运算符函数

    一个非成员运算符函数的等价调用

    data1+data2; //普通的表达式
    operator+(data1,data2); // 等价的函数调用
    

    调用成员运算符函数

    data1+=data2; //基于“调用”的表达式
    data1.operator+=(data2); // 对成员运算符函数的等价调用
    

    某些运算符不应该被重载

    通常情况下,不应该重载逗号、取地址、逻辑与、逻辑或等运算符。

    使用与内置类型一致的含义

    在这里插入图片描述

    选择作为成员或者非成员

    当我们定义重载的运算符时,必须首先决定是将其声明为类的成员函数还是声明为一个普通的非成员函数。在某些时候我们别无选择,因为有的运算符必须作为成员;另一些情况下,运算符作为普通函数比作为成员更好。
    在这里插入图片描述

    %通常定义为非成员
    %=通常定义为类成员,因为它会改变对象的状态
    ++通常定义为类成员,因为它会改变对象的状态
    ->必须定义为类成员,否则编译会报错
    <<通常定义为非成员
    &&通常定义为非成员
    ==通常定义为非成员
    ()必须定义为类成员,否则编译会报错

    输入和输出运算符

    IO标准库分别使用>>和<<执行输入和输出操作。对于这两个运算符来说,IO库定义了用其读写内置类型的版本,而类则需要自定义适合其对象的新版本以支持IO操作。

    重载输出运算符<<

    通常情况下,输出运算符的第一个形参是一个非常量ostream对象的引用。之所以ostream是非常量是因为向流写入内容会改变其状态,而该形参是引用是因为我们无法直接复制一个ostream对象。

    第二个形参一般来说是一个常量的引用,该常量是我们想要打印的类类型。第二个形参是引用的原因是我们希望避免复制实参,而之所以该形参可以是常量是因为(通常情况下)打印对象不会改变对象的内容。
    为了与其他输出运算符保持一致,operator<<一般要返回它的ostream形参。

    示例代码:

    ostream& operator<<(ostream&os,const Sales_data &item){
    	//输出内容
    	os<<item.isbn()<<" "<<item.units_sold;
    	//返回ostream
    	return os;
    }
    

    输出运算符尽量减少格式化操作

    用于内置类型的输出运算符不太考虑格式化操作,尤其不会打印换行符,用户希望类的输出运算符也像如此行事。如果运算符打印了换行符,则用户就无法在对象的同一行内接着打印一些描述性的文本了。相反,令输出运算符尽量减少格式化操作可以使用户有权控制输出的细节。

    输入输出运算符必须是非成员函数

    与iostream标准库兼容的输入输出运算符必须是普通的非成员函数,而不能是类的成员函数。否则,它们的左侧运算对象将是我们的类的一个对象:

    Sales_data data;
    data<<cout; //如果operator<<是Sales_data的成员
    

    因此,如果我们希望为类自定义IO运算符,则必须将其定义为非成员函数。IO运算符通常需要读写类的非公有数据成员,所以IO运算符一般被声明为友元。

    重载输入运算符>>

    通常情况下,输入运算符的第一个形参是运算符将要读取的流的引用,第二个形参是将要读入到的(非常量)对象的引用。该运算符通常会返回某个给定流的引用。 第二个形参之所以必须是个非常量是因为输入运算符本身的目的就是将数据读入到这个对象中。

    输入运算符必须处理输入可能失败的情况,而输出运算符不需要。

    输入时的错误:

    • 当流含有错误类型的数据时读取操作可能失败。
    • 当读取操作到达文件末尾或者遇到输入流的其他错误时也会失败。

    通常情况下,输入运算符只设置failbit。除此之外,设置eofbit表示文件耗尽,而设置badbit表示流被破坏。

    算术和关系运算符

    通常,我们把算术和关系运算符定义成非成员函数以允许对左侧或右侧的运算对象进行转换。因为这些运算符一般不需要改变运算对象的状态,所以形参都是常量的引用。

    算术运算符通常会计算它的两个运算对象并得到一个新值,这个值有别于任意一个运算对象,常常位于一个局部变量之内,操作完成后返回该局部变量的副本作为其结果。如果类定义了算术运算符,则它一般也会定义一个对应的复合赋值运算符。此时最有效的方式是使用复合赋值来定义算术运算符:

    Sales_data operator+(const Sales_data &lhs,const Sales_data &rhs){
    	Sales_data sum = lhs;//把lhs的数据成员拷贝给sum
    	sum+=rhs; //使用复合赋值运算符将rhs加到sum中
    	return sum;
    }
    

    如果类同时定义了算术运算符和相关的复合赋值运算符,则通常情况下应该使用复合赋值来实现算术运算符。

    相等运算符

    通常情况下,c++中的类通过定义相等运算符来检验两个对象是否相等。也就是说,它们会比较对象的每一个数据成员,只有当所有对应的成员都相等时才认为两个对象相等。

    关系运算符

    定义了相等运算符的类也常常(但不总是)包括关系运算符。特别是,因为关联容器和一些算法要用到小于运算符,所以定义operator<会比较有用。

    通常情况下,关系运算符应该:

    • 定义顺序关系,令其与关联容器中对关键字的要求一致。
    • 如果类同时也含有 == 运算符的话,则定义一种关系令其与 == 保持一致。特别是,如果两个对象是 != 的,那么一个对象应该 < 另外一个。

    如果存在唯一一种逻辑可靠的 < 定义,则应该考虑为这个类定义 < 运算符。如果类同时还包含 == ,则当且仅当 < 的定义和 == 产生的结果一致时才定义 < 运算符。

    赋值运算符

    我们可以重载赋值运算符,不论形参的类型是什么,赋值运算符都必须定义为成员函数。

    示例代码:
    在这里插入图片描述

    复合赋值运算符

    复合赋值运算符不非得是类的成员,不过我们还是倾向于把包括复合赋值在内的所有赋值运算都定义在类的内部。为了与内置类型的复合赋值保持一致,类中的复合赋值运算符也要返回其左侧运算对象的引用。

    示例代码:
    在这里插入图片描述
    赋值运算符必须定义成类的成员,复合赋值运算符通常情况下也应该这样做。这两类运算符都应该返回左侧运算对象的引用。

    下标运算符

    表示容器的类通常可以通过元素在容器中的位置访问元素,这些类一般会定义下标运算符operator[ ]。

    下标运算符必须是成员函数。

    为了与下标的原始定义兼容,下标运算符通常以所访问元素的引用作为返回值,这样做的好处是下标可以出现在赋值运算符的任意一端。进一步,我们最好同时定义下标运算符的常量版本和非常量版本,当作用于一个常量对象时,下标运算符返回常量引用以确保我们不会给返回的对象赋值

    示例代码:
    在这里插入图片描述

    递增和递减运算符

    定义递增和递减运算符的类应该同时定义前置版本和后置版本。这些运算符通常应该被定义成类的成员。

    为了与内置版本保持一致,前置运算符应该返回递增或递减后对象的引用。
    在这里插入图片描述
    在这里插入图片描述

    区分前置和后置运算符

    前置和后置版本使用的是同一个符号,意味着其重载版本所用的名字将是相同的,并且运算对象的数量和类型也相同。为了解决这个问题,后置版本接受一个额外的(不被使用的)int类型的形参。当我们使用后置运算符时,编译器为这个形参提供一个值为0的实参。尽管从语法上来说,后置函数可以使用这个额外的形参,但是在实际过程中通常不会这么做。这个形参的唯一作用就是区分前置版本和后置版本的函数,而不是真的要在实现后置版本时参与运算。

    为了与内置版本保持一致,后置运算符应该返回对象的原值(递增或递减之前的值),返回的形式是一个值而非引用。

    后置版本示例代码:
    在这里插入图片描述

    显式地调用后置运算符

    StrBlobPtr p(a1);
    p.operator++(0);  //调用后置版本的operator++
    p.operator++();   //调用前置版本的operator++
    

    成员访问运算符

    箭头运算符 -> 必须是类的成员。解引用运算符 * 通常也是类的成员。

    重载的箭头运算符必须返回类的指针或者自定义了箭头运算符的某个类的对象。

    函数调用运算符

    如果类重载了函数调用运算符,则我们可以像使用函数一样使用该类的对象。因为这样的类同时也能存储状态,所以与普通函数相比它们更加灵活。

    函数调用运算符必须是成员函数,一个类可以定义多个不同版本的调用运算符,相互之间应该在参数数量或类型上有所区别。

    如果类定义了调用运算符,则该类的对象称作函数对象。因为可以调用这种对象,所以我们说这些对象的“行为像函数一样”。

    class absInt{
    	int operator()(int val)const{
    		return val < 0 ? -val : val;
    	}
    }
    
    int i=-42;
    absInt absObj;		//含有函数调用运算符的对象
    int ui = absObj(i);  //将i传递给absObj.operator()
    

    即使absObj只是一个对象而非函数,我们也能“调用”该对象。调用对象实际上是在运行重载的调用运算符。该例中,该运算符接受一个int值并返回其绝对值。

    含有状态的函数对象类

    和其他类一样,函数对象类除了operator()之外也可以包含其他成员。函数对象类通常含有一些数据成员,这些成员被用于定制调用运算符中的操作。

    示例代码:

    #ifndef PRINTSTRING_H
    #define PRINTSTRING_H
    
    #include<iostream>
    #include<string>
    using namespace std;
    
    class PrintString
    {
    public:
    	PrintString(ostream &o=cout,char c=' ') :os(o),sep(c){}
    	void operator()(const string &s)const { os << s << sep; }
    private:
    	ostream &os;
    	char sep;
    };
    #endif
    
    

    测试代码:

    void testPrintString() {
    	PrintString p1;
    	p1("hello");
    	PrintString p2(cout, '!');
    	p2("hello");
    }
    

    输出结果:

    hello hello!
    

    示例代码:

    //IntCompare类
    class IntCompare {
    public:
    	IntCompare(int v) :val(v) {}
    	bool operator()(int v) { return val == v; }
    private:
    	int val;
    };
    	//测试代码
    	vector<int>vec = { 1,2,3,2,1 };
    
    	int oldVal = 2;
    	int newVal = 200;
    	IntCompare icmp(oldVal);
    
    	replace_if(vec.begin(),vec.end(),icmp,newVal);
    
    	for (auto a:vec) {
    		cout << a << " ";
    	}
    

    输出结果:

    1 200 3 200 1
    

    lambda是函数对象

    在lambda表达式产生的类中含有一个重载的函数调用运算符,例如:

    [](const string & a , const string & b){return a.size()<b.size();}
    

    其行为类似于下面这个类的一个未命名对象:

    class ShortString{
    public:
    	bool operator()(const string & a , const string & b)		
    		{return a.size()<b.size();}
    }
    

    该类可被如下调用:

    stable_sort(words.begin(),words.end(),ShortString());
    

    当stable_sort内部的代码每次比较两个string时就会“调用”这一对象,此时该对象将调用运算符的函数体,判断第一个string的大小小于第二个时返回true。

    表示lambda及相应捕获行为的类

    当一个lambda表达式通过引用捕获变量时,将由程序负责确保lambda执行时引用所引的对象确实存在。因此编译器可以直接使用该引用而无须在lambda产生的类中将其存储为数据成员。

    如果通过值捕获的变量被拷贝到lambda中,这种lambda产生的类必须为每个值捕获的变量建立对应的数据成员,同时创建构造函数,令其使用捕获的变量的值来初始化数据成员。

    示例如下:

    [sz](const string & a){return a.size()>=sz;}
    

    该lambda表达式产生的类将形如:

    class SizeComp{
    public:
    	SizeComp(size_t n):sz(n){}  //该形参对应捕获的变量
    	//该调用运算符的返回类型、形参和函数体都与lambda一致
    	bool operator(){const string & s}const{
    		return s.size()>=sz;
    	}
    private:
    	size_t sz;//该数据成员对应通过值捕获的变量
    }
    

    这个类含有一个数据成员以及一个用于初始化该成员的构造函数。这个合成的类不含有默认构造函数,因此要想使用这个类必须提供一个实参:

    auto wc = find_if(words.begin(),words.end(),SizeComp(sz));
    

    lambda表达式产生的类不含默认构造函数、赋值运算符及默认析构函数;它是否含有默认的拷贝 / 移动构造函数则通常要视捕获的数据成员类型而定。

    标准库定义的函数对象

    标准库定义了一组表示算术运算符、关系运算符和逻辑运算符的类,每个类分别定义了一个执行命名操作的调用运算符。例如,plus类定义了一个函数调用运算符用于对一对运算对象执行+的操作;modulus类定义了一个调用运算符执行二元的%操作;equal_to类执行==。
    示例代码

    	plus<int>intAdd;
    	negate<int>intNegate;//negate<int>可对int取反
    	int sum = intAdd(10,20);
    	cout << sum << endl;
    	sum = intNegate(intAdd(10, 20));
    	cout << sum << endl;
    	sum = intAdd(10, intNegate(20));
    	cout << sum << endl;
    

    输出结果:

    30
    -30
    -10
    

    标准库函数对象,下表所列的类型定义在functional头文件中
    在这里插入图片描述

    在算法中使用标准库函数对象

    表示运算符的函数对象常用来替换算法中的默认运算符。例如,默认情况下,排序算法使用operator<将序列按照升序排列,如果要执行降序排列的话,我们可以传入一个greater类型的对象。该类将产生一个调用运算符并负责执行待排序类型的大于运算。例如,如果svec是一个vector<string>

    sort(svec.begin(),svec.end(),greater<string>());
    

    示例代码:

    	vector<int>vec{ 1,3,5,7,9,2,4,6,8,10 };
    	//统计大于4的值有多少个
    	int num = count_if(vec.begin(),vec.end(),bind2nd(greater<int>(),4));
    	cout << num << endl;
    
    	vector<string>sv{"hello","hello","hi","nihao","nihao"};
    	//找到第一个不等于hello的字符串
    	auto its = find_if(sv.begin(),sv.end(), bind2nd(not_equal_to<string>(), "hello"));
    	cout << *its << endl;
    
    	//将所有的值乘以2
    	transform(vec.begin(), vec.end(), vec.begin(), bind2nd(multiplies<int>(), 2));
    
    	for (auto a:vec) {
    		cout << a << " ";
    	}
    	cout << endl;
    

    输出结果:

    6
    hi
    2 6 10 14 18 4 8 12 16 20
    

    transform函数

    transform函数的作用是:将某操作应用于指定范围的每个元素。transform函数有两个重载版本:

    transform(first,last,result,op);
    first是容器的首迭代器,last为容器的末迭代器,result为存放结果的容器,op为要进行操作的一元函数对象或sturct、class。

    transform(first1,last1,first2,result,binary_op);
    first1是第一个容器的首迭代 器,last1为第一个容器的末迭代器,first2为第二个容器的首迭代器,result为存放结果的容器,binary_op为要进行操作的二元函数 对象或sturct、class。

    可调用对象与function

    c++语言中有几种可调用的对象:函数、函数指针、lambda表达式、bind创建的对象以及重载了函数调用运算符的类。

    和其他对象一样,可调用的对象也有类型。例如,每个lambda有它自己唯一的(未命名)类类型;函数及函数指针的类型则由其返回值类型和实参类型决定,等等。

    不同类型可能具有相同的调用形式

    在这里插入图片描述
    上面这些可调用对象分别对其参数执行了不同的算术运算。尽管它们的类型各不相同,但是共享同一种调用形式:int(int,int)

    我们可以定义一个函数表用于存储指向这些可调用对象的“指针”。当程序需要执行某个特定的操作时,从表中查找该调用的函数。

    函数表可以很容易的通过map来实现。我们的map可以定义成如下形式:

    //构建从运算符到函数指针的映射关系,其中函数接受两个int、返回一个int
    map<string,int(*)(int,int)>binops;
    

    我们可以按照下面的形式将add的指针添加到binops中:

    binops.insert({"+",add});//{"+",add}是一个pair
    

    但是我们不能将mod或者divide存入binops中,因为mod是个lambda表达式,而每个lambda有它自己的类类型,该类型于存储在binops中的类型不匹配。

    binops.insert({"%",mod});//错误:mod不是一个函数指针
    

    我们可以使用一个名为function的新的标准库类型解决上述问题,function定义在functional头文件中,下表列出了function定义的操作:
    在这里插入图片描述
    function是一个模板,和我们使用过的其他模板一样,当创建一个具体的function类型时我们必须提供额外的信息。示例如下:

    function<int(int,int)>
    

    在这里我们声明了一个function类型,它可以表示接受两个int、返回一个int的可调用对象。

    function<int(int,int)>f1 = add;
    function<int(int,int)>f1 = divide();
    function<int(int,int)>f1 = [](int i,int j){return i*j};
    
    //f1(4,2): 6
    //f2(4,2): 2
    //f3(4,2): 8
    

    使用这个function我们可以重新定义map:

    map<string,function<int(int,int)>>binops;
    

    我们能把所有可调用对象,包括函数指针、lambda或者函数对象在内,都添加到这个map中:

    map<string,function<int(int,int)>>binops={
    {"+",add}, 					 		 //函数指针
    {"-",std::minus<int>()}, 			 //标准库函数对象
    {"/",divide()},						 //用户定义的函数对象
    {"*",[](int i,int j){return i*j}},	 //未命名的lambda
    {"%",mod},							 //命名的lambda
    }
    

    调用操作:

    binops["+"](10,5); //调用add(10,5)
    

    重载的函数与function

    我们不能(直接)将重载函数的名字存入function类型的对象中。
    在这里插入图片描述

    重载、类型转换与运算符

    类型转换运算符

    类型转换运算符是类的一种特殊成员函数,它负责将一个类类型的值转换成其他类型。类型转换函数的一般形式如下所示:

    operator type()const;
    

    其中type表示某种类型。类型转换运算符可以面向任意类型(除了void之外)进行定义,只要该类型能作为函数的返回类型。因此我们不允许转换成数组或者函数类型,但允许转换成指针(包括数组指针及函数指针)或者引用类型。

    一个类型转换函数必须是类的成员函数;它不能声明返回类型,形参列表也必须为空。类型转换函数通常应该是const。

    定义含有类型转换运算符的类

    class SmallInt {
    public:
    	SmallInt(int i = 0) :val(i) {}
    	operator int()const { return val; }
    	void print() { cout << val << endl; }
    private:
    	size_t val;
    };
    
    //测试代码:
    	SmallInt s1;
    	s1 = 4;
    	s1.print();
    	cout << s1 + 5 << endl;
    	s1 = 3.5;
    	s1.print();
    	cout << s1 + 5 << endl;
    

    输出结果:

    4
    9
    3
    8
    

    因为类型转换运算符是隐式执行的,所以无法给这些函数传递实参,当然也就不能在类型转换运算符的定义中使用任何形参。同时,尽管类型转换函数不负责指定返回类型,但实际上每个类型转换函数都会返回一个对应类型的值:
    在这里插入图片描述

    显式的类型转换运算符

    当类型转换运算符是显式的时候,我们也能执行类型转换,不过必须通过显式的强制类型转换才可以。

    class SmallInt {
    public:
    	SmallInt(int i = 0) :val(i) {}
    	explicit operator int()const { return val; }
    	void print() { cout << val << endl; }
    private:
    	size_t val;
    };
    
    //测试代码
    	SmallInt s1;
    	s1 = 4;
    	s1.print();
    	cout << int(s1) + 5 << endl;
    	s1 = 3.5;
    	s1.print();
    	cout << int(s1) + 5 << endl;
    

    如果表达式被用作条件,则编译器会将显式的类型转换自动应用于它。换句话说,当表达式出现在下列位置时,显式的类型转换将被隐式地执行:
    在这里插入图片描述

    向bool的类型转换通常用在条件部分,因此operator bool一般定义成explicit的。

    避免有二义性的类型转换

    如果类中包含一个或多个类型转换,则必须确保在类类型和目标类型之间只存在唯一一种转换方式。否则的话,我们编写的代码很可能会具有二义性。

    在两种情况下,可能产生多重转换路径。

    • 两个类提供相同的类型转换,例如,当A类定义了一个接受B类对象的转换构造函数,同时B类定义了一个转换目标是A类的类型转换运算符时,我们就说它们提供了相同的类型转换。
      在这里插入图片描述
    • 类定义了多个转换规则,而这些转换涉及的类型本身可以通过其他类型转换联系在一起。最典型的例子是算术运算符,对某个给定的类来说,最好只定义最多一个与算术类型有关的转换规则。
      在这里插入图片描述

    除了显式地向bool类型的转换之外,我们应该尽量避免定义类型转换函数并尽可能地限制那些“显然正确”的非显式构造函数。

    展开全文
  • 注意:匹配单词时,不区分大小写,但要求完全匹配,即给定单词必须文章中的某一独立单词在不区分大小写的情况下完全相同,如果给定单词仅是文章中某一单词的一部分则不算匹配。 输入格式 共2行。 第1行为一个...

    题目:给定一个单词,请你输出它在给定的文章中出现的次数和第一次出现的位置。注意:匹配单词时,不区分大小写,但要求完全匹配,即给定单词必须与文章中的某一独立单词在不区分大小写的情况下完全相同,如果给定单词仅是文章中某一单词的一部分则不算匹配。
    输入格式
    共2行。
    第1行为一个字符串,其中只含字母,表示给定单词;
    第2行为一个字符串,其中只可能包含字母和空格,表示给定的文章。
    题目非原创,题目提供者,CCF_NOI
    输出样例
    输入: To
    to be or not to be is a question
    输出 :2 0
    输入:to
    Did the Ottoman Empire lose its power at that time
    输出 : -1
    思路
    1.明显的字符串匹配问题,其中第一行是子字符串
    2.选择匹配方法,本科阶段常用的方法为直接匹配和kmp算法,本题子字符串较为简单,直接用直接匹配就可,因为本人按照数据结构书本编写的直接匹配函数编译错误,就用了一些系统函数直接做了,有大佬经过跪求指点。
    3.写代码:
    #include
    #include

    using namespace std;
    int main(){

    string a;
    string b;//定义两个字符串方便操作
    getline(cin,a);//使用string中的getline方法读入a,b字符串
    getline(cin,b);
    for (int i=0;i<a.length();++i){
        a[i]=tolower(a[i]);
    }
    for (int i=0;i<b.length();++i){
        b[i]=tolower(b[i]);
    }//给a和b转换大小写
    a=' '+a+' ';
    b=' '+b+' ';
    if (b.find(a)==string::npos){
        cout<<-1<<endl;
    }//npos 是一个常数,用来表示不存在的位置(在string中找不到某个要查找的字符)
    else {
        int index=b.find(a);//记录第一次出现的索引位置
        int flag=b.find(a),count=0;
        while (flag!=string::npos){
            ++count;
            flag=b.find(a,flag+1);
        }//设置计数器输出出现的次数
        cout<<count<<" "<<index<<endl;
    }
    return 0;
    

    }

    知识点:

    1. tolower()//转换大小写函数
    2. npos//判断常数
    3. “ ”空格的添加方便精确查找
      //朋友和我说过思路确实有和我相似的人,如有雷同,纯属巧合,毕竟这个题不是我一个人做过
    4. cin和getline的区别
    展开全文
  • javascript--正则表达式

    2016-02-26 05:37:52
    正则表达式 var expression = / pattern / flags; flags:每个正则表达式都可带一个或多个标志,用以标明正则表达式的行为 ...m:表示多行模式,即在到达文本末尾时还会继续查找下一行中是否模式匹配的...
        

    正则表达式

    var expression = / pattern / flags;

    flags:每个正则表达式都可带一个或多个标志,用以标明正则表达式的行为

    • g:表示全局模式,即模式将被应用于所有字符串,而非在发现第一个匹配项时立即停止。

    • i:表示不区分大小写模式

    • m:表示多行模式,即在到达文本末尾时还会继续查找下一行中是否与模式匹配的项。

    正则表达式中的元字符

    这些元字符在正则表达式都有一种或者多种用途。因此如果想要匹配字符串中包含的这些字符必须转义。下面将描述元字符在模式中的各种应用。

    ( [ { \ ^ $ | ) ? * .] }

    字符 含义
    \t 水平制表符
    \n 换行符
    \r 回车符
    \f 换页符
    \cX 与X对应的控制字符(Ctrl+X)
    \v 垂直制表符
    \0 空字符

    所谓类是指,符合某些特征的对象,是一个泛指,而不是特指某个字符。

    使用元字符[ ]构建类。

    1.[ ]:构建简单类

    [abc]
    图片描述
    2.^:与[ ]并用构建反向类

    [^abc]
    图片描述

    3.范围类
    [a-zA-Z]
    图片描述

    边界

    单独使用^代表以xxx开头

    边界元字符
    ^ 以xxx开头
    $ 以xxx结尾
    \b 单词边界
    \B 非单词边界

    ^ab
    图片描述
    ab$
    图片描述
    \ba
    图片描述
    a\b
    图片描述

    元字符|代表或

    a|c
    图片描述

    预定义类

    字符 等价类
    . 1 除了回车符和换行符之外的所有字符
    \d [0-9] 数字字符
    \D 2 非数字字符
    \s [\t\n\x0B\f\r] 空白符
    \S 3 非空白符
    \w [a-zA-Z_0-9] 单词字符,字母、数字下划线
    \W 4 非单词字符

    分组

    使用元字符( )进行分组

    (ab)
    图片描述
    嵌套分组(捕获组):(ab(cd))
    图片描述
    忽略分组:有时候我们不希望捕获某些分组,只需要在分组内加上 ?:就可以了,这并不意味着该分组内容不属于正则表达式,只是不会给这个分组加编号了而已
    (ab(?:cd))
    图片描述

    量词

    代表出现次数,次数都为正整数

    量词元字符
    ? 出现0次或1次 [0,1]
    + 至少出现1次 >=1
    * 出现0次或多次 >=0

    { }元字符
    {n} :出现n次
    {n,m} :出现n到m次
    {n,} :至少出现n次
    {0,m} :最多出现m次

    贪婪模式与非贪婪模式

    {3,5}到底代表匹配3次,4次还是5次呢?在贪婪模式下会尽可能的多的匹配,也就是说会匹配5次,默认是贪婪模式。而在非贪婪模式下则尽可能少的匹配,也就说会匹配3次,在量词后面加上?即可

    贪婪模式'123456789'.replace(/\d{5,8}/g,'O');//"O9"
    非贪婪模式'123456789'.replace(/\d{5,8}?/g,'O');//"06789"

    前瞻

    表达式 含义
    exp1(?=exp2) 匹配后面是exp2的exp1
    exp1(?!exp2) 匹配后面不是exp2的exp

    good(?=bad) ![]()
    good(?!bad) ![]()

    正则表达式实例方法

    exec()

    参数:接收一个参数,即要应用模式的 字符串
    返回:第一个匹配项信息的数组,或者在没有匹配项的情况下返回null。

    返回的数组包含两个额外的信息:index和input。index匹配项在字符串中的位置,input表示应用正则表达式的字符串。在数组中,第一项是与整个模式匹配的字符串,其他项是与模式中的捕获组匹配的字符串(如果模式中没有捕获组,则该数组只包含一项)

    var text = 'mom and dad and baby';
    var pattern = /mom( and dad)( and baby?)?/g
    
    var matches = pattern.exec(text);
    
    matches// ["mom and dad and baby", " and dad", " and baby"]
    matches.index// 0
    matches.input// 'mom and dad and baby'
    
    // 忽略分组
    var matches = /mom(?: and dad)(?: and baby?)?/g.exec(text)
    matches// ["mom and dad and baby"]
    
    var matches = /mom( and dad)(?: and baby?)?/g.exec(text)
    matches// ["mom and dad and baby", " and dad"]
    
    var matches = /mom(?: and dad)( and baby?)?/g.exec(text)
    matches// ["mom and dad and baby", " and baby"]

    Note:对于exec()方法即使在模式中设置了全局标志(g),它每次也只返回一个匹配项。但是在同一个字符串上多次调用exec()则会在字符串中查找新匹配项。而在不设置全局标志的情况下,在同一个字符串上多次调用exe(),始终返回第一个匹配项信息。

    /*非全局调用*/
    var reg1 = /\d/;
    /*全局调用*/
    var reg2 = /\d/g;
    
    reg1.exec('a1b2c3');//["1"]
    reg1.exec('a1b2c3');//["1"]
    reg2.exec('a1b2c3');//["1"]
    reg2.exec('a1b2c3');//["2"]
    reg2.exec('a1b2c3');//["3"]
    reg2.exec('a1b2c3');//null
    
    while(r=reg.exec('a1b3c3')){
    console.log(r.index+':'+r[0])
    }//1:1 3:2x 5:3

    test()

    参数:接收一个字符串参数

    返回:布尔值
    在想知道目标字符串与某个模式是否匹配,但不需要知道其文本内容的情况下,使用这个方法非常方便。

    var text = '000-00-0000';
    var pattern = /\d{3}-\d{2}-\d{4}/;
    
    if(pattern.test(text)){
        console.log('The pattern was matched')
    } // The pattern was matched
    //分组()->$1分组内匹配
    'a1b2c3'.replace(/a(\d)b(\d)c(\d)/g,'a$1-b$2-c$3');//"a1-b2-c3"
    'a%1b%2c%3'.replace(/%(\d)%/,'#$1#');//"a#1#b%2%c%3%"
    
    //忽略分组
    'a1b2c3'.replace(/a(?:\d)b(?:\d)c(?:\d)/g,'a$1-b$2-c$3');//"a$1-b$2-c$3"
    
    //前瞻
    'goodByron'.replace(/good(?=Byron)/g,'T');//"TByron"
    'goodByron'.replace(/good(?!Byron)/g,'T');//"goodByron"'

    lastIndex:告诉已经搜到哪了,下一次从那开始

    var reg = /\d+/g;
    
    reg.test('a1b2c3');//true
    reg.lastIndex//2
    reg.test('a1b2c3');//true
    reg.lastIndex;//4
    reg.test('a1b2c3');//true
    reg.lastIndex//6
    reg.test('a1b2c3');//false
    reg.lastIndex;//0

    参考网站:Regexper


    1. \r\n
    2. 0-9
    3. \t\n\x0B\f\r
    4. a-zA-Z_0-9
    展开全文
  • RegExp类型

    2012-06-07 22:57:10
    每个正则表达式都可带有一个或者多个标志,用以...i: 表示区分大小写(case-insensitive)模式,即在确定匹配项时忽略模式字符串的大小写 m: 表示多行(multiline)模式,即在到达一行文本末尾时还会继续查找下一行中

    每个正则表达式都可带有一个或者多个标志,用以标明正则表达式的行为。正则表达式的匹配模式支持下列3个标志:

    g:表示全局(global)模式,即模式将被应用于所有字符串,而非在发现第一个匹配项时立即停止。

    i: 表示不区分大小写(case-insensitive)模式,即在确定匹配项时忽略模式与字符串的大小写

    m: 表示多行(multiline)模式,即在到达一行文本末尾时还会继续查找下一行中是否存在与模式匹配的项。

    //匹配字符串总所有"at"的实例

    var pattern1= /at/g;

    //匹配第一个"bat"或"cat",不区分大小写

    var pattern2 =/[bc]at/i;

    //匹配所有以"at"结尾的3个字符的组合,不区分大小写

    var pattern3= /.at/gi;

    RegExp对象的主要方法是exec(),该方法是专门为捕获组而设计的。exec()接受一个参数,即要应用模式的字符串,然后返回包含第一个匹配项信息的数组;或者在没有匹配项的情况下返回null。返回的数组虽然是Array的实例,但包含两个额外的属性:index和input.其中,index表示匹配项在字符串中的位置,而input表示应用正则表达式的字符串。在数组中,第一项是与整个模式匹配的字符串,其他项是与模式中的捕获组匹配的字符串

    对于exec()方法而言,即使在模式中设置了全局标志(g),它每次也只返回一个匹配项。在不设置全局标志的情况下,在同一个字符串上多次调用exec()将始终返回第一个匹配项的信息。在设置了全局标志的情况下,每次调用exec()则都会在字符串中继续查找新匹配项。

    正则表达式的第二个方法是test(),他接受一个字符串参数。在模式与该参数匹配的情况下返回true.否则,返回false。在只想知道目标字符串与某个模式是否匹配,但不需要知道其文本内容的情况下,使用这个方法非常方便。因此,test()方法经常被用在if语句中。

    展开全文
  • 我们显示,当以有效物理参数表示时,带电的GB黑色麸皮的热力学行为与带电的爱因斯坦黑麸皮的热力学行为是完全无法区分的。 此外,两类黄铜的极值,近水平极限是完全相同的,因为它们允许相同的AdS 2×R 3,近水平,...
  • JAVA面试题最全集

    2010-03-13 13:09:10
    81.UML中,类视图如何表示类中的继承聚合? 82.客户端游标服务器端游标的区别? 83.动态游标静态游标的区别? 84.dotnet由哪几个基本框架组成? 85.Oracle中SGA是什么? 86.web servers是什么? 87.UNIX中QT是...
  • 建议136:优先使用后缀表示已有类型的新版本 / 306 建议137:委托和事件类型应添加上级后缀 / 307 建议138:事件和委托变量使用动词或形容词短语命名 / 308 建议139:事件处理器命名采用组合方式 / 309 第11章 ...
  • &是位运算符,表示按位运算,&&是逻辑运算符,表示逻辑(and)。 14、HashMap和Hashtable的区别。 HashMap是Hashtable的轻量级实现(线程安全的实现),他们都完成了Map接口,主要区别在于HashMap允许空...
  • java 面试题 总结

    2009-09-16 08:45:34
    &是位运算符,表示按位运算,&&是逻辑运算符,表示逻辑(and)。 11、HashMap和Hashtable的区别。 HashMap是Hashtable的轻量级实现(线程安全的实现),他们都完成了Map接口,主要区别在于HashMap允许空...
  • 高级Shell脚本编程

    2013-10-28 10:08:19
    33.1. 交互与非交互式的交互与非交互式的shell和脚本 33.2. Shell包装 33.3. 测试和比较: 一种可选的方法 33.4. 递归 33.5. 将脚本"彩色化" 33.6. 优化 33.7. 各种小技巧 33.8. 安全问题 33.9. 可移植性问题...
  • 入门学习Linux常用必会60个命令实例详解doc/txt

    千次下载 热门讨论 2011-06-09 00:08:45
    这是因为Linux和许多版本的Unix一样,提供了虚拟控制台的访问方式,允许用户在同一时间从控制台(系统的控制台是系统直接相连的监视器和键盘)进行多次登录。每个虚拟控制台可以看作是一个独立的工作站,工作台...
  • 图像分类 是根据图像的语义信息对不同类别图像进行区分,是计算机视觉中重要的基础问题,是物体检测、图像分割、物体跟踪、行为分析、人脸识别等其他高层视觉任务的基础,在许多领域都有着广泛的应用。如:安防领域...
  • 本章还将介绍确定字符关系(如测试字符是数字还是打印字符)的函数库cctype。最后,还将简要地介绍 文件输入/输出。 第7章:函数——C++的编程模块 函数是C++的基本编程部件。本章重点介绍C++函数C函数共同...
  • 本章还将介绍确定字符关系(如测试字符是数字还是打印字符)的函数库cctype。最后,还将简要地介绍 文件输入/输出。 第7章:函数——C++的编程模块 函数是C++的基本编程部件。本章重点介绍C++函数C函数共同...
  • 本章还将介绍确定字符关系(如测试字符是数字还是打印字符)的函数库cctype。最后,还将简要地介绍 文件输入/输出。 第7章:函数——C++的编程模块 函数是C++的基本编程部件。本章重点介绍C++函数C函数共同...
  • 表示层为了用户交互例如用户添加表单。 优点: 分工明确,条理清晰,易于调试,而且具有可扩展性。 缺点: 增加成本。 12.在下面的例子里 using System; class A { public A() { PrintFields(); } ...
  • 正数的反码和补码原码表示相同。 负数的反码原码有如下关系: 符号位相同(仍用1表示),其余各位取反(0变1,1变0)。 补码由该数反码的最末位加1求得。 第 二 章 C++简单程序设计 2-1 C++语言有那些主要特点和...
  • JavaScript王者归来

    2013-01-10 11:30:48
    12.7 外观与行为 12.7.1 DOM样式属性 12.7.2 控制DOM元素的显示隐藏 12.7.3 改变颜色和大小--一个简单有趣的例子 12.7.4 改变位置--创建一个绕圆圈旋转的文字 12.7.5 编辑控制及其范例 12.7.6 改变样式及其范例 ...
  • WM_CTLCOLOR消息缺省处理函数CWnd::OnCtlColor返回一个HBRUSH类型的句柄,这样,就可以设置前景和背景文本颜色,并为控件或者对话框的文本区域选定一个刷子。 WM_CTLCOLOR的映射函数原型如下: afx_msg HBRUSH ...
  • 可以通过能否实现Copy trait来区分数据类型的值语义和引用语义。但为了描述的更加精准,Rust也引入了新的语义:复制(Copy)语义和移动(Move)语义。复制语义对应值语义࿰...
  • 操作是数据库中定义的"原子行为",每个操作都在日志文件中保存为一条记录。它可以是用户直接输入的SQL语句,比如标准的insert命令,日志文件中便会记录一条操作代码来标志这个insert操作。 事物(Transaction) ...
  • VB.NET 入门经典 (第三版)

    热门讨论 2009-07-29 16:56:26
    2.1.3 .NETJava有些类似 26 2.1.4 现在所处的阶段 27 2.2 为Windows编写软件 27 2.2.1 .NET Framework类 28 2.2.2 执行代码 29 2.3 公共语言运行库 30 2.3.1 载入并执行代码 31 2.3.2 应用程序隔离 31 2.3.3 安全...
  • 《Effective c++ 》

    千次下载 热门讨论 2013-02-25 22:13:11
    条款34:区分接口继承和实现继承 161 differentiate between inheritance of interface and inheritance of implementation 161 条款35:考虑virtual函数以外的其他选择 169 consider alternatives to virtual ...
  • <code>0.1和<code>0.2的二进制浮点表示都不是精确的,所以相加后不是<code>0.3</code>,接近(不等于)<code>0.30000000000000004。 所以,比较数字时,应该有个宽容值。ES6中...
  • asp.net知识库

    2015-06-18 08:45:45
    DotNet数据对象结合的自定义数据对象设计 (二) 数据集合DataTable DotNet数据对象结合的自定义数据对象设计 (一) 数据对象DataRow ASP.NET中大结果集的分页[翻译] .net 2.0 访问Oracle --Sql Server的...
  • 涉及到各种nlp相关的算法,基于keras和tensorflow 、Python文本挖掘/NLP实战示例、 Blackstone:面向结构化法律文本的spaCy pipeline和NLP模型通过同义词替换实现文本“变脸” 、中文 预训练 ELECTREA 模型: ...
  • 我一同工作的同志对本研究所做的任何贡献均已在论文中作了明确的说明并表示了谢意。 研究生签名: 日期: 东南大学学位论文使用 授权声明 东南大学、中国科学技术信息研究所、国家图书馆有权保留本人...
  • C++MFC教程

    热门讨论 2013-05-21 13:37:15
    CompareNoCase 不区分大小写比较 MakeUpper 改为小写 MakeLower 改为大写 CStringArray:用来表示可变长度的字符串数组。数组中每一个元素为CString对象的实例。下面介绍几个成员函数: Add 增加CString Remove...
  • php高级开发教程说明

    2008-11-27 11:39:22
    最优解决方案。 更大的项目如果缺乏计划将导致更多的错误,在开发后期,可能会遇到没有或无法预见的 困难,这是由于缺乏计划的时间和工作,这些困难可能会严重到让你彻底地重组整个项目。例 如,对一个依赖额外...

空空如也

空空如也

1 2
收藏数 36
精华内容 14
关键字:

区分表示行为与非表示行为