C++学习笔记(二)C风格字符串和string类区别和联系

来源:互联网 发布:上海威纳贸易数据 编辑:程序博客网 时间:2024/06/04 18:44

一、概述

有时候在使用字符串时,总把C++的字符串类型和C风格的字符串混淆,或者独立为不同概念,为此特定查找资料,总结两者之间的区别和联系。如有错误,恳请指出。

二、C语言中的字符串

在C语言中,对字符串的处理主要是使用字符数组(以空字符’\0’为结尾)或者是指向字符类型的指针,即用char*,但指针在实现字符串类型是较为麻烦的。用法如下:

//example 1char str[15]="Hello world!"; //使用字符数组, 也可以char str[] ="Hello world!";  *(str+2)=’L’;   //使用*()指定数组修改位置改变第3个字母char *p= str;    //使用指针p指向数组str的首地址*(p+2)=’L’;    //仍可间接修改数组str的第3个字母char *ptr ="Hello world!";  //使用指针指向一行字符串;*(ptr+2)='L';             //错误,编译虽通过,但无法改变字符串的第3个字母

这是因为第一个字符串是由数组str开辟的,数组的每个值是可以改变的变量,而第二个指针ptr指向的是字符串常量,而字符串常量是无法改变的,故为了避免误判,指向字符串常量时应该使用const指针。

const char *ptr ="Hello world!"

//example 2char *ptr = new char[15];   //由new在堆中开辟的15个char型空间,ptr指向该空间首地址ptr = "abcdefg";           //错误,不可再用ptr指向另一行字符串首地址ptr[0]='A';                //可由ptr[下标]或*(ptr+索引)写或读数据,用后者指针的形式速度较快*ptr ='a';                 //可改变ptr[0]的值
由于是堆分配的内存,故函数调用结束后,不会自行撤销,故需要在函数加入delete []ptr;语句。


三、C++中的字符串

   由于C风格字符串较为复杂,不适合大程序的开发,故C++标准库定义了string类,头文件形式为#include <string>,而头文件<string.h>和<cstring>都是错误的,这两个头文件主要定义处理C风格字符串的一些方法,譬如strlen(), strcpy()等。第一个为C的头文件格式,第 2个为C++的C风格头文件。

    先看sting类的原形:

//example 3class String{public:String(const char *str = NULL);// 普通构造函数String(const String &other); //拷贝构造函数~ String(void); //析构函数String & operator =(const String &other);//赋值函数private:char *m_data;// 用于保存字符串};//普通构造函数String::String(const char *str){if(str==NULL){m_data = new char[1]; // 对空字符串自动申请存放结束标志'\0'的//加分点:对m_data加NULL 判断*m_data = '\0';}else{int length = strlen(str);m_data = new char[length+1]; // 若能加 NULL 判断则更好strcpy(m_data, str);}}// String的析构函数String::~String(void){delete[] m_data; // 或delete m_data;}//拷贝构造函数String::String(const String &other) // 输入参数为const型{int length = strlen(other.m_data);m_data = new char[length+1]; //对m_data加NULL 判断strcpy(m_data, other.m_data);}//赋值函数String & String::operator =(const String &other) // 输入参数为const型{if(this == &other) //检查自赋值return *this;delete[] m_data; //释放原有的内存资源int length = strlen( other.m_data );m_data = new char[length+1]; //对m_data加NULL 判断strcpy( m_data, other.m_data );return *this; //返回本对象的引用}

可看成string类含有一个私有的指针char* m_data,由构造函数和拷贝构造函数用new开辟空间,并用strcpy复制传进来的字符串(C风格或string类对象),由析构函数释放内存。

(1)string类的构造函数和析构函数如下:

a) strings;  //生成一个空字符串s

b) strings(str) //拷贝构造函数 生成str的复制品,str为string类的对象

c) strings(str,stridx) //将字符串str内“始于位置stridx”的部分当作字符串的初值

