stl-string

#include<iostream>
using namespace std;
#include<cstdio>
//string就是管理字符串的类
#include<string>

//库里面定义
template<class T>
class basic_string
{
private:
	T* _str;
	//...
};


//编码 --值--符号建立映射关系--编码表(用值和符号建立对应关系) 
// ASCILL编码表---表示英文编码
// unicode ---(包含ascill)表示全世界文字编码
//又包含utf -8,utf-16 
//gbk        --     中国自己量身定做的编码表
// 汉字可以用2个字节,
// 
//typrdef basic_string<char> string,我们用的是typedef后出来的,模板的

//int main()
//{
//	string s1("hello");
//	char str2[] = "吃饭";
//	cout << sizeof(char) << endl;
//	cout << sizeof(wchar_t) << endl;//2个字节,wstring
//
//	return 0;
//}



//初始化

void init()
{
	string s1;//无调用构造函数
	string s2("hello world");//构造函数
	string s3(s2);//拷贝构造
	//cin >> s1;
	cout << s1 << endl;
	cout << s2 << endl;
	cout << s3 << endl;
	//substring (3)	

	//string(const string & str, size_t pos, size_t len = npos);
	//利用字串进行初始化,pos是从0开始,从string里面先后数len个长度进行拷贝


	string s4(s2, 2, 6);
	cout << s4 << endl;//llo wo
	string s5(s2, 2);//默认从坐标为2的地方往后截取所有的s2
	cout << s5 << endl;//ello world

	//string (const char* s, size_t n);
	string s7("hello world", 3);//取前3个字符
	cout << s7 << endl;
	//string(size_t n, char c);连续弄n个c
	string s8(3, '!');//!!!
}


void func()
{
	string s1("hello");
	//不计算‘\0’,这两个对于string没什么区别,size是后出现为了保证容器的一致性
	cout << s1.size() << endl;//5
	cout << s1.length() << endl;//5
	cout << s1.max_size() << endl;//没什么意义
	cout << s1 << endl;
								  //计算容量
	cout << s1.capacity() << endl;//15
	s1.clear();//把有效数据都清理掉,空间保留,变成空字符串,0个字符
	cout << s1 << endl;
	cout << s1.capacity() << endl;
	if (s1.empty())//判断此字符串是否为空,即是否长度为0
	{
		cout << "not" << endl;
	}


}


//char& operator[] (size_t pos);这里的引用返回是因为这个数组是在堆上开辟的,出了作用域还在,并且可以对其中的字符进行修改,或者调用,还可以减少拷贝(不是主要目的)


void operatoracess()
{
	string s1("hello world");
	for (size_t i = 0; i < s1.length(); i++)
	{
		cout << s1[i];//[]是断言终止程序,检查错误
		s1[i] += 1;
	}
	cout << endl;
	for (size_t i = 0; i < s1.length(); i++)
	{
		s1.at(i) -= 1;//和上面是一样的
		cout << s1.at(i) << endl;//at是抛异常检查错误,建议还是使用[ ]
	}
	cout << endl;

}

//对字符串进行尾部添加字符或字符串
void add()
{
	string s;
	s.push_back('a');
	s.append("bcde");//尾插bcd
	cout << s << endl;//abcd
	s += '!';//也可以利用运算符重载进行实现尾插,推荐,abcd!
}


//只交换字符
//abc-bcd-qwlkj变成 jkl-wqd-cbcba  
//
class Solution {
public:
  //计算最后一个单词的长度如“hello world  ”g

  int lengthOfLastWord(string s) {
            int end=s.size()-1;
                    while(s[end]==' ')
                    {
                                  s.erase(end,1);//无法使用
                                              end--;
                                                      
                                                      
                    }
                            
                    size_t pos=s.rfind(" ");

                    string sub=s.substr(pos+1);
                    return sub.size();



                        
  }




};

//遍历,1.迭代器2.范围for
void test_string1()
{
  
string s1("hello");
string::iterator it=s1.begin();//s1.begin(),是第一个数据的地址,s1.end()是最后一个数据的后一个的地址
//这个iterator是定义在string里面,it现在指向了第一个数据的地址
//现在可以先想象成一个像指针一样的类型
//
while(it!=s1.end())//直到结尾就结束了,但是不建议用<
{
  cout<<*it<<" ";//*就是取他的数据
  ++it;//到下一个地址
}
cout<<endl;
//除了可以读还可以写
 it=s1.begin();//s1.begin(),是第一个数据的地址,s1.end()是最后一个数据的后一个的地址
//这个iterator是定义在string里面,it现在指向了第一个数据的地址
//现在可以先想象成一个像指针一样的类型
//
while(it!=s1.end())//直到结尾就结束了
{
  *it-=1;//*就是取他的数据
  ++it;//到下一个地址
}
cout<<endl;


//范围for,auto可以自动识别
//for(auto e:s1)//把s1里面每个字符取出来赋值给e,不需要自己++,自动判断结束
//{
//  cout<<e<<" ";
//}
cout<<endl;

//要修改就要用引用
//for(auto& e:s1)
//{
//  e-=1;
//}
cout<<endl;

//反向迭代器
//倒着遍历
string::reverse_iterator rit=s1.rbegin();//rbegin(),是最后一个数据的地址
//为了简化代码也可以直接auto推到
//
//auto  rit=s1.rbegin()
//
while(rit!=s1.rend())//rend()是第一个数据的前一个地址
{
  cout<<*rit<<" ";//olleh,反过来遍历
  ++rit;//反向迭代器的++,是往左走的
}
cout<<endl;

//迭代器遍历的意义是什么呢:所有的容器都可以用迭代器这种访问修改
//1.对于string类来说,利用[]都足够好用,确实可以不用迭代器
//2。对于其他容器(数据结构)也可以使用,如list,map,set,这些是不支持[],因为只有像数组一样的东西才支持[]遍历和下标,
//结论::对于string得会用迭代器,但是我们还是喜欢下标加[],

//还有const迭代器,普通迭代器是可读可写的
string cstr("hello world");
//funcion(cstr);
string::const_iterator re=s1.begin();//只读不写,同理还有反向迭代器
//cbegin()就是const迭代器,但是我们平时都不太用,

}



