学习心得——字符串

        字符串在编程中出现的特别频繁,学好C++必须要会用字符串。

        C++非常灵活,它对字符串的处理有多种方式,这里列举使用的最多的两种:字符串(string)和C风格字符串(C-Style character String)。前者是C++语言中常用的处理方式,后者是C语言中常用的处理方式,为了与C兼容,C++也支持后者。

        字符串(string):我们常说的字符串,有时候指的是字符串类型(string type),有时候指的是字符串变量(string variable)。

        字符串字面值(string literal):字符串字面值就是指一串字符了,如"hello",在C++语言中,使用双引号来表示引号内部的内容是字符串常量,对于字符串字面值,末尾有结束标志'\0'。

        字符字面值(character literal):字符字面值指的是单个字符,如'c',在C++语言中,使用单引号来表示引号内部的内容是字符字面值。对于字符字面值,常用char类型保存,保存的是它的ASCII码。

 

一、字符串

        字符串是C++提供的一种新的数据类型,C语言中没有它。字符串是一种非常好的数据类型,它封装了字符串结构以及很多字符串的操作,使用起来非常方便。

        字符串是C++标准库(STL)中声明的一个模板类,它不是C++语言的内置类型(built-in type),但是我们完全可以和使用内置类型一样来使用它。

        要使用字符串,我们必须引入头文件。我们使用如下两条语句:

#include<string>
using namespace std;//这句也可以换成using std::string。
          请注意:这两条语句是C++标准的写法,是包含了std的C++头文件,它对应的是新的string类。其它的写法都不是真正意义上的C++标准写法,具体原因会在后面阐述。

        在引入头文件以后,我们就可以很方便的使用string类型以及它的操作了。我们可以像定义整型变量一样定义字符串变量。例如string str;。

        下面讲述字符串的操作。

        1、字符串变量的初始化。

         前面已经说过,字符串类型是一个类模板,所以它有构造函数。它提供了几种构造函数。

         string str1;                        //这种定义方式调用默认的构造函数,str1是一个空字符串,如果用cout输出,可以看到屏幕上为空。

         string str2(str1);              //这种定义方式将str2初始化为str1的副本,调用的是复制构造函数。

         string str3("hello");          //这种定义方式将str3初始化为一个字符串常量(string literal)。

         string str4(n,'c');              //这种定义方式将str4初始化为n个字符c的复制。

        2、字符串变量的赋值

        字符串的赋值方式用多种。

        我们可以用字符串字面值来赋值,如string str1; str1="hello";。

        我们可以用字符指针来赋值,如char *p="hello"; str1=p; 这样str1保存的也是hello。

        我们可以用字符数组来赋值,如char q[]="hello"; str1=q;这样str1保存的还是hello。

        这些赋值方式经常使用,可以看到可以很容易的从字符指针或者字符数组转成字符串。

        3、字符串变量的输入和输出

        其输入和输出很简单,和内置类型一样。

        4、字符串变量的操作

        (1)字符串长度。C++提供了两个函数来获取字符串的长度。一个是size()函数,一个是length()函数。这两个函数都是返回字符串的长度,且返回值均为size_type(这个类型其实就是unsigned int/long以保证足够大),它们的功能是一样的。

        那么C++为什么要提供这两个函数?

        因为C++是兼容C的,为了照顾一些人的习惯,所以就有了length()函数。也就是说length()函数是C风格的,它反映了字符串的顺序属性。

        C++有一些东西是没有的,比如说容器(container)。相比于数组,C++更希望程序员使用容器。字符串可以作为STL容器,所以按照惯例给出了size()函数。

        刚才已经讲过,字符串字面值在其结尾有一个字符串结束标识,那么使用长度函数返回的到底是什么呢?

        返回的是字符串中字符的个数,不包括字符串结束标志。而且,当我们将字符串字面值存放到字符串变量中时,只存放字符串本身,而不保存字符串结束标志\0'。当然,我们使用string的时候,我们不需要去关心字符串结束标志。在string中,字符串不是以字符串结束标志作为结尾的,通常string中每增加一个字符,它的长度就增加1,所以完全没有必要保存'\0'。

        (2)字符串的复制、连接、比较

        对于string对象,我们可以使用赋值形式,也就是使用“=”来完成复制功能,使用大于号小于号完成比较功能,使用“+”完成连接功能,这是因为在string的类模板中,已经重载了这些运算符,所以使用起来很方便。

        (3)获得单个字符

        字符串本质上仍然是一个字符数组,所以我们可以使用下标运算符(subscript)"[]"来获得字符串中某一位字符。  

        

        我们可以看出,字符串使用起来是极为方便的,程序员完全可以把它当成一种内置类型来使用,同时它还提供了众多的函数,使得我们可以直接调用,节省很多时间。推荐使用string类型来操作字符串。

 

二、C风格字符串

        我们之前讲过字符串字面值,字符串字面值是由单个字符字面值组成的,所以我们可以将字符串字面值看成是字符字面值的数组。我们把它抽象成一种类型,这种类型就叫C风格字符串,定义是:有终结符的字符数组(Character Array)。这样,字符串字面值就是C风格字符串的一个实例。

        1、定义、赋值、输入和输出

        对于C风格字符串,有两种方式来定义,分别是使用字符数组和使用字符指针。

