string_stringbuilder - CSDN
string 订阅
string是C++、java、VB等编程语言中的字符串,字符串是一个特殊的对象,属于引用类型。 在java、C#中,String类对象创建后,字符串一旦初始化就不能更改,因为string类中所有字符串都是常量,数据是无法更改,由于string对象的不可变,所以可以共享。对String类的任何改变,都是返回一个新的String类对象。 C++标准库中string类以类型的形式对字符串进行封装,且包含了字符序列的处理操作。 [1-2] 展开全文
string是C++、java、VB等编程语言中的字符串,字符串是一个特殊的对象,属于引用类型。 在java、C#中,String类对象创建后,字符串一旦初始化就不能更改,因为string类中所有字符串都是常量,数据是无法更改,由于string对象的不可变,所以可以共享。对String类的任何改变,都是返回一个新的String类对象。 C++标准库中string类以类型的形式对字符串进行封装,且包含了字符序列的处理操作。 [1-2]
信息
属    性
编程语言
外文名
String
所属领域
计算机
中文名
字符串
string基本信息
String就是C++、java、VB等编程语言中的字符串,用双引号引起来的几个字符,如"Abc","一天".
收起全文
精华内容
参与话题
  • String类型

    千次阅读 2018-09-28 15:33:42
    String类型 一、相关概念 1.定义 String类型是字符串的对象包装类型 创建String对象 var stringObject=new String("hello world"); ...

    String类型

    一、相关概念

    1.定义

    1. String类型是字符串的对象包装类型
    2. 创建String对象
    var stringObject=new String("hello world");
    

    2.补充

    1. String对象大方法也可以在所有基本的字符串值中访问到
    2. 继承的valueOf()toLocaleString()toString()方法,都返回对象所表示的基本字符串值

    二、属性

    1.length

    1. String类型的每个实例都有一个length属性,表示字符串中包含多个字符
    2. 字符串中包含双字节字符(不是占一个字节的ASCII字符),每个字符仍然算一个字符
    var stringValue=new String("hello world");
    alert(stringValue.length);/"11"
    

    三、方法

    (一).字符方法

    1.charAt()
    1. 接收一个参数,基于0的字符位置
    2. 以单字符字符串的形式返回给定位置的哪个字符(ECMAScript中没有字符类型)
    var stringValue=new String("hello world");
    alert(stringValue.charAt(1));//"e"
    
    2.charCodeAt()
    1. 接收一个参数,基于0的字符位置
    2. 以单字符字符串的形式返回给定位置的哪个字符的字符编码
    var stringValue=new String("hello world");
    alert(stringValue.charCodeAt(1));//"101"
    
    3.方括号表示法
    1. 在支持的浏览器中,可以使用方括号加数字索引来访问字符串中的特定字符
    2. 使用方括号表示法访问个别字符的语法得到了IE8FirefoxSafariChromeOpera所有版本的支持
    3. 如果是在IE7及更早版本中使用这种语法,会返回undefined值(尽管根本不是特殊的undefined值)
    var stringValue=new String("hello world");
    alert(stringValue[1]);//"e"
    

    (二).字符串操作方法

    1.concat()
    1. concat()用于将一或多个字符串拼接起来,返回拼接得到的新字符串。不改变原字符串
    2. concat()方法可以接收任意多个参数,也就是说可以通过它拼接任意多个字符串
    3. 虽然concat()是专门用来拼接字符串的方法,但实践中使用更多的还是加号操作符(+)。而且,使用加号操作符在大多数情况下都比使用concat()方法要简便易行(特别是在拼接多个字符串的情况下)
    var stringValue=new String("hello ");
    var result=stringValue.concat("world");
    alert(result);//"hello world"
    alert(stringValue);//"hello "
    
    var stringValue=new String("hello ");
    var result=stringValue.concat("world","!");
    alert(result);//"hello world!"
    alert(stringValue);//"hello "
    
    2.slice()
    1. 返回被操作数的一个子字符串,而且也接收一或两个参数。第一个参数指定子字符串的开始位置,第二个参数(在指定的情况下)表示子字符串到哪里结束
    2. 第二个参数指定的是子字符串最后一个字符后面的位置
    3. 如果没有给这些方法传递第二个参数,则将字符串的末尾作为结束吧位置
    4. 不会修改字符串本身的值——只是返回一个基本类型的字符串值,对原字符串没有任何影响
    5. 传入参数是负数时,slice()会将传入的负值与字符串的长度相加
    var stringValue=new String("hello world");
    alert(stringValue.slice(3));//"lo  world" 
    alert(stringValue.slice(3,7));//"lo w" 
    
    var stringValue=new String("hello world");
    alert(stringValue.slice(-3));//"rld"
    alert(stringValue.slice(3,-4));//"lo w"
    
    3.substr()
    1. 返回被操作数的一个子字符串,而且也接收一或两个参数。第一个参数指定子字符串的开始位置,第二个参数(在指定的情况下)表示子字符串到哪里结束
    2. 第二个参数指定的是返回的字符个数
    3. 如果没有给这些方法传递第二个参数,则将字符串的末尾作为结束吧位置
    4. 不会修改字符串本身的值——只是返回一个基本类型的字符串值,对原字符串没有任何影响
    5. 传入参数是负数时,substr()方法会将负的第一个参数加上字符串的长度,而将将负的第二个参数转换为0
    var stringValue=new String("hello world");
    alert(stringValue.substr(3));//"lo  world"
    alert(stringValue.substr(3,7));//"lo worl"
    
    var stringValue=new String("hello world");
    alert(stringValue.substr(-3));//"rld"
    alert(stringValue.substr(3,-4));//""
    //substr()会将第二个参数转换为0,返回的字符串包含零个字符串,也就是一个空字符串
    
    4.substring()
    1. 返回被操作数的一个子字符串,而且也接收一或两个参数。第一个参数指定子字符串的开始位置,第二个参数(在指定的情况下)表示子字符串到哪里结束
    2. 第二个参数指定的是子字符串最后一个字符后面的位置
    3. 如果没有给这些方法传递第二个参数,则将字符串的末尾作为结束吧位置
    4. 不会修改字符串本身的值——只是返回一个基本类型的字符串值,对原字符串没有任何影响
    5. 传入参数是负数时,substring()方法会将所有的负值参数都转换为0
    var stringValue=new String("hello world");
    alert(stringValue.substring(3));//"lo  world"
    alert(stringValue.substring(3,7));//"lo w"
    
    var stringValue=new String("hello world");
    alert(stringValue.substring(-3));//"hello  world"
    alert(stringValue.substring(3,-4));//"hel"
    //substring()方法会把第二个参数转换为0,也就是substring(3,0),而由于这个方法会将较小的数作为开始位置,将较大数作为结束位置,最终相当于调用了substring(0,3)
    

    (三).字符串位置方法

    1.indexOf()
    1. 从一个字符串中搜索给定的字符串,然后返回怒字符串的位置(如果没有找到该字符串,则返回-1)
    2. indexOf()方法从字符串的开头向后搜索字符串
    3. 如果给定字符串仅出现一次,那么indexOf()lastIndexOf()会返回相同的位置值
    4. 第二个参数(可选)表示从字符串中的哪个位置开始搜索
    5. indexOf()会从该参数指定的位置向后搜索,忽略该位置之前的所有字符
    var stringValue=new String("hello world");
    alert(stringValue.indexOf("o"));//4
    
    var stringValue=new String("hello world");
    alert(stringValue.indexOf("o",6));//7
    
    var strinngValue="Lorem ipsum dolor sit amet, consectetur adipisicing elit";
    var positions=new Array();
    var pos=stringValue.indexOf("e");
    while(pos>-1){
    	positions.push(pos);
    	pos=stringValue.indexOf("e",pos+1);
    }
    alert(positions);
    
    2.lastIndexOf()
    1. 从一个字符串中搜索给定的字符串,然后返回怒字符串的位置(如果没有找到该字符串,则返回-1)
    2. lastIndexOf()方法是从字符串的末尾向前搜索字符串
    3. 第二个参数(可选)表示从字符串中的哪个位置开始搜索
    4. lastIndexOf()会从该参数指定的位置向前搜索,忽略该位置之后的所有字符
    var stringValue=new String("hello world");
    alert(stringValue.lastIndexOf("o"));//7
    
    var stringValue=new String("hello world");
    alert(stringValue.lastIndexOf("o",6));//4
    

    (四).trim()方法

    1. trim()会创建一个字符串的副本,删除前置及后缀的所有空格,然后返回结果
    2. trim()返回的是字符串的副本,所以原始字符串中的前置及后缀空格会保持不变
    3. 支持这个方法的浏览器有IE 9+Firefox 3.5+Safari 5+Opera 10.5+Chrome
    4. 此外,Firefox 3.5+Safari 5+Chrome 8+还支持非标准的trimLeft()trimRight()方法,分别用于删除字符串开头和末尾的空格
    var stringValue=new String(" hello world ");
    var trimmedStringValue=stringValue.trim();
    alert(stringValue);" hello world "
    alert(trimmedStringValue);//"hello world"
    

    (五).字符串大小写转换方法

    1.toLowerCase()
    1. 借鉴自java.lang.String中的同名方法,将对象转换为小写
    var stringValue=new String("hello world");
    alert(stringValue.toLowerCase());//"hello world"
    
    2.toLocaleLowerCase()
    1. 针对特定时区,将对象转换为小写
    2. 一般来说,在不知道自己的代码将在哪种语言环境中运行的情况下,还是使用针对地区的方法更稳妥一些
    var stringValue=new String("hello world");
    alert(stringValue.toLocaleLowerCase());//"hello world"
    
    3.toUpperCase()
    1. 借鉴自java.lang.String中的同名方法,将对象转换为大写
    var stringValue=new String("hello world");
    alert(stringValue.toUpperCase());//"HELLO WORLD"
    
    4.toLocaleUpperCase()
    1. 针对特定时区,将对象转换为大写
    2. 一般来说,在不知道自己的代码将在哪种语言环境中运行的情况下,还是使用针对地区的方法更稳妥一些
    var stringValue=new String("hello world");
    alert(stringValue.toLocaleUpperCase());//"HELLO WORLD"
    

    (六).字符串的模式匹配方法

    1.match()
    1. match(),在字符串上调用这个方法,本质上与调用RegExp()exec()方法相同
    2. match()方法只接收一个参数,要么是一个正则表达式,要么是一个RegExp对象
    var text=new String("cat,bat,sat,fat");
    var pattern=/.at/;
    //与pattern.exec(text)相同
    var matches=text.match(pattern);
    alert(matches.index);//0
    alert(matches[0]);
    alert(pattern.lastIndex);//0
    //match()方法返回了一个数组
    //如果是调用RegExp对象的exec()方法并传递本例中的字符串作为参数,那么也会得到与此相同的数组:数组的第一项是与整个模式匹配的字符串,之后的每一项(如果有)保存着与正则表达式中的捕获组匹配的字符串
    
    2.search()
    1. search()方法的唯一参数与match()方法的参数相同:由字符串或RegExp对象指定的一个正则表达式
    2. search()方法返回字符串中第一个匹配项的索引;如果没有找到匹配项,则返回-1
    3. search()方法始终是从字符串开头向后查找模式
    var text=new String("cat,bat,sat,fat");
    var pos=text.search(/at/);
    alert(pos);//1
    //search()方法返回1,即"at"在字符串中第一次出现的位置
    
    3.replace()
    1. replace()用于替换字符串
    2. 这个方法接收两个参数:第一个参数可以是一个RegExp对象或者一个字符串(这个字符串不会被转换成正则表达式),第二个参数可以是一个字符串或者一个函数
    3. 如果第一个参数是字符串,那么只会替换第一个字符串。要想替换所有子字符串,唯一的办法就是提供一个正则表达式,而且要指定全局(g)标志
    4. 如果第二个参数是字符串,那么还可以使用一些特殊的字符序列,将正则表达式操作得到的值插入到结果字符串中
    5. replace()方法的第二个参数也可以是一个函数。在只有一个匹配项(即与模式匹配的字符串)的情况下,会向这个函数传递3个阐述:模式匹配、模式匹配项在字符串中的位置和原始字符串。在正则表达式中定义了多个捕获组的情况下,传递给函数的参数依次是模式的匹配项、第一个捕获组的匹配项、第二个捕获组的匹配项······,但最后两个参数仍然分别是模式的匹配项在字符串中的位置和原始字符串。这个函数应该返回一个字符串,表示应该被替换的匹配项。使用函数作为replace()方法的第二个参数可以实现更加精细的替换操作
    function htmlEscape(text){
    	return text.replace(/[<>"&]/g,function(match,pos,originalText){
    		switch(match){
    			case "<":return "&lt;";
    			case ">":return "&map;";
    			case "\"":return "&quot;";
    		}
    	};)
    }
    alert(htmlEscape("<p class=\"greeting\">Hello world!</p>"));
    //&lt;p class=&quot;greeting&quot;&gt;Hello world!&lt;/p&gt;
    
    字符序列 替换文本
    $$ $
    $& 匹配整个模式的子字符串。与RegExp.lastMatch的值相同
    $' 匹配的子字符串之前的字符串。与RegExp.leftContext的值相同
    $` 匹配的子字符串之后的子字符串。与RegExp.rightContext的值相同
    $n 匹配第n个捕获组的子字符串,其中n等于0~9.例如,$1是匹配第一个捕获组的子字符串,$2是匹配第二个捕获组的子字符串,以此类推。如果正则表达式中没有定义捕获组,则使用空字符串
    $nn 匹配第nn个捕获组的子字符串,其中nn等于01~99。例如,$01是匹配第一个捕获组的子字符串,$02是匹配第二个捕获组的子字符串,以此类推。如果正则表达式中没有定义捕获组,则使用空字符串
    var text=new String("cat,bat,sat,fat");
    var result=text.replace("at","ond");
    alert(result);//"cond,bat,sat,fat"
    //传入replace()方法的是字符串"at"和替换用的字符串"ond"。替换的结果是把"cat"变成了"cond",但字符串中的其他字符并没有收到任何影响
    
    result=text.replace(/at/g,"ond");
    alert(result);//"cond,bond,sond,fond"
    //通过将第一个参数修改为带有全局标志的正则表达式,就将全部"at"都替换成了"ond"
    
    var text=new String("cat,bat,sat,fat");
    result=text.replace(/(.at)/g,"word($1)");
    alert(result);//word(cat),word(bat),word(sat),word(fat)
    //在此,每个以"at"结尾的单词都被替换了,替换结果是"word"后跟一对圆括号,而圆括号中是被字符序列$1所替换的单词
    
    4.split()
    1. split()方法可以基于指定的分隔符将一个字符串分隔成多个字符串,并将结果放在一个数组中。分隔符可以是字符串,也可以是一个RegExp对象(这个方法不会将字符串看成正则表达式)
    2. split()方法可以接受可选的第二个参数,用于指定数组的大小,以便确保返回的数组不会超过既定大小
    3. split()正正则表达式的支持因浏览器而异。尽管对于简单的模式没什么差别,但对于未发现匹配项及带有捕获组的模式,匹配的行为大不相同
      • IE8及之前版本会忽略捕获组。ECMA-262规定应该把捕获组拼接到结果数组中。IE9能正确地在结果中包含捕获组
      • Firefox 3.6及之前版本在捕获组未找到匹配项时,会在结果数组中包含空字符串;ECMA-262规定没有匹配项的捕获组在结果数组中应该用undefined表示
    var colorText=new String("red,blue,green,yellow");
    var colors1=colorText.split(",");//["red","blue","green","yellow"]
    var colors1=colorText.split(",",2);//["red","blue"]
    var colors1=colorText.split(/[^\,]+/);//["",",",",",""]
    //通过正则表达式指定的分隔符出现在了字符串的的开头(即子字符串"red")和末尾(即子字符串"yellow")
    

    (七).localeCompare()方法

    1. localeCompare()方法比较两个字符串,并返回下列值中的第一个
      • 如果字符串在字母表中应该在字符串参数之前,则返回一个负数(大多数情况下是-1,具体的值要视实现而定)
      • 如果字符串等于字符串参数,则返回0
      • 如果字符串在字母表中应该排在字符串参数之后,则返回一个正数(大多数情况下是-1,具体的值同样要视实现而定)
    var stringValue=new String("yellow");
    alert(stringValue.localeCompare("brick"));//1
    alert(stringValue.localeCompare("yellow"));//0
    alert(stringValue.localeCompare("zoo"));//-1
    
    function determineOrder(value){
    	var result=stringValue.localeCompare(value);
    	if(result<0){
    		alert("The string 'yellow' comes before the string '"+value+"'.");
    	}else if(result>0){
    		alert("The string 'yellow' comes after the string '"+value+"'.");
    	}else{
    		alert("The string 'yellow' is equal to the string '"+value+"'.");
    	}
    }
    determineOrder("brick");
    determineOrder("yellow");
    determineOrder("zoo");
    

    (八).fromCharCode()方法

    1. String构造函数本身还有一个静态方法:fromCharCode()。这个方法的任务是接受一或多个字符编码,然后将它们转换成一个字符串
    2. 从本质上看,这个方法与实例方法charCodeAt()执行的是相反的操作
    alert(String.fromCharCode(104,101,,108,108,111));//"hello"
    //给fromCharCode()传递的是字符串"hello"中每个字母的字符编码
    

    (九).HTML方法

    1. 早期的Web浏览器提供商觉察到了使用JavaScript动态格式化HTML的需求。这些提供商就扩展了标准,实现了一些专门用于简化常见HTML格式化任务的方法
    2. 应该尽量不使用这些方法,因为它们创建的标记通常无法表达语义
    方法 输出结果
    anchor(name) <a name="name">string</a>
    big() <big>string</big>
    bold() <b>string</b>
    fixed() <tt>string</tt>
    fontcolor() <font color="color">string</font>
    fontsize() <font size="size">string</font>
    italics() <i>string</i>
    link(url) <a href="url">string</a>
    small() <small>string</small>
    strike() <strike>string</strike>
    sub() <sub>string</sub>
    sup() <sup>string</sup>

    源自
    源于整理《JavaScript高级程序设计》

    展开全文
  • string 在c++中的使用

    万次阅读 多人点赞 2018-08-11 20:44:31
    字符类型和字符数组( 字符值知识点)要提前了解一下,能更好的了解string   string类型支持长度可变的字符串 在头文件 #include&lt;string&gt;中   一:string对象的定义和初始化   string s1; ...

    字符类型和字符数组( 字符值知识点)要提前了解一下,能更好的了解string

     

    string类型支持长度可变的字符串  在头文件 #include<string>中

     

    :string对象的定义和初始化

        

    string s1;

    默认构造函数,s1位空串

    string s2(s1); 将s2初始化为s1的一个副本
    string s3("value"); 将s3初始化为一个字符串字面值副本
    string s4(n,'c') 将s4初始化为字符'c'的n个副本

    当没有明确指定对象初始华式时,系统使用默认构造函数

    #include<iostream>
    #include<string>
    using namespace std;
    int main()
    {
        string s1;
        s1="chenchen";
        cout<<s1<<endl;
    
        string s2(s1);
        cout<<s2<<endl;
    
        string s3("value");
        cout<<s3<<endl;
    
        string s4(10,'c');
        cout<<s4<<endl;
    
        return 0;
    }
    

     

    :string对象的读写

        对:cin>>s;//和scanf()类似

        从标准输入读取string,并将读入的串存储在s中。

     a.读取并忽略开头所有的空白字符(如空格,换行符,制表符,进纸符)

    b.读取字符直至再次遇到空白符,读取终止

    #include<iostream>
    #include<string>
    #include<cstdio>
    
    using namespace std;
    int main()
    {
        int T;
        cin>>T;
        //如果没有这个getchar()那么s首先会把我们按空格给s,这里我们要注意下
        //cin是不会这样的
        //同样的是gets()也会和getline()出现一样的情况
        /*
        比如输入:
        1 adfs
        输出:adfs有个空格
    
        输入
        1
        adfs
        输出:那么string参数被置为空string
        */
        getchar();
        while(T--)
        {
            string s;
            getline(cin,s);
            cout<<s<<endl;
        }
        return 0;
    }
    

     

    getline()了解一下,在字符串知识里有,上面有链接//换行符是丢弃的

     

     

     

    :string对象的操作

        

    s.empty() 如果s为空串,则返回true,否则返回false
    s.size() 返回s 中字符的字符个数
    s[n]

    返回s中位置为n的字符,位置从0开始计数

    s1+s2 把s1和s2链接成一个新的字符串,返回新生成的字符串
    s1=s2 把s1内容替换为s2的副本
    v1==v2 判断v1与v2的内容,相等则返回true,否则返回false
    !=, <, <=, >, >= 保持这些操作的惯有含义

    a. string::size_type 类型

     注意s.size()返回的类型是string::size_type()类型,而不是int形,string::size_type 的类型长度是int的俩倍所以尽量让s.size()的返 回值给string::size_type 类型

    因为string 的字符会很长,所以有了string::size_type 类型

    #include<iostream>
    #include<string>
    #include<cstdio>
    
    using namespace std;
    int main()
    {
        string s("value");
        string::size_type it;
        it=s.size();
        cout<<it<<endl;//5
        return 0;
    }
    

    b.和字符串字面值的连接问题

    #include<iostream>
    #include<string>
    #include<cstdio>
    
    using namespace std;
    int main()
    {
        string s1="hello";
        string s2=("world");
        string s3=s1+", ";//正确的
        cout<<s3<<endl;
    //    string s4="hello"+", ";//错误的
        string s5=s1+", "+", "+"world";//错误的
    //    string s6="hello"+", "+s2;//错误的
        cout<<s5<<endl;
        return 0;
    }
    

    s5的理解为:string t=s1+", "; s5=t+"world";

    注意俩个字符串字面值相加,是非法的

     

     

    c.下标操作可以作左值

    如:s[x]='*';

     

     

    :string对象中字符的处理

    这些函数都在cctype头文件中定义

     

    isalnum(c) 如果c是字母或数字,则为true
    isalpha(c) 如果c是字母,则为true
    isdigit(c) 如果c是数字,则为true
    islower(c) 如果c是小写字母,则为ture
    isupper(c) 如果c是大写字母,则为true
    isspace(c) 如果c是空白字符,则为true
    ispunct(c) 如果c是标点符号,则为true
    iscntrl(c) 如果c是控制字符,则为true
    isgraph(c) 如果c不是空格,但是可打印,则为true
    isprint(c) 如果c是可打印的字符,则为true
    isxdigit(c) 如果c是十六进制数,则为true
    tolower(c) 如果c是大写字母,则返回其小写字母形式,否则直接返回c
    toupper(c) 如果c是小写字母,则返回其大写字母形式,否则直接返回c

    表中大部分函数是测试一个给定的字符是否符合条件,并返回一个int值作为真值。如果失败,则函数返回0,否则返回一个(无意义的)非0值,表示被测字符符合条件

     

    注意:除了一些特殊操作,string类型提供与vector容器相同的操作。string类型和vector容器不同的是,它不支持以栈方式操纵容器:在string类型中不能使用front,back,pop_back操作

    string 是支持push_back()的,因为string也是顺序容器

     

     

    :string 的遍历

    #include<iostream>
    #include<string>
    #include<cstdio>
    
    using namespace std;
    int main()
    {
        string s("Hiya");
        string::iterator it;
        for(it=s.begin();it!=s.end();++it)
            cout<<*it<<endl;
        for(int i=0;s[i];i++)
            cout<<s[i]<<endl;
        cout<<s<<endl;
        return 0;
    }
    

    :构造string对象的其他方法

    写这个之前学个知识点:

    char s[]="abcd";  这个是字符串,以'\0'结束的,用strlen(s)是4,'\0'不计,但是它是有五个字符的
    char s1[]={'a','b','c','d'};  这个是字符数组,没有'\0',用strlen(s1)是不确定的,它有四个字符

     a.使用只有一个指针参数的构造函数,该指针指向空字符结束的字符数组中的第一个元素。//前面已经介绍了

    b.构造函数需要一个指向字符数组元素的指针和一个标记要复制多少字符的计数器做参数,由于该构造函数有一个计数器,因此  数组不必以空字符结束

     

     

    string s(cp,n) 创建一个string对象,它被初始化为cp所指向数组的前n个元素副本
    string s(s2,pos2)

    创建一个string对象,它被初始化为一个已存在的string对象s2中从下标pos2开始的字符的副本

    如果pos2>s.size(),则该操作未定义

    string s(s2,pos2,len2)

    创建一个string对象,它被初始化为s2中从下标pos2开始的len2个字符的副本

    如果pos2>s2.size(),则该操作未定义

    无论len2的值是多少,最多只能复制s2.size()-pos2个字符

    注意:n,len2和pos2都是unsinged

    #include<iostream>
    #include<string>
    #include<cstdio>
    
    using namespace std;
    int main()
    {
        char *cp="Hiya";
        char c_array[]="world!!!!";
        char no_null[] = {'H','i'};
        string s1(cp);
        cout<<"s1="<<s1<<endl;
        string s2(c_array,5);
        cout<<"s2="<<s2<<endl;
        string s3(c_array+5,4);
        cout<<"s3="<<s3<<endl;
        //string s4(no_null);//s4是错误的
        //cout<<s4<<endl;
        string s5(no_null,2);
        cout<<"s5="<<s5<<endl;
        string s6(s1,2);
        cout<<"s6="<<s6<<endl;
        string s7(s1,0,2);
        cout<<"s7="<<s7<<endl;
        string s8(s1,0,8);
        cout<<"s8="<<s8<<endl;
        return 0;
    }

     

    :修改string对象的其他方法

     

    与容器共有的string操作
    s.insert(p,t) 在迭代器p指向的元素之前插入一个值为t的新元素。返回指向新插入元素的迭代器
    s.insert(p,n,t) 在迭代器p指向的元素之前插入n个值为t的新元素。返回void
    s.insert(p,b,e) 在迭代器p指向的元素之前插入b和e标记范围内所有的元素,返回void
    s.assign(b,e) 用迭代器b和e标记范围内的元素替换s。对于string类型,该操作返回s,对于容器类型,则返回void
    s.assign(n,t) 用值为t的n个副本替换s。对于string类型,该操作返回s,对于容器类型,返回void
    s.erase(p) 删除迭代器p指向的元素,返回一个迭代器,指向被删除元素后面的元素
    s.erase(b,e) 删除迭代器b和e标记范围内所有的元素,返回一个迭代器,指向被删除元素段后面的第一个元素
    reverse(b,e) 把迭代器b和e标记范围内的所有元素反转

     

    #include<iostream>
    #include<string>
    #include<cstdio>
    #include<bits/stdc++.h>
    using namespace std;
    int main()
    {
        string s="12345abcde";
        string::iterator it;
        it=s.begin();
        s.insert(it+2,'s');
        cout<<"s="<<s<<endl;
        it=s.begin();
        s.insert(it+2,2,'t');
        cout<<s<<endl;
        it= s.begin();
        s.assign(it,it+3);
        cout<<s<<endl;
        s.assign(10,'c');
        cout<<s<<endl;
        string s1="sfdfsaf";
        s1.erase(s1.begin());
        cout<<s1<<endl;
        s1.erase(s1.begin(),s1.begin()+3);
        cout<<s1<<endl;
        reverse(s1.begin(),s1.end());
        cout<<s1<<endl;
        return 0;
    }

     

     

     

    string 类型特有的版本
    s.insert(pos,n,c) 在下表pos的元素之前插入n个字符c
    s.insert(pos,s2)

    在下标为pos的元素之前插入string对象s2的副本

    s.insert(pos,s2,pos2,len)

    在下标为pos的元素之前插入s2中从下标pos2开始len个字符

    s.insert(pos,cp,len) 在下标为pos的元素之前插入s2中从下标pos2开始的len个字符
    s.insert(pos,cp) 在下标为pos的元素之前插入cp所指向的以空字符结束的字符串副本
    s.assign(s2) 用s2的副本替换s
    s.assign(s2,pos2,len) 用s2中从下标pos2开始的len个字符副本替换s
    s.assign(cp,len) 用cp所指向数组的前len个字符副本替换s
    s.assign(cp) 用cp所指向的以空字符结束的字符串副本替换s

    s.erase(pos,len)

    删除从下标pos开始的len个字符

     

    #include<iostream>
    #include<string>
    #include<cstdio>
    #include<bits/stdc++.h>
    using namespace std;
    int main()
    {
        string s="12345abcde";
        s.insert(2,2,'s');
        cout<<s<<endl;
        string s2="zyz";
        s.insert(1,s2);
        cout<<s<<endl;
        s.insert(0,s2,0,2);
        cout<<s<<endl;
        char *cp="Statelu pou";
        s.insert(0,cp);
        cout<<s<<endl;
        s.insert(0,cp,2);
        cout<<s<<endl;
        string s3="123456abc";
        s.assign(s3);
        cout<<s<<endl;
        string s4="987";
        s.assign(s4,0,3);
        cout<<s<<endl;
        s.erase(1,6);
        cout<<s<<endl;
    
        return 0;
    }

    除非特殊声明,上述所有操作都返回s的引用

     

    其实string 的特有版本,就是多了pos下标的使用还有就是控制了一下,比较方便了

     

    :只适用于string类型的操作

    a.substr函数,返回当前string对象的子串

    b.append和replace函数,用于修改string对象

    c.一系列find函数,用于查找string对象

     

    子串操作
    s.substr(pos,n) 返回一个string类型的字符串,它包含s中从下标pos开始的n个字符
    s.substr(pos) 返回一个string类型的字符串,它包含从下标pos开始到s末为的所有字符
    s.substr() 返回s的副本

     

    #include<iostream>
    #include<string>
    #include<cstdio>
    #include<bits/stdc++.h>
    using namespace std;
    int main()
    {
        string s("hello world");
        string s2=s.substr(6,5);
        cout<<s2<<endl;
        string s3=s.substr(6);
        cout<<s3<<endl;
    
        return 0;
    }

     

     

    修改string对象的操作
    s.append(args) 将args串接在s后面。返回s的引用
    s.replace(pos,len,args)

    删除s中从下标pos开始的len个字符,用args指定的字符替换之,返回s的引用

    这个版本中,args不能为b2,e2

    s.replace(b,e,args)

    删除迭代器b和e标记的范围内所有的字符,用args代替之。返回s的引用

    这个版本中,args不能为 s1,pos2,len2

     

     

    append和replace操作的参数
    s2 string类型的字符串s2
    s2,pos1,pos2 字符串s2中从下标pos2开始的len2个字符
    cp 指针cp指向的以空字符结束的数组
    cp,len2

    cp指向的以空字符结束的数组中前len2个字符

    n,c 字符c的n个副本
    b2,e2 迭代器b2和e2标记的范围内所有字符

     

     

    #include<iostream>
    #include<string>
    #include<cstdio>
    #include<bits/stdc++.h>
    using namespace std;
    int main()
    {
        string s("C++ Prime");
        s.append(" 3rd Ed");
        cout<<s<<endl;
        s.insert(s.size(),"w");
        cout<<s<<endl;
        s.replace(10,3,"4th");
        cout<<s<<endl;
        s.erase(10,3);
        cout<<s<<endl;
        s.insert(10,"4th");
        cout<<s<<endl;
        return 0;
    }
    

     

     

     

    string类型的查找操作

    string类提供了6中查找函数,每种函数以不同形式的find命名。这些操作全都返回string::size_type类型的值,以下标形式标记查找所发生的位置;或者返回一个名为string::npos 的特殊值,说明没有找到匹配。string类将npos定义为保证大于任何有效下标的值

     

    string类型的查找操作
    s.find(args) 在s中查找args的第一次出现
    s.rfind(args) 在s中查找args的最后一次出现
    s.find_first_of(args) 在s中查args的任意字符的第一次出现
    s.find_last_of(args) 在s中查找args的任意字符的最后一次出现
    s.find_first_not_of(args) 在s中查找第一个不属于args的字符
    s.find_last_not_of(args) 在s中查找最后一个不属于args的字符
    string类型提供的find操作的参数
    c,pos 在s中,从下标pos标记的位置开始,查找字符c、pos的默认值是0
    s2,pos 在s中,从下标pos标记的位置开始,查找string对象s2,pos的默认值为0
    cp,pos 在s中从下标pos标记的位置开始,查找cp所指向的c风格的以空格结束的字符串。pos默认值为0
    cp,pos,n 在s中,从下标pos标记的位置开始,查找指针cp所指向数组的前n个字符,pos和n都没有默认值

     

    #include<iostream>
    #include<string>
    #include<cstdio>
    #include<bits/stdc++.h>
    using namespace std;
    int main()
    {
        //查找单个单词
        string ss="abcdefg";
        string::size_type pos=ss.find('c',0);
        cout<<pos<<endl;
        cout<<ss[pos]<<endl;
    
    
    
    
        //如果找不到就是npos
        //精确匹配的查找
        string name("AnnaBelle");
        string::size_type pos1=name.find("Anna");
        cout<<pos1<<endl;//子串Anna在name中的下标是0
    
        string s("annaBelle");
        pos1=s.find("Anna");//pos1=npos
        //cout<<pos1<<endl;
    
    
    
    
        //查找任意字符
        string s2("0123456789");
        string s3("r2d2");
    //    string::size_type pos=s3.find_first_of(s2);
    //    cout<<s3[pos]<<endl;//2
    //    cout<<pos<<endl;//1
    
    
    
    
    
    
        //指定查找的起点
        string::size_type pos2=0;
        while((pos2=s3.find_first_of(s2,pos2))!=string::npos)
        {
            cout<<"pos2="<<pos2<<endl;
            cout<<s3[pos2]<<endl;
            pos2++;//pos2值必须加1,以确保下一次循环从刚找到的数字后面开始查找下一个数字
        }
    
    
        //寻找不匹配点
        string nums("0123456789");
        string depet("03714p3");
        string::size_type pos3=depet.find_first_not_of(nums);
        cout<<"pos3="<<pos3<<endl;
        cout<<depet[pos3]<<endl;
    
        //反向查找
        string river("Mississippi");
        string::size_type first=river.find("is");
        string::size_type last=river.rfind("is");
        cout<<first<<"    "<<river[first]<<endl;
        cout<<last<<"    "<<river[last]<<endl;
    
        return 0;
    }

     

    九:string对象的比较

     

    string类型的compare操作
    s.compare(s2) 比较s和s2
    s.compare(pos1,n1,s2)

    让s中从pos下标位置开始的n1个字符与s2做比较

    s.compare(pos1,n1,s2,pos2,n2) 让s中从pos1下标位置开始的n1个字符与s2中从pos2下标位置开始的n2个字符做比较
    s.compare(cp) 比较s和cp所指向的以空字符结束的字符串
    s.compare(pos1,n1,cp) 让s从pos1下标位置开始的n1个字符与cp所指向的字符串做比较
    s.compare(pos1,n1,cp,n2)

    让s中从pos1下标位置开始的n1个字符与cp所指向字符串的前n2个字符做比较

    比如:s1.compare(args);

    a.正数,此时s1大于args所代表的string对象

    b.负数,此时s1小于args所代表的string对象

    c.0,此时s1恰好等于args所代表的string对象

     

    这次举个例子以前做的题

    #include<bits/stdc++.h>
    using namespace std;
    int main()
    {
        int n,q;
        scanf ("%d%d", &n,&q);
        string s;
        cin>>s;
        for ( int i=0; i<q;i++ )
        {
            int a,b,c,d;
            scanf ( "%d%d%d%d" ,&a,&b ,&c , &d );
            if ( s.compare( a-1,b-a+1,s,c-1,d-c+1)==0 )
                printf ( "YES\n" );
            else
                printf ( "NO\n" );
        }
     
        return 0;
    }
    
    

     

    展开全文
  • 深入理解Java String

    万次阅读 多人点赞 2019-09-11 10:43:47
    在Java语言了中,所有类似“ABC”的字面值,都是String类的实例;String类位于java.lang包下,是Java语言的核心类,提供了字符串的比较、查找、截取、大小写转换等操作;Java语言为“+”连接符(字符串连接符)以及...

    在Java语言中,所有类似“ABC”的字面值,都是String类的实例;String类位于java.lang包下,是Java语言的核心类,提供了字符串的比较、查找、截取、大小写转换等操作;Java语言为“+”连接符(字符串连接符)以及对象转换为字符串提供了特殊的支持,字符串对象可以使用“+”连接其他对象。String类的部分源码如下

    public final class String
        implements java.io.Serializable, Comparable<String>, CharSequence {
        /** The value is used for character storage. */
        private final char value[];
    
        /** Cache the hash code for the string */
        private int hash; // Default to 0
        ...
    }
    

    从上面可以看出
    1)String类被final关键字修饰,意味着String类不能被继承,并且它的成员方法都默认为final方法;字符串一旦创建就不能再修改。
    2)String类实现了Serializable、CharSequence、 Comparable接口。
    3)String实例的值是通过字符数组实现字符串存储的。


    1. “+”连接符

    1.1 “+”连接符的实现原理

    Java语言为“+”连接符以及对象转换为字符串提供了特殊的支持,字符串对象可以使用“+”连接其他对象。其中字符串连接是通过 StringBuilder(或 StringBuffer)类及其append 方法实现的,对象转换为字符串是通过 toString 方法实现的,该方法由 Object 类定义,并可被 Java 中的所有类继承。有关字符连接和转换的更多信息,可以参阅 Gosling、Joy 和 Steele 合著的 《The Java Language Specification》

    我们可以通过反编译验证一下

    /**
     * 测试代码
     */
    public class Test {
        public static void main(String[] args) {
            int i = 10;
            String s = "abc";
            System.out.println(s + i);
        }
    }
    
    /**
     * 反编译后
     */
    public class Test {
        public static void main(String args[]) {    //删除了默认构造函数和字节码
            byte byte0 = 10;      
            String s = "abc";      
            System.out.println((new StringBuilder()).append(s).append(byte0).toString());
        }
    }
    

    由上可以看出,Java中使用"+"连接字符串对象时,会创建一个StringBuilder()对象,并调用append()方法将数据拼接,最后调用toString()方法返回拼接好的字符串。由于append()方法的各种重载形式会调用String.valueOf方法,所以我们可以认为:

    //以下两者是等价的
    s = i + ""
    s = String.valueOf(i);
     
    //以下两者也是等价的
    s = "abc" + i;
    s = new StringBuilder("abc").append(i).toString();
    

    1.2 “+”连接符的效率

    使用“+”连接符时,JVM会隐式创建StringBuilder对象,这种方式在大部分情况下并不会造成效率的损失,不过在进行大量循环拼接字符串时则需要注意。

    String s = "abc";
    for (int i=0; i<10000; i++) {
        s += "abc";
    }
    
    /**
     * 反编译后
     */
    String s = "abc";
    for(int i = 0; i < 1000; i++) {
         s = (new StringBuilder()).append(s).append("abc").toString();    
    }
    

    这样由于大量StringBuilder创建在堆内存中,肯定会造成效率的损失,所以在这种情况下建议在循环体外创建一个StringBuilder对象调用append()方法手动拼接(如上面例子如果使用手动拼接运行时间将缩小到1/200左右)。

    /**
     * 循环中使用StringBuilder代替“+”连接符
     */
    StringBuilder sb = new StringBuilder("abc");
    for (int i = 0; i < 1000; i++) {
        sb.append("abc");
    }
    sb.toString();
    

    与此之外还有一种特殊情况,也就是当"+"两端均为编译期确定的字符串常量时,编译器会进行相应的优化,直接将两个字符串常量拼接好,例如:

    System.out.println("Hello" + "World");
    
    /**
     * 反编译后
     */
    System.out.println("HelloWorld");
    
    /**
     * 编译期确定
     * 对于final修饰的变量,它在编译时被解析为常量值的一个本地拷贝存储到自己的常量池中或嵌入到它的字节码流中。
     * 所以此时的"a" + s1和"a" + "b"效果是一样的。故结果为true。
     */
    String s0 = "ab"; 
    final String s1 = "b"; 
    String s2 = "a" + s1;  
    System.out.println((s0 == s2)); //result = true
    
    /**
     * 编译期无法确定
     * 这里面虽然将s1用final修饰了,但是由于其赋值是通过方法调用返回的,那么它的值只能在运行期间确定
     * 因此s0和s2指向的不是同一个对象,故上面程序的结果为false。
     */
    String s0 = "ab"; 
    final String s1 = getS1(); 
    String s2 = "a" + s1; 
    System.out.println((s0 == s2)); //result = false 
     
    public String getS1() {  
        return "b";   
    }
    

    综上,“+”连接符对于直接相加的字符串常量效率很高,因为在编译期间便确定了它的值,也就是说形如"I"+“love”+“java”; 的字符串相加,在编译期间便被优化成了"Ilovejava"。对于间接相加(即包含字符串引用,且编译期无法确定值的),形如s1+s2+s3; 效率要比直接相加低,因为在编译器不会对引用变量进行优化。

    2. 字符串常量池

    在Java的内存分配中,总共3种常量池,分别是Class常量池运行时常量池字符串常量池

    字符串的分配和其他对象分配一样,是需要消耗高昂的时间和空间的,而且字符串使用的非常多。JVM为了提高性能和减少内存的开销,在实例化字符串的时候进行了一些优化:使用字符串常量池。每当创建字符串常量时,JVM会首先检查字符串常量池,如果该字符串已经存在常量池中,那么就直接返回常量池中的实例引用。如果字符串不存在常量池中,就会实例化该字符串并且将其放到常量池中。由于String字符串的不可变性,常量池中一定不存在两个相同的字符串

    /**
     * 字符串常量池中的字符串只存在一份!
     * 运行结果为true
     */
    String s1 = "hello world!";
    String s2 = "hello world!";
    System.out.println(s1 == s2);
    

    2.1 内存区域

    在HotSpot VM中字符串常量池是通过一个StringTable类实现的,它是一个Hash表,默认值大小长度是1009;这个StringTable在每个HotSpot VM的实例中只有一份,被所有的类共享;字符串常量由一个一个字符组成,放在了StringTable上。要注意的是,如果放进String Pool的String非常多,就会造成Hash冲突严重,从而导致链表会很长,而链表长了后直接会造成的影响就是当调用String.intern时性能会大幅下降(因为要一个一个找)。

    在JDK6及之前版本,字符串常量池是放在Perm Gen区(也就是方法区)中的,StringTable的长度是固定的1009;在JDK7版本中,字符串常量池被移到了堆中,StringTable的长度可以通过**-XX:StringTableSize=66666**参数指定。至于JDK7为什么把常量池移动到堆上实现,原因可能是由于方法区的内存空间太小且不方便扩展,而堆的内存空间比较大且扩展方便。

    2.2 存放的内容

    在JDK6及之前版本中,String Pool里放的都是字符串常量;在JDK7.0中,由于String.intern()发生了改变,因此String Pool中也可以存放放于堆内的字符串对象的引用。

    /**
     * 运行结果为true false
     */
    String s1 = "AB";
    String s2 = "AB";
    String s3 = new String("AB");
    System.out.println(s1 == s2);
    System.out.println(s1 == s3);
    

    由于常量池中不存在两个相同的对象,所以s1和s2都是指向JVM字符串常量池中的"AB"对象。new关键字一定会产生一个对象,并且这个对象存储在堆中。所以String s3 = new String(“AB”);产生了两个对象:保存在栈中的s3和保存堆中的String对象。
    这里写图片描述

    当执行String s1 = "AB"时,JVM首先会去字符串常量池中检查是否存在"AB"对象,如果不存在,则在字符串常量池中创建"AB"对象,并将"AB"对象的地址返回给s1;如果存在,则不创建任何对象,直接将字符串常量池中"AB"对象的地址返回给s1。

    3. intern方法

    直接使用双引号声明出来的String对象会直接存储在字符串常量池中,如果不是用双引号声明的String对象,可以使用String提供的intern方法。intern 方法是一个native方法,intern方法会从字符串常量池中查询当前字符串是否存在,如果存在,就直接返回当前字符串;如果不存在就会将当前字符串放入常量池中,之后再返回。

    JDK1.7的改动:

    1. 将String常量池 从 Perm 区移动到了 Java Heap区
    2. String.intern() 方法时,如果存在堆中的对象,会直接保存对象的引用,而不会重新创建对象。
    /**
     * Returns a canonical representation for the string object.
     * <p>
     * A pool of strings, initially empty, is maintained privately by the
     * class {@code String}.
     * <p>
     * When the intern method is invoked, if the pool already contains a
     * string equal to this {@code String} object as determined by
     * the {@link #equals(Object)} method, then the string from the pool is
     * returned. Otherwise, this {@code String} object is added to the
     * pool and a reference to this {@code String} object is returned.
     * <p>
     * It follows that for any two strings {@code s} and {@code t},
     * {@code s.intern() == t.intern()} is {@code true}
     * if and only if {@code s.equals(t)} is {@code true}.
     * <p>
     * All literal strings and string-valued constant expressions are
     * interned. String literals are defined in section 3.10.5 of the
     * <cite>The Java&trade; Language Specification</cite>.
     *
     * @return  a string that has the same contents as this string, but is
     *          guaranteed to be from a pool of unique strings.
     */
    public native String intern();
    

    3.1 intern的用法

    static final int MAX = 1000 * 10000;
    static final String[] arr = new String[MAX];
    
    public static void main(String[] args) throws Exception {
        Integer[] DB_DATA = new Integer[10];
        Random random = new Random(10 * 10000);
        for (int i = 0; i < DB_DATA.length; i++) {
            DB_DATA[i] = random.nextInt();
        }
        long t = System.currentTimeMillis();
        for (int i = 0; i < MAX; i++) {
            //arr[i] = new String(String.valueOf(DB_DATA[i % DB_DATA.length]));
             arr[i] = new String(String.valueOf(DB_DATA[i % DB_DATA.length])).intern();
        }
    
        System.out.println((System.currentTimeMillis() - t) + "ms");
        System.gc();
    }
    

    运行的参数是:-Xmx2g -Xms2g -Xmn1500M 上述代码是一个演示代码,其中有两条语句不一样,一条是未使用 intern,一条是使用 intern。结果如下图

    未使用intern,耗时826ms:
    这里写图片描述
    使用intern,耗时2160ms:
    这里写图片描述
    通过上述结果,我们发现不使用 intern 的代码生成了1000w 个字符串,占用了大约640m 空间。 使用了 intern 的代码生成了1345个字符串,占用总空间 133k 左右。其实通过观察程序中只是用到了10个字符串,所以准确计算后应该是正好相差100w 倍。虽然例子有些极端,但确实能准确反应出 intern 使用后产生的巨大空间节省。

    细心的同学会发现使用了 intern 方法后时间上有了一些增长。这是因为程序中每次都是用了 new String 后,然后又进行 intern 操作的耗时时间,这一点如果在内存空间充足的情况下确实是无法避免的,但我们平时使用时,内存空间肯定不是无限大的,不使用 intern 占用空间导致 jvm 垃圾回收的时间是要远远大于这点时间的。 毕竟这里使用了1000w次intern 才多出来1秒钟多的时间。

    4. String、StringBuilder和StringBuffer

    4.1 继承结构

    这里写图片描述

    4.2 主要区别

    1)String是不可变字符序列,StringBuilder和StringBuffer是可变字符序列。
    2)执行速度StringBuilder > StringBuffer > String。
    3)StringBuilder是非线程安全的,StringBuffer是线程安全的。

    5. 总结

    String类是我们使用频率最高的类之一,也是面试官经常考察的题目,下面是一个小测验。

    public static void main(String[] args) {
        String s1 = "AB";
        String s2 = new String("AB");
        String s3 = "A";
        String s4 = "B";
        String s5 = "A" + "B";
        String s6 = s3 + s4;
        System.out.println(s1 == s2);
        System.out.println(s1 == s5);
        System.out.println(s1 == s6);
        System.out.println(s1 == s6.intern());
        System.out.println(s2 == s2.intern());
    }
    

    运行结果:
    这里写图片描述

    解析:真正理解此题目需要清楚以下三点
    1)直接使用双引号声明出来的String对象会直接存储在常量池中;
    2)String对象的intern方法会得到字符串对象在常量池中对应的引用,如果常量池中没有对应的字符串,则该字符串将被添加到常量池中,然后返回常量池中字符串的引用;
    3) 字符串的+操作其本质是创建了StringBuilder对象进行append操作,然后将拼接后的StringBuilder对象用toString方法处理成String对象,这一点可以用javap -c命令获得class文件对应的JVM字节码指令就可以看出来。
    这里写图片描述

    参考文献
    https://docs.oracle.com/javase/8/docs/api/
    https://blog.csdn.net/sinat_19425927/article/details/38663461
    https://www.cnblogs.com/xiaoxi/p/6036701.html
    https://tech.meituan.com/in_depth_understanding_string_intern.html

    展开全文
  • String用法详解

    万次阅读 多人点赞 2018-04-05 16:15:51
    string类声明string类本不是STL的容器,但是它与STL容器有着很多相似的操作,因此,把string放在这里一起进行介绍。 之所以抛弃char*的字符串而选用C++标准程序库中的string类,是因为他和前者比较起来,不必担心...

    string类

    声明

    string类本不是STL的容器,但是它与STL容器有着很多相似的操作,因此,把string放在这里一起进行介绍。 
    之所以抛弃char*的字符串而选用C++标准程序库中的string类,是因为他和前者比较起来,不必担心内存是否足够、字符串长度等等,而且作为一个类出现,他集成的操作函数足以完成我们大多数情况下的需要。我们尽可以把它看成是C++的基本数据类型。 
    首先,为了在我们的程序中使用string类型,我们必须包含头文件。如下:

    #include  <string>  // 注意这里不是string.h,string.h是C字符串头文件

    1、声明一个C++字符串

    声明一个字符串变量很简单: string str; 
    这样我们就声明了一个字符串变量,但既然是一个类,就有构造函数和析构函数。上面的声明没有传入参数,所以就直接使用了string的默认的构造函数,这个函数所作的就是把str初始化为一个空字符串。string类的构造函数和析构函数如下:

    1)  string s;  // 生成一个空字符串s 
    2)  string s(str) ; // 拷贝构造函数生成str的复制品 
    3)  string s(str, stridx);  // 将字符串str内"始于位置stridx"的部分当作字符串的初值 
    4)  string s(str, stridx, strlen) ; // 将字符串str内"始于stridx且长度顶多strlen"的部分作为字符串的初值 
    5)  string s(cstr) ;  // 将C字符串(以NULL结束)作为s的初值 
    6)  string s(chars, chars_len) ;  // 将C字符串前chars_len个字符作为字符串s的初值。 
    7)  string s(num, ‘c’) ;  // 生成一个字符串,包含num个c字符 
    8)  string s(“value”);  string s=“value”;  // 将s初始化为一个字符串字面值副本
    9)  string s(begin, end);  // 以区间begin/end(不包含end)内的字符作为字符串s的初值 
    10) s.~string();  //销毁所有字符,释放内存 

    2、string与C字符数组的比较

    string串要取得其中某一个字符,和传统的C字符串一样,可以用s[i]的方式取得。比较不一样的是如果s有三个字符,传统C的字符串的s[3]是’\0’字符,但是C++的string则是只到s[2]这个字符而已。

    1、C风格字符串

    • 用”“括起来的字符串常量,C++中的字符串常量由编译器在末尾添加一个空字符;
    • 末尾添加了‘\0’的字符数组,C风格字符串的末尾必须有一个’\0’。

    2、C字符数组及其与string串的区别

    • char ch[ ]={‘C’, ‘+’, ‘+’}; //末尾无NULL
    • char ch[ ]={‘C’, ‘+’, ‘+’, ‘\0’}; //末尾显式添加NULL
    • char ch[ ]=”C++”; //末尾自动添加NULL字符 若[ ]内数字大于实际字符数,将实际字符存入数组,其余位置全部为’\0’。 
      这里写图片描述

    3、string对象的操作

    string s;
    1)  s.empty();  // s为空串 返回true
    2)  s.size();  // 返回s中字符个数 类型应为:string::size_type
    3)  s[n];  //0开始相当于下标访问
    4)  s1+s2;  // 把s1和s2连接成新串 返回新串 
    5)  s1=s2;  // 把s1替换为s2的副本
    6)  v1==v2;  // 比较,相等返回true
    7)  `!=, <, <=, >, >=`  惯有操作 任何一个大写字母都小于任意的小写字母

    当进行string对象和字符串字面值混合连接操作时,+操作符的左右操作数必须至少有一个是string类型的:

    string s1(“hello”);
    string s3=s1+”world”;  //合法操作
    string s4=”hello”+”world”;  //非法操作:两个字符串字面值相加

    4、字符串操作函数

    1、string类函数

    1) =, s.assign() // 赋以新值 
    2) swap() // 交换两个字符串的内容 
    3) +=, s.append(), s.push_back() // 在尾部添加字符 
    4) s.insert() // 插入字符 
    5) s.erase() // 删除字符 
    6) s.clear() // 删除全部字符 
    7) s.replace() // 替换字符 
    8) + // 串联字符串 
    9) ==,!=,<,<=,>,>=,compare() // 比较字符串 
    10) size(),length() // 返回字符数量 
    11) max_size() // 返回字符的可能最大个数 
    12) s.empty() // 判断字符串是否为空 
    13) s.capacity() // 返回重新分配之前的字符容量 
    14) reserve() // 保留一定量内存以容纳一定数量的字符 
    15) [ ], at() // 存取单一字符 
    16) >>,getline() // 从stream读取某值 
    17) << // 将谋值写入stream 
    18) copy() // 将某值赋值为一个C_string 
    19) c_str() // 返回一个指向正规C字符串(C_string)的指针 内容与本string串相同 有’\0’ 
    20) data() // 将内容以字符数组形式返回 无’\0’ 
    21) s.substr() // 返回某个子字符串 
    22) begin() end() // 提供类似STL的迭代器支持 
    23) rbegin() rend() // 逆向迭代器 
    24) get_allocator() // 返回配置器

    2、函数说明

    1、s.assign();

    s.assign(str); // 不说 
    s.assign(str,1,3); // 如果str是"iamangel" 就是把"ama"赋给字符串 
    s.assign(str,2,string::npos); // 把字符串str从索引值2开始到结尾赋给s 
    s.assign("gaint"); // 不说 
    s.assign("nico",5); // 把’n’ ‘I’ ‘c’ ‘o’ ‘\0’赋给字符串 
    s.assign(5,'x'); // 把五个x赋给字符串

    2、大小和容量函数

    一个C++字符串存在三种大小: 
    1) 现有的字符数,函数是s.size()和s.length(),他们等效。s.empty()用来检查字符串是否为空。 
    2) max_size(); 这个大小是指当前C++字符串最多能包含的字符数,很可能和机器本身的限制或者字符串所在位置连续内存的大小有关系。 
    3) capacity()重新分配内存之前string所能包含的最大字符数。 
    这里另一个需要指出的是reserve()函数,这个函数为string重新分配内存。重新分配的大小由其参数决定,默认参数为0,这时候会对string进行非强制性缩减。

    3、元素存取

    我们可以使用下标操作符[]和函数at()对元素包含的字符进行访问。但是应该注意的是操作符[]并不检查索引是否有效(有效索引0~str.length()),如果索引失效,会引起未定义的行为。而at()会检查,如果使用at()的时候索引无效,会抛出out_of_range异常。 
    有一个例外不得不说,const string a;的操作符[]对索引值是a.length()仍然有效,其返回值是’\0’。其他的各种情况,a.length()索引都是无效的。

    4、比较函数

    C ++字符串支持常见的比较操作符(>,>=,<,<=,==,!=),甚至支持string与C-string的比较(如 str<”hello”)。在使用>,>=,<,<=这些操作符的时候是根据”当前字符特性”将字符按字典顺序进行逐一的比较。字典排序靠前的字符小,比较的顺序是从前向后比较,遇到不相等的字符就按这个位置上的两个字符的比较结果确定两个字符串的大小。 
    另一个功能强大的比较函数是成员函数compare()。他支持多参数处理,支持用索引值和长度定位子串来进行比较。他返回一个整数来表示比较结果,返回值意义如下:0-相等 、>0-大于、<0-小于。

    5、插入字符

    也许你需要在string中间的某个位置插入字符串,这时候你可以用insert()函数,这个函数需要你指定一个安插位置的索引,被插入的字符串将放在这个索引的后面。 
    s.insert(0,”my name”); 
    s.insert(1,str); 
    这种形式的insert()函数不支持传入单个字符,这时的单个字符必须写成字符串形式。为了插入单个字符,insert()函数提供了两个对插入单个字符操作的重载函数: 
    insert(size_type index, size_type num, chart c)和insert(iterator pos, size_type num, chart c)。 
    其中size_type是无符号整数,iterator是char*,所以,你这么调用insert函数是不行的: 
    insert(0, 1, ‘j’);这时候第一个参数将转换成哪一个呢? 
    所以你必须这么写:insert((string::size_type)0, 1, ‘j’)! 
    第二种形式指出了使用迭代器安插字符的形式。

    6、提取子串s.substr()

    s.substr(); // 返回s的全部内容 
    s.substr(11); // 从索引11往后的子串 
    s.substr(5,6); // 从索引5开始6个字符

    5、字符串流stringstream操作

    Iostream标准库支持内存中的输入输出,只要将流与存储在程序内存中的string对象捆绑起来即可。此时,可使用iostream输入和输出操作符读写这个stream对象。使用stringstream,我们必须包含头文件#include。

    1、string s

    1)  >>操作符 // 用于从istream对象中读入输入
    2)  is >> s;  // 从输入流is中读取一个以空白字符分割的字符串,写入s
    3)  <<操作符 // 用于把输出写到ostream对象中
    4)  os << s; // 将s写到输出流os中
    5)  getline(is, s);  // 从输入流is中读取一行字符,写入s,直到遇到分行符或到了文件尾
    6)  istream // 输入流 提供输入操作
    7)  ostream // 输出流 提供输出操作

    2、stringstream特定的操作

    1)  stringstream strm; // 创建自由的stringstream对象
    2)  stringstream strm(s); // 创建存储s的副本的stringstream对象,s是stringstream类型
    3)  strm.str(); // 返回strm中存储的string类型对象
    4)  strm.str(s); // 将string类型的s复制给strm 返回void

    3、string到int的转换

    stringstream通常是用来做数据转换的,如果你打算在多次转换中使用同一个stringstream对象,记住在每次转换前要使用clear()方法。在多次转换中重复使用同一个stringstream(而不是每次都创建一个新的对象)对象最大的好处在于效率。stringstream对象的构造和析构函数通常是非常耗费CPU时间的。 
    string到int的转换(与其他类型间的转换一样大同小异):

    string result=”10000”;  
    int n=0;
    stream<<result;
    stream>>n;  // n等于10000

    6、C字符串、string串、stringstream之间的关系

    首先必须了解,string可以被看成是以字符为元素的一种容器。字符构成序列(字符串)。有时候在字符序列中进行遍历,标准的string类提供了STL容器接口。具有一些成员函数比如begin()、end(),迭代器可以根据他们进行定位。注意,与char*不同的是,string不一定以NULL(‘\0’)结束。string长度可以根据length()得到,string可以根据下标访问。所以,不能将string直接赋值给char*。

    1、string转换成const char *

    如果要将字面值string直接转换成const char *类型。string有2个函数可以运用:一个是.c_str(),一个是data成员函数。 
    c_str()函数返回一个指向正规C字符串的指针,内容与本string串相同。这是为了与C语言兼容,在C语言中没有string类型,故必须通过string类对象的成员函数c_str()把string 对象转换成C中的字符串样式。注意:一定要使用strcpy()函数等来操作方法c_str()返回的指针

    string str = "Hello World";
    const char *ch1 = str.c_str();
    const char *ch2 = str.data();

    此时,ch1与ch2的内容将都是”Hello World”。但是只能转换成const char*,如果去掉const编译不能通过。

    2、string转换成char *

    C++提供的由C++字符串得到对应的C_string的方法是使用data()、c_str()和copy(),其中 
    1) data()以字符数组的形式返回字符串内容,但并不添加’\0’。 
    2) c_str()返回一个以’\0’结尾的字符数组,返回值是const char*。 
    3) copy()则把字符串的内容复制或写入既有的c_string或字符数组内。 
    C++字符串并不以’\0’结尾。我的建议是在程序中能使用C++字符串就使用,除非万不得已不选用c_string。 
    如果要转换成char*,可以用string的一个成员函数strcpy实现。

    string str = "Hello World";
    int len = str.length();
    char *data = new char[len+1];  //这里+1还是不+1需要注意
    strcpy(data, str.c_str());  // const char *data = new char[len+1];  strcpy(data, str);

    此时,data中的内容为”Hello World”使用c_str()要么str赋给一个const指针,要么用strcpy()复制。

    3、char *转换成string

    string类型能够自动将C风格的字符串转换成string对象:

    string str; 
    const char *pc = "Hello World"; 
    str = pc;
    printf(“%s\n”, str);  //此处出现错误的输出
    cout<<str<<endl;

    不过这个是会出现问题的。有一种情况我要说明一下。当我们定义了一个string类型之后,用printf(“%s”,str);输出是会出问题的。这是因为“%s”要求后面的对象的首地址。但是string不是这样的一个类型。所以肯定出错。 
    用cout输出是没有问题的,若一定要printf输出。那么可以这样:

    printf("%s",str.c_str());

    4、char[ ] 转换成string

    这个与char*的情况相同,也可以直接赋值,但是也会出现上面的问题,需要同样的处理。 
    - 字符数组转化成string类型:

    char ch [] = "ABCDEFG";
    string str(ch); //也可string str = ch;

    或者

    char ch [] = "ABCDEFG";
    string str;
    str = ch; //在原有基础上添加可以用str += ch;

    5、string转换成char[ ]

    string对象转换成C风格的字符串:

    const char *str = s.c_str();

    这是因为为了防止字符数组被程序直接处理c_str()返回了一个指向常量数组的指针。 
    由于我们知道string的长度可以根据length()函数得到,又可以根据下标直接访问,所以用一个循环就可以赋值了,这样的转换不可以直接赋值。

    string str = "Hello World";
    int len=str.length();
    char ch[255]={};
    for( int i=0;i<str.length();i++)
    ch[i] = str[i];
    ch[len+1] = '\0';
    printf("%s\n", ch);
    cout<<ch<<endl;

    6、stringstream与string间的绑定

    stringstream strm;
    string s;
    strm<<s;  // 将s写入到strm
    strm>>s;  // 从strm读取串写入s
    strm.str(); // 返回strm中存储的string类型对象
    strm.str(s); // 将string类型的s复制给strm 返回void
    char* cstr;  // 将C字符数组转换成流
    string str(cstr);
    stringstream ss(str);
    展开全文
  • 深入理解Java中的String(大坑)

    万次阅读 多人点赞 2019-03-07 11:49:07
    String源码分析 Srtring在JVM层解析 String典型案例 String被设计成不可变和不能被继承的原因 JVM相关知识 下面这张图是JVM的体系结构图: 下面我们了解下Java栈、Java堆、方法区和常量池: Java栈...
  • String

    万次阅读 多人点赞 2018-06-14 12:29:22
    构造方法: * public String():空构造 * public String(byte[] bytes):把字节数组转成字符串 * public String(byte[] bytes,int index,int length):把字节数组的一部分转成字符串 * public String(char[] ...
  • C++中的string类用法简介

    万次阅读 多人点赞 2019-08-30 15:20:35
    本文主要介绍C++中的string类的常见用法。 1. 概述 string是C++标准库的一个重要的部分,主要用于字符串处理。可以使用输入输出流方式直接进行string操作,也可以通过文件等手段进行string操作。同时,C++的算法库...
  • 浅谈String str = "" 和 new String()的区别

    万次阅读 多人点赞 2018-09-20 15:44:52
    关于String类的知识经常出现在面试题中,在此先记录自己的理解。 首先明白一个事,java存在一个常量池,可以用来存储字符串常量。 1 创建的字符串变量在内存中的区别 两者看似都是创建了一个字符串对象,但在内存...
  • C++的string学习总结

    千次阅读 2018-11-13 08:44:49
    2.string类常用接口总结a.string类对象的常见构造函数b.string类对象常用的容量操作c.string类对象的访问操作d.string类对象常见的修改操作 一.标准库的string类 1.string类是什么? string是表示字符串的字符...
  • 1 String转换为int类型的方法

    万次阅读 2018-03-02 11:17:53
    Object obj = getObject();if(obj instanceof Integer) int value = ... 1 String转换为int类型的方法: 2 1. Integer.parseInt([String]) 3 2.Integer.valueOf([String]).intValue(); 4 3.Integer.decode([S...
  • C++ string的用法和例子

    万次阅读 多人点赞 2018-03-25 20:10:35
    同时C++的算法库对string也有着很好的支持,而且string还和c语言的字符串之间有着良好的接口。虽然也有一些弊端,但是瑕不掩瑜。 其中使用的代码多数都是来自cpp官网,因为例子非常全。 声明和初始化方法: 想...
  • String类的20种常见方法

    万次阅读 多人点赞 2017-02-05 16:32:46
    String类里面常用的20个方法 和长度有关的方法返回类型 方法名 作用 int length() 得到一个字符串的字符个数(一个中文是一个字符,一个英文是一个字符,一个转义字符是一个字符) 和数组有关的方法返回类型 方法...
  • String和List<String>间的相互转换

    万次阅读 2018-06-06 15:13:08
    public void test() { //字符串转list&lt;String&gt; String str = "asdfghjkl"; List&...String&... lis = Arrays.asList(str.split("... for (String string : lis) { ...
  • int与String互相转换

    万次阅读 2018-11-09 21:54:02
    一、String转为int int i=Integer.parseInt(string); int i=Integer.valueOf(s).intValue(); 二、int转为String String s = String.valueOf(i); String s = Integer.toString(i); String s = “” + i; ...
  • string 数组怎么定义

    万次阅读 2018-04-13 10:52:19
    string数组的定义有三种: String arr[] = new String[10]; //创建一个长度为10的String 类型数组。 String arr[] = {"张三","李四"}; String[] arr = new String[10];
  • golang 中string和int类型相互转换

    万次阅读 多人点赞 2018-03-14 10:26:56
    总结了golang中字符串...string转成int: int, err := strconv.Atoi(string) string转成int64: int64, err := strconv.ParseInt(string, 10, 64) int转成stringstring := strconv.Itoa(int) int64转成string
  • Java中byte怎么转化为String

    万次阅读 2018-03-15 17:50:26
    string转化为byte[]数组String str = "abcd"; byte[] bs = str.getBytes();byte[]数组转化为string字符串/*String str1 = "abcd"; byte[] bs1 = str1.getBytes();*/ byte[] bs1 = {97,98,100}; ...
  • go string []byte相互转换

    万次阅读 2017-08-01 14:45:01
    string 不能直接和byte数组转换 string可以和byte的切片转换 1,string 转为[]byte var str string = "test" var data []byte = []byte(str)   2,byte转为string var data [10]byte  byte...
  • String类型转换BigDecimal类型

    万次阅读 2018-08-12 16:38:34
    public static void main(String[] args) { String str1="2.30"; BigDecimal bd=new BigDecimal(str1); System.out.println(bd); }  
  • java将double型数据转化为String类型

    万次阅读 2020-01-05 12:10:32
    运用String.valueOf(double d)方法和运用语句String string = “” + d可以将double数据转化为String类型
1 2 3 4 5 ... 20
收藏数 7,686,339
精华内容 3,074,535
关键字:

string