【string总汇】一个string类的简单实现案例&c语言string类函数实现汇总
目录
6、C字符串、string串、stringstream之间的关系
string类
声明
string类本不是STL的容器,但是它与STL容器有着很多相似的操作,因此,把string放在这里一起进行介绍。
之所以抛弃char*的字符串而选用C++标准程序库中的string类,是因为他和前者比较起来,不必担心内存是否足够、字符串长度等等,而且作为一个类出现,他集成的操作函数足以完成我们大多数情况下的需要。我们尽可以把它看成是C++的基本数据类型。
首先,为了在我们的程序中使用string类型,我们必须包含头文件。如下:
#include <string> // 注意这里不是string.h,string.h是C字符串头文件
string 用法
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赋给字符串
5、大小和容量函数
一个C++字符串存在三种大小:
1) 现有的字符数,函数是s.size()和s.length(),他们等效。s.empty()用来检查字符串是否为空。
2) max_size(); 这个大小是指当前C++字符串最多能包含的字符数,很可能和机器本身的限制或者字符串所在位置连续内存的大小有关系。
3) capacity()重新分配内存之前string所能包含的最大字符数。
这里另一个需要指出的是reserve()函数,这个函数为string重新分配内存。重新分配的大小由其参数决定,默认参数为0,这时候会对string进行非强制性缩减。
6、元素存取
我们可以使用下标操作符[]和函数at()对元素包含的字符进行访问。但是应该注意的是操作符[]并不检查索引是否有效(有效索引0~str.length()),如果索引失效,会引起未定义的行为。而at()会检查,如果使用at()的时候索引无效,会抛出out_of_range异常。
有一个例外不得不说,const string a;的操作符[]对索引值是a.length()仍然有效,其返回值是’\0’。其他的各种情况,a.length()索引都是无效的。
7、比较函数
C ++字符串支持常见的比较操作符(>,>=,<,<=,==,!=),甚至支持string与C-string的比较(如 str<”hello”)。在使用>,>=,<,<=这些操作符的时候是根据”当前字符特性”将字符按字典顺序进行逐一的比较。字典排序靠前的字符小,比较的顺序是从前向后比较,遇到不相等的字符就按这个位置上的两个字符的比较结果确定两个字符串的大小。
另一个功能强大的比较函数是成员函数compare()。他支持多参数处理,支持用索引值和长度定位子串来进行比较。他返回一个整数来表示比较结果,返回值意义如下:0-相等 、>0-大于、<0-小于。
8、插入字符
也许你需要在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’)!
第二种形式指出了使用迭代器安插字符的形式。
9、提取子串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);
原文链接:https://blog.csdn.net/manonghouyiming/article/details/79827040
int转stirng和int转string
【C/C++】数值转换成字符串|字符串转换成数值_bandaoyu的笔记-CSDN博客_数值转换字符串
string 实现
https://www.cnblogs.com/nanqiang/p/9937175.html
class String
{
public:
String(const char* str = NULL);// 普通构造函数
String(const String& str); // 拷贝构造函数
~String(void); // 析构函数
String& operator = (const String& str);// 赋值函数
private:
char* m_data;// 用于保存字符串
int length;
};
String::String(const char* str)
{
if (NULL == str)
{
m_data = new char[1];// 得分点:对空字符串自动申请存放结束标志'\0'的,加分点:对m_data加NULL判断
m_data[0] = '\0';
length = 0;
}
else
{
length = strlen(str);
m_data = new char[length + 1];// 若能加 NULL 判断则更好
memcpy(m_data, str, length);
m_data[length] = '\0';
}
}
String::String(const String& str)// 得分点:输入参数为const型
{
length = str.length;
m_data = new char[length + 1]; // 若能加 NULL 判断则更好
memcpy(m_data,str.m_data,length);
m_data[length] = '\0';
}
// String的析构函数
String::~String(void)
{
length = 0;
delete[] m_data;
}
//赋值函数
String& String::operator = (const String& str) 得分点:输入参数为const型
{
if (this == &str) //得分点:检查自赋值
return *this;
if(m_data)
delete[] m_data; //得分点:释放原有的内存资源
length = str.length;
m_data = new char[length + 1];//加分点:对m_data加NULL判断
strcpy(m_data, str.m_data);
m_data[length] = '\0';
return *this;//得分点:返回本对象的引用
}
//------------------------------------------------------------------------------------------------------------------------------------2020.03.23
带有不错的讲解:C++中String类的实现 - 止战 - 博客园
string类中使用到了赋值构造函数、复制构造函数、构造函数、默认构造函数、析构函数、重载操作符等一些类操作
class String
{
public:
String()
{
data = new char[1]; //这里为什么使用new char[1]呢,虽然是一个字符,这是为了和析构函数保持对称,因为在别的构造函数中使用的char[]
data[0]='\0';
length = 0;
}
String(const char* str)
{
length = strlen(str);
data = new char[length+1];
strcpy(data,str);
data[length]='\0';
}
String(const char* str,int n)
{
length = n;
data = new char[n+1];
strncpy(data,str,n);
data[length] ='\0';
}
String(const String& src) //拷贝构造函数 也就是复制构造函数
{
length = src.length;
data = new char[length+1];
strcpy(data,src.data);
}
String& operator=(const String& src) //赋值构造函数
{
if(this == &src)
return *this;
delete [] data;
data = new char[src.length+1];
strcpy(data,src.data);
return *this;
}
String& operator=(const char* src) //另一种的赋值构造函数
{
delete [] data;
length = strlen(src);
data = new char[length+1];
strcpy(data,src);
return *this;
}
char& operator[](int n)
{
return data[n];
}
const char& operator[](int n) const //对于const成员函数 最好就是返回const的引用,这样是为了避免返回值被修改
{
return data[n];
}
friend ostream& operator<<(ostream& os,const String& st);
~String()
{
delete [] data;
}
private:
char* data;
int length;
};
ostream& operator<<(ostream& os,const String& st)
{
os<<st.data;
return os;
}
以上这篇一个string类的简单实现案例就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持脚本之家。
看到很多地方都面试或者考试都要涉及字符串的很多知识 有的需要自己写字符串 最近看书的收集了一些 算是摘抄 然后在其中加了点我自己的感受 嘿嘿
strcpy 函数 ,作用是将一个字符串的字符复制到另一个字符串中
char * strcpy(char *destination ,const char * source)
{
while(*destination++=*source++);//看这一句话写的,精炼间断而又让人一目了然
//我用while写肯定是要三条语句,循环变量,赋值,递增,唉。。。这就是菜鸟啊
return(destination-1);
}
strcat函数,作用是将一个串的内容追加到另一个串上
char *strcat(char *target,const char * source)
{
char *original=target;
while(*target)//这里可以看出指针和数组下标的不同,一直都觉得指针式很有优势的
target++;
while(*target++=*source++);
return(original);//注意到与上面一个函数返回的不同
}
strncat函数,这个不常用,作用是给字符串追加了N个字符
char *strcat(char *destination ,const char * source,int n)
{
char *original=destination;
int i=0;
while(*destination )
destination ++;
while((i++<n)&&(*destination ++=*source++));//我忍不住再一次赞叹一下这个循环语句
//这个容错性的想到也很牛,只要n为负数,就将目标字符串改为空
if(i>n)
*destination=NULL;
return(original);
}
strlwr 和 strupr函数 这两个函数实现起来比较简单,就不列了 :)
str_index函数 作用是返回索引到串的首次出现
int str_index(const char*string, char letter)
{
char *original=string;
while((*string!=letter)&&(*string))
string++;
return(string-original);//这个返回方法,没有一定功力估计很难想出来,至少脑子里不会首先会想到这样写
}
strrchr函数 也是不常用的函数 作用是搜索字符在字符串中的末次出现
char *strrchr(const char *string, char letter)
{
char *ptr=NULL;
while(*string)//这个逻辑在很多地方都有用
{
if(*string==letter)
ptr=string;
string++;
}
return (ptr);
}
strchr函数 作用是获取字符串中第一次出现某个字符
char *strchr(const char *string, char letter)
{
while((*string!=letter)&&(*string))
string++;
return (string);
}
strr_index函数 作用是返回指向字符串末次出现的索引
int strr_index(const char *string,char letter)
{
char *original=string;
char *ptr=NULL;
while(*string)
{
if(*string==letter)
ptr=string;
string++
}
return((*ptr)?ptr-original:string-original);//要么返回末次出现的索引,要么返回字符串的长度
}
charcnt函数 作用是计算字符串中字符出现的次数
int charcnt(const char *string,char letter)
{
int count=0;
while(*string)
if(*string==letter)
count++;
return(count);
}
strrev函数 作用是将字符串内容反转
char *strrev(char *string)
{
char *original=string;
char *forward=string;
char tmp;
while(*string)
string++;
while(forward<string)//逻辑和交换两个数差不多
{
temp=*(--string);
*string=*forward;
*forward++=tmp;
}
return(original);
}
strset函数 作用是将某特定字符赋给字符串 相当于用某一个字符重置字符串 不是很难的函数 :)
strcmp函数 作用是比较两个字符串 相同返回0,第一个大返回-1 ,第二个大返回1
int strcmp(const char *s1, const char *s2)
{
while((*s1==*s2)&&(*s1))//这个比较的方式很简练吧,也很有逻辑
{
s1++;
s2++;
}
if((*s1==*s2)&&(!*s1))
return(0);
else if((*s1)&&(!*s2))
return(-1);
else if((!*s1)&&(*s2))
return(1);
else
return((*s1>*s2)?-1:1);
}
strncmp函数 作用是比较两个字符串的前N个字符 实现和上面的函数很类似 只是要添加一个控制变量控制下长度 : )
strdup函数 作用是复制字符串的内容
strdup(const char *s1)
{
char *ptr;
if((ptr=malloc(strlen(s1)+1)))
strcpy(ptr,s1);
return(ptr);
}
strspn函数 作用是从给定字符序列中查找字符的首次出现
size_t strspn(const char *s1, const char *s2)//这个函数我看了很久才明白是什么意思,比如第一个参数传abcDef,第二个传cbA,
//按照顺序查找第一个字符串,可以找到第一个没有在第二个字符串中出现的字符是'D'
//返回这个字符在第一个字符串中的索引,也就是3,另外,为什么不用int而用size_t做
//返回值,是因为site_t是unsigned int,也就是正数
{
int i,j;
for(i=0;*s1;i++,s1++)
{
for(j=0; s2[j]; j++)
if(*s1==s2[j])
break;
if(s2[j]==NULL)
break;
}
return(i);
}
strstr函数 作用是在字符串中查找子字符串 虽然返回值是char* 但是这个函数应该在判断有没有找到子字符串情况下用的多些
char * strstr(const char *s1,const char *s2)
{
int i,j,k;
for(i=0; s1[i]; i++)
for(j=i,k=0; s1[j]==s2[k]; j++,k++)
if(!s2[k+1])
return(s1+i)
return(NULL);
}
strstr_cnt函数 作用是计算字符串出现的次数 实现差不多是strstr 和cnt的组合 : )
substring_index函数 作用是给子字符串获取索引 只要将strstr的返回值改成i就可以了 : )
r_strstr函数 作用是获取子字符串最右端出现 和strstr差不多 然后参照一般的查找最右端的函数 : )
strstr_rem函数 作用是从字符串中删除子字符串
char * strstr_rem(char *string, char *substring)//我没有仔细看这个函数,我有点懒,嘿嘿,但是按照上面的strstr在找到字符串后进行
//进行替换,具体过程没看 列出来 可以学习
{
int i,j,k,loc=-1;
for(i=0; string[i]&&(loc==-1); i++)
for(j=i,k=0; string[j]==substring[k]; j++,k++)
if(!substring[k+1])
loc=i;
if(loc!=-1)
{
for(k=0; substr[k];k++);
for(j=loc;i=loc+k,string[i]; j++, i++)
string[j]=string[i];
string[i]=NULL;
}
return(string)
}
strstr_rep函数 作用是用另一个字符串代替子字符串
char *strstr_rep(char *source, char *old , char *new)
{
char *original=source;
char temp[256];
int old_length=strlen(old);
int i,j,k,location=-1;
for(i=0; source[i]&&(location==-1); i++)
for(j=i,k=0; source[j]==old [k]; j++,k++)
if(!old [k+1])
location=i;
if(location!=-1)
{
for(j=0;j<location;j++)
temp[j]=source[j];
for(i=0;new[i];i++,j++)
temp[j]=new[i];
for(k=location+old_length;source[k];k++,j++)
temp[j]=source[k];
temp[j]=NULL;
for(i=0; source[i]=temp[i];i++);
}
return(original);
}
string append方法的常用用法
C++ string append()添加文本
使用append()添加文本常用方法:
直接添加另一个完整的字符串:
如str1.append(str2);
添加另一个字符串的某一段子串:
如str1.append(str2, 11, 7);
添加几个相同的字符:
如str1.append(5, '.');
注意,个数在前字符在后.上面的代码意思为在str1后面添加5个".".
//========================================
#include<iostream>
using namespace std;
//========================================
int main()
{
string str1="I like C++";
string str2=",I like the world.";
string str3="Hello";
string str4("Hi");
//====================================
str1.append(str2);
str3.append(str2, 11, 7);
str4.append(5, '.');
//====================================
cout<<str1<<endl;
cout<<str3<<endl;
cout<<str4<<endl;
system("pause");
return 0;
}
//========================================
运行结果为
I like C++,I like the world.
Hello World.
Hi.....