C++使用字符串之二(string,数值转换,原始字符串字面量)

C++提供了一个更好的string类,并且作为标准库的一部分提供了这个字符串的实现。在C++中,std::string是一个类(实际上是basic_string模板类的一个实例),这个类支持<cstring>中提供的大部分功能,还能自动管理内存分配。string类在std名称空间的<string>头文件中定义。

1. C风格的字符串的优势和劣势

优势是:1)底层使用了基本的字符类型和数组结构

      2)量级小,如果用的好,只会占用所需的内存

      3)可以按照操作原始内存的方式操作和复制字符串

劣势是:1)很难找到bug在哪,信不信由你

      2)没有利用C++面向对象的特性

      3)程序员需要明白底层的表示方式,有很多是你不愿意去明白的


2.使用string类

要明白string是一个类,不过你也可以把它看做是基本类型,像int,实际上它不是基本类型。它用起来很简单,看例子就知道了:

string A("12");

string B("34");

string C;

C=A+B;

如果使用C风格就比较麻烦了:

char* str1="12";

char* str2="34";

char* str3=new char[strlen(str1)+strlen(str2)+1];

strcpy(str3,str1);

strcat(str3,str2);

C风格字符串的另一个问题是不能通过==运算符进行比较。假设有一下两个字符串:

char* a="12";

char b[]="12";

if(a==b){.......};

if的判断语句始终返回false,因为它比较的是指针的值,而不是字符串的内容。注意C数组和指针是相关的。可以把C数组看成是指向数组中第一个元素的指针。要比较C字符串,需要这样写代码:if(strcmp(a,b)==0){......}; 此外C字符串也无法通过<,>,<=,>=进行比较,因此都需要strcmp()根据字符的字典顺序返回-1、0和1的值进行判断。但是在C++的string,这些符号都被重载了,随便用,这些运算符可以操作真正的字符串字符。单独的字符可以通过运算符operator[]访问。说到底就是一句话,好使。

看代码:

string myString="Hello";

myString +=",there";

string myOtherString=myString;

if(myString == myOtherString)

{

myOtherString[0]='H';

}

cout<<myString<<endl;

cout<<myOtherString<<endl;

输出是:hello,there

      Hello,there

在这个例子中,要注意即使字符串被分配和调整大小,也不会出现内存泄漏的情况。所有这些string对象都创建为堆栈变量。尽管string类肯定需要完成大量分配内存和调整大小的操作,但是string的析构函数会在string对象离开作用域时清理内存。

可以运用string的c_str()方法获得一个表示C风格字符串的const字符指针。不过一旦string执行了任何内存重分配或string对象被销毁了,这个返回的const指针就失效了。

因此永远不要返回在基于堆栈的string上调用c_str()的结果

源代码中的字符串字面量通常解释为const char*。使用用户定义的标准字面量"s"可以把字符串字面量解释为std::string,例如

auto string1="Hello world";

auto string2="Hello world"s;


3. 数值转换

std名称空间包含很多辅助函数,以便完成数值和字符串之间的转换。下面的函数可以用于将数值转换为字符串:

string to_string(int val);(括号里面放各种基本类型,例如double,long等)

例如:long double d=3.14L;

     string to_string(d);

通过下面这组在std名称空间中定义的函数可以将string转换为数值。在这些函数圆形中,str表示要转换的string,idx是一个指针,这个指针会接受第一个未转换的字符的索引,base表示转换过程中使用的进制。idx可以是空指针,如果是空指针则被忽略。如果不能执行任何转换,函数会抛出invalid_argument异常,如果转换的值超出了返回类型的范围,则抛出out_of_range异常。

int stoi(const string& str,size_t* idx=0,int base=10);

long stol(const string& str,size_t* idx=0,int base=10);

unsigned long stoul(const sting& str, size_t* idx=0,int base=10);

//就是说string to double的缩写 stod,第一个参数是待转换的string,第二个参数是

将接受第一个未转换的字符的索引,base表示几进制。

4.原始字符串字面量

原始字符串字面量是可以横跨多行代码的字符串字面量,不需要转义嵌入的双引号,像\t和\n这种转义序列不按照转义序列的方式处理,而是按照普通的文本的方式进行处理。

例子:

string str="Hello, "World!""; //报错,应该都看得懂

必须使用转义字符:

string str="Hello, \"World\"";

但是对于原始字符串字面量来说:

string str = R"(Hello "World"!)";

原始字符串字面量可以跨越多行,会忽略转义符号,把它当做普通的字符处理。

string str="Line 1

Line 2 with \t"; //错的

使用原始字符串字面量时就可以:

string str=R"(Line 1

Line 2 with \t)";

会输出:Line 1

       Line 2 with \t

但是如果原始字符里面包含)"时,这个方法就不好使了,这时候就得使用扩展的原始字符串字面量语法。

R"d-char-sequence(r-char-sequence)d-char-sequence)";

r-char-sequenece是原始的字符串,d-char-sequence是可选的分隔符序列。原始字符串首尾的分隔符序列应该一致。分隔符序列最多只能有16个字符。应该选择未出现在原始字符串字面量中的序列作为分割符序列。

string str=R"-(The characters )" are embedded in this string)-";

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值