d) strings(str,stridx,strlen) //将字符串str内“始于stridx且长度顶多strlen”的部分作为字符串的初值

e) strings(cstr) //将C风格字符串作为s的初值

f)string s(chars,chars_len) //将C风格字符串前chars_len个字符作为字符串s的初值。

g) strings(num,c) //生成一个字符串,包含num个c字符,c是字符型

h) strings(beg,end) //以区间beg;end(不包含end)内的字符作为字符串s的初值

i) s.~string()//销毁所有字符,释放内存

 

(2)字符串操作函数

a)=,assign()   //赋以新值

b)swap()   //交换两个字符串的内容

c)+=,append(),push_back() //在尾部添加字符

d)insert() //插入字符

e)erase() //删除字符

f)clear() //删除全部字符

g)replace() //替换字符

h)+ //串联字符串

i)==,!=,<,<=,>,>=,compare()  //比较字符串

j)size(),length()  //返回字符数量

k)max_size() //返回字符的可能最大个数

l)empty()  //判断字符串是否为空

m)capacity() //返回重新分配之前的字符容量

n)reserve() //保留一定量内存以容纳一定数量的字符

o)[ ], at() //存取单一字符

p)>>,getline() //从stream读取某值

q)<<  //将谋值写入stream

r)copy() //将某值赋值为一个C_string

s)c_str() //将内容以C_string返回

t)data() //将内容以字符数组形式返回

u)substr() //返回某个子字符串

v)查找函数

w)begin()end() //提供类似STL的迭代器支持

x)rbegin() rend() //逆向迭代器

y)get_allocator() //返回配置器

   这些成员函数给string字符串的操作带来了极大的方便。

(3)元素读写

//example 4string str("abcdefg");     //调用构造函数初始化strstr[0] = 'A';             //使用下标访问,可访问可修改str.at(0)='A';            //使用成员函数at()可访问可修改

但是注意使用下标一旦越界则不报任何异常,而使用at()则会报异常,当由str.length()函数得到字符串长度(不包含空字符),即可使用for遍历数组,另一种方法是使用迭代器

//example 5string s = "abcdefg";for(string::iterator iter = s.begin(); iter!=s.end(); iter++)    //向前遍历{cout<<*iter<<endl;}for(string::reverse_iterator iter = s.rbegin(); iter!=s.rend(); iter++)    //向后遍历{cout<<*iter<<endl;}

string类提供了向前和向后遍历的迭代器iterator,迭代器提供了访问各个字符的语法,类似于指针操作,迭代器不检查范围。

string::iteratorstring::const_iterator声明迭代器变量,const_iterator不允许改变迭代的内容。常用迭代器函数有:

const_iterator begin()const;

iteratorbegin();               //返回string的起始位置

const_iterator end()const;

iteratorend();                   //返回string的最后一个字符后面的位置

const_iterator rbegin()const;

iteratorrbegin();               //返回string的最后一个字符的位置

const_iterator rend()const;

iteratorrend();                   //返回string第一个字符位置的前面rbeginrend用于从后向前的迭代访问,通过设置迭代器string::reverse_iterator,string::const_reverse_iterator实现

四、C风格字符串和string类的转换

    C++提供的由C++字符串得到对应的C风格字符串的方法是使用data()、c_str()和copy(),C风格字符串转为string则用构造函数即可。

//example 6string var = "abcdefg";const char *p = var.c_str();    //不加const则不正确,p所指向的字符是不可改变的string str = "abcdefg";char p[10];strcpy(p,str.c_str());p[0] ='A';                  //因为p为长度10数组,故p所指向的值可改变char *p = new char[str.length()+1];strcpy(p ,str.data());delete []p;                  //使用data()函数char  p[10];str.copy(p,7);p[str.length()+1]='\0';         //使用copy函数


data()以字符数组的形式返回字符串内容,但并不添加’\0’。c_str()返回一个以‘\0’结尾的字符数组,而copy()则把字符串的内容复制或写入既有的c_string或字符数组内。






0 0