char cstr1[]={'c','+','+'};       //不是
char cstr2[]={'c','+','+','\0'}; //是
char cstr3[]="hello";             //是
char *cstr4=cstr1;                //不是
char *cstr5=cstr2;                //是
char *cstr6="hello";             //是

          在上面的代码中,cstr1字符数组使用字符字面值来初始化,不包含'\0',所以它不是C风格字符串。cstr2显式的包含了'\0',cstr3使用字符串字面值来初始化,隐式的包含了'\0'。cstr4指向cstr1,所以也不是C风格字符串。cstr5指向cstr2,由于cstr2是C风格字符串,所以它也是。

        最后一种方式,定义了字符指针,使用字符串字面值对其初始化。初始化的过程就是将字符串字面值的第一个元素的地址赋给字符指针。这种用法是C语言中处理字符串最常用的方法。

        我们知道数组名代表了数组第一个元素的地址,例如上述代码中cstr3就代表了其保存的字符串常量"hello"中第一个字母h的地址,如果我们用cout<<&cstr3;语句,我们可以得到h。如果我们用cout<<cstr3;呢,会出现什么结果?结果是输出字符串"hello"。这是由于在ostream中对<<进行了重载。对于C风格字符串,如果输出字符数组名时,会输出第一个元素,接着输出第二个元素,直到遇到'\0'。cstr1中不含'\0',如果我们尝试输出cstr1,会产生意想不到的结果。

        cstr6和数组名很像,都保存了数组第一个元素的地址。我们可以使用cout<<cstr6输出整个字符数组。

        2、C风格字符串的操作。

       我们需要包含头文件,因为对C风格字符串进行操作的函数定义在头文件中。之所以没有像字符串一样一开始就引入,是因为定义C风格字符串完全不需要这个头文件,定义时用到的是C++语言的内置类型。

#include<cstring>
using namespace std;

           同样,这里也是C++标准写法。
           对C风格字符串的操作与string差不多,需要注意的是string是类,string变量是它的对象,所以我们使用成员运算符(.)来访问各个函数,而C风格字符串不同,它的函数是直接调用的,而不是类的成员函数。

        (1)求长度。使用strlen(cstr6),返回的是字符串中字符的个数,'\0'是字符串结束标志,不作为字符串的字符,所以返回的长度要比实际长度少1。

        (2)比较函数。strcmp(cstr5,cstr6)。从左往右一个一个字符的比较,比较的是它们的ASCII码。如果cstr5大,那么返回正值,如果相等,返回0,如果cstr5小,返回负值。

        (3)复制函数。strcpy(cstr5,cstr6)。将cstr6内容赋给cstr5。

        (4)连接函数。strcpy(cstr5,cstr6)。将cstr6内容连接在cstr5后。

        还有一些函数就不在这里一一列举了。

        使用C风格字符串需要谨记:字符串尾部有一个字符串结束标志。

 

三、比较

        无论是字符串string,还是C风格字符串,它们都是字符数组,它们在内存中以数组的形式存放,我们可以使用下标运算符访问它们的某一元素。

        它们都能够比较方便的操作字符串,都可以处理变长的字符串,都能获得字符串的长度,对字符串进行操作。

        它们之间有些区别,可以说C++提供的string是对C风格字符串的继承和扩展。string将字符串完全封装起来了,提供了一个新的类型,用对象进行操作,显然,它比C风格字符串用指针操作更好。这种封装隐藏了很多细节,我们不必在意字符串结尾是否有字符串结束标志(实际上用string时是没有的,前面已经说过了),也不用担心函数的调用会造成内存错误(C中的strcpy,strcat)。

        总之,使用string类型处理字符串是一个良好的编程习惯,它能避免很多不必要的BUG产生。

 

四、string   cstring   string.h

        前面我们提到了头文件的引用,这里有必要讲一下。

        C++含有众多的头文件,为了兼容C,它保留了C的头文件,同时它自己也新增了很多头文件,比如iostream.h等。在新标准的C++中,保留了原来头文件的写法,同时引入了不带h后缀的头文件,比如以前用的iostream.h现在有对应的iostream,这些不带h后缀的头文件仍然是头文件,它们相比于带h后缀的头文件,做了一些修改,并将一些东西放入std,所以我们在C++程序经常使用命名空间。也就是说iostream是iostream.h的升级版。而原来C的头文件则在它的文件名前加上前缀c以表示它是C语言的,例如cstdio,cstring,cmath等。

        但是string.h文件是特例。因为string.h本身是C语言库里面的头文件,这样一来,C++引入的string类的名无法命名为string.h,它的名字被C抢占了,汗!由于C使用广泛,所以不可能要求C将string.h改名。那C++引入的string类最早叫什么呢?我也不知道。新标准后,string就表示C++引入的string类,还好这个名字没有被C占用。这样C的string.h怎么办?前面说了,要在它的名字前面加c,就变成了cstring。

         所以,结果是,在C++头文件中,存在这三个文件,cstring,string.h和string,没有cstring.h。

         cstring其实就是string.h的升级版,是string.h的std版;

         string.h还是C中的string.h,没有变;

         string就是C++新引入的string类头文件,至于它的非std版,即它的原版,不知道是什么。

 

The End

 

参考:http://gjunwei.blog.sohu.com/43310610.html

            http://topic.csdn.net/t/20040111/09/2653513.html

            http://topic.csdn.net/u/20091107/22/fb5800fb-4dd6-4bca-b989-99d1c72d9fb6.html

            http://www.examda.com/ncre2/cpp/fudao/20090508/082131342.html

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值