//对于容量的函数
void test_string3()
{
string s1;
s1.reserve(100);//可以设置容量的大小,容量就是100,加上原来的容量
string s2;
s2.resize(100,'x');//也是可以设置容量的大小,同时还可以对其进行初始化,如将s1有效数据的后面全部设置成x,如果没有第二个参数,则默认是‘\0’
}





//对于find,c_str ,rfind的认识与理解
void test_string2()
{

string s2="hello world";
cout<<s2.c_str()<<endl;//将string转变成c语言的形式字符串,char*,以\0截至
string file("test.txt");
//我们要以c语言的形式打开一个文件
//FILE* fout=fopen(s2.c_str(),"w"); //fopen第一个参数是char*,所以用这函数

//要求取出文件的后缀

  size_t pos=file.find('.');//在file里面查找‘x’的位置,find的返回值是size_t,下标从0开始,查找第一个符合的坐标,否则就返回-1
  
string s1(file,pos);
cout<<s1<<endl;
if(pos!=string::npos)
{
  string suffix=file.substr(pos);
cout<<suffix<<endl;
}

//rfind()//可以从后面完前找,找到第一个.,方便找后缀名
//https://blog.csdn.net/m0_61567378?spm=1000.2115.3001.5343
string url("http://blog.csdn.net/m0_61567378?spm=1000.2115.3001.5343");
//找协议头
size_t pos1=url.find(':');//:前面的就是协议头

string protocol=url.substr(0,pos1-0);//取得字串就是从0开始,到pos1位置,长度为pos1的字串,也就是http
cout<<protocol<<endl;

//找域名,
size_t pos2=url.find('/',pos1+3);//find默认从0开始找,现在我们给定他从pos1+3位置处开始找,也就是b开始,往后找,找到/的位置

string domain=url.substr(pos1+3,pos2-pos1-3);
cout<<domain<<endl;

//统一资源定位
string uri=url.substr(pos2+1);
cout<<uri<<endl;


}



//
void test_string4()
{

//insert不太推荐用,O(n),效率低

  string s="hell";
  s.insert(0,"owlod");//在头上插入一个owlod,是从第0个位置往后插入
  s.insert(0,1,'x');//在头上插入一个x,是
  s.insert(4,"xx");//从第4个位置往后插入xx
  cout<<s<<endl;

  //要挪动数据效率很低,
  s.erase(4,2);//从4位置,删除两个长度的字符
  cout<<s<<endl;
  s.erase(s.size()-1,1);//尾删
  s.erase(3);//第二个参数不给值就后面全部都删除了

  //尾删也可以
//s.pop_back();

//输入一整行的数据,包括‘ ’
getline(cin,s);//第一个参数是流 


}



void test_string5()
{

  string s1="hello";
  string s2="string";
  cout<<(s1<s2)<<endl;//h<s所以就是小于

  cout<<("hello"<s2)<<endl;//char*的也可以比较
  cout<<(string("hello")<s2)<<endl;//这样也是可以的
}



//字符串与整形的转化


void test_string6()
{

  int val=stoi("1234");//转变成int
  cout<<val<<endl;//1234
  double val1=stod("123");
  //转变成字符串
  string str=to_string(12.345);
string s=to_string(123456);


  string str = to_string(12.345);

}


//浅拷贝,完成值拷贝,将每个字节一起拷贝
//对于指针类型的就不可以靠浅拷贝
//浅拷贝抄作业连名字都没改,完完全全的抄
//深拷贝就是抄作业改了名字,不完全的抄
//

classm  my_string 
{
  private:
    char* _str;
  public:
    //构造函数
    my_string(const char* str)
    :_str(new char[strlen(str)+1])
    {
strcpy(_str,str);
    }

    //拷贝构造要用深拷贝
    my_string(const my_string& s)
      :_str(new char[strlen(str)+1])
    {
      strcpy(_str,s.str);
    }

}

void test_string7()
{


}




int main()
{
//	init();
//	func();
//	operatoracess();
//	add();
//	Solution sl;

//	sl.reverseOnlyLetters("Test1ng-Leet=code-Q!");
//test_string1();
//test_string3();
//test_string2();
//test_string4();
Solution ts;
string s="hello world  ";
//int k=ts.lengthOfLastWord(s);
//cout<<k<<endl;
//test_string6();

string s1 = "A man, a plan, a canal: Panama";

isPalindrome(s1);

return 0;

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Zevin~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值