IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 【C++初阶】string(上) -> 正文阅读

[C++知识库]【C++初阶】string(上)

本文中的string类的常用接口可以查询相关的文档进行查看:文档查询,暂不做具体的介绍

目录

一,string类对象的访问及遍历操作?

取文件的后缀?

三,经典习题

字符串中的第一个唯一字符OJ

仅仅反转字母OJ

字符串最后一个单词的长度OJ

验证回文串OJ

字符串相加OJ

四,深浅拷贝

深拷贝的传统写法:

赋值:

深拷贝的现代写法:

赋值:?


一,string类对象的访问及遍历操作?

template<class T>
class basic_string
{
public:
private:
	T* _a;
	size_t _size;
	size_t _capacity;
};
int main()
{
	string s1;
	string s2("hello");
	cout << s1 << endl;
	cout << s2 << endl;
	//第一种遍历方式
	for (size_t i = 0; i < s2.size(); i++)
	{
		s2[i] += 1;
	}
	for (size_t i = 0; i < s2.size(); i++)
	{
		cout << s2[i] << endl;
	}
	//第二种遍历方式
	for (auto& ch : s2)
	{
		ch -= 1;
	}
	cout << endl;
	for (auto ch : s2)
	{
		cout << ch << "";
	}
	cout << endl;

	//第三种遍历方式
    //迭代器的方式
	string::iterator it = s2.begin();
	while (it != s2.end())
	{
		*it += 1;
		it++;
	}
	it = s2.begin();

	while (it != s2.end())
	{
		cout << *it << "";
		it++;
	}
	cout << endl;
	return 0;
}

begin()返回第一个有效数据位置的迭代器

end()返回最后一个有效数据的下一个位置的迭代器?

迭代器是一个像指针一样的东西,有可能是指针,也有可能不是指针!

迭代器的好处:可以统一类似的方式去访问修改容器

vector迭代器:

int main()
{
	vector<int>v = { 1, 2, 3, 4, 5 };
	vector<int>::iterator vit = v.begin();
	while (vit != v.end())
	{
		cout << *vit << "";
		vit++;
	}
	cout << endl;
}

所以容器都支持用你迭代器,所以迭代器才是容器通用的访问方式

vector/string这种结构支持下标+[]去访问,像list,map就不支持了

取文件的后缀?

void test_string()
{
	string file1("test.txt.zip");
	string file2("test.c");
	size_t pos1 = file1.rfind('.');
	if (pos1 != string::npos)
	{
		//string sub1 = file1.substr(pos1,file1.size()-pos1);
		string sub1 = file1.substr(pos1);
		cout << sub1 << endl;
	}
	string url("http://www.cplusplus.com/reference/string/string/rfind/");
	cout << url << endl;
	//取出url中协议,域名,uri
	size_t i1 = url.find("://");
	if (i1 != string::npos)
	{
		string p = url.substr(0, i1 - 0);
		cout << "协议:" << p << endl;
	}
	size_t i2 = url.find('/',i1+3);
	if (i2 != string::npos)
	{
		string d = url.substr(i1+3,i2-(i1+3));
		cout << "域名:" << d << endl;
	}
	string uri = url.substr(i2);
	cout << "uri:" << uri << endl;
}
int main()
{
	test_string();
	return 0;
}

三,经典习题

字符串中的第一个唯一字符OJ

?计数排序的思想:

class Solution {
public:
    int firstUniqChar(string s) 
    {
        int count[26] = {0};
        //统计出每个字符出现的次数
        for(auto ch:s)
        {
            count[ch-'a']++;
        }
        for(int i = 0;i < s.size();i++)
        {
            if(count[s[i]-'a'] == 1)
            {
                return i;
            }
        }
        return -1;
    }
};

仅仅反转字母OJ

class Solution {
public:
	bool isLetter(char ch)
	{
		if (ch >= 'a' && ch <= 'z')
			return true;
		if (ch >= 'A' && ch <= 'Z')
			return true;
		return false;
	}
	string reverseOnlyLetters(string S) {
		auto begin = S.begin();
		auto end = S.end() - 1;
		while (begin < end)
		{
			while (begin < end && !isLetter(*begin))
				++begin;
			while (begin < end && !isLetter(*end))
				--end;
			swap(*begin, *end);
			++begin;
			--end;
		}
		return S;
	}
};

字符串最后一个单词的长度OJ

#include<iostream>
using namespace std;
int main()
{
    string s;
    getline(cin,s);
    size_t pos = s.rfind(' ');
    if(pos != string::npos)
    {
        cout <<s.size()-(pos+1)<<endl;
    }
    else
    {
        cout<<s.size()<<endl;
    }
    return 0;
}

验证回文串OJ

class Solution
{
public:
	bool IsletterOrNun(char ch)
	{
		if ((ch >= 'A' && ch <= 'Z')
			|| (ch >= 'a'&& ch <= 'z')
			|| (ch >= '0'&& ch <= '9'))
		{
				return true;
		}
		else
		{
			return false;
		}
	}
	bool isPalindrome(string s)
	{
		int begin = 0;
		int end = s.size() - 1;
		while (begin < end)
		{
			while (begin < end && !IsletterOrNun(s[begin]))
			{
				begin++;
			}
			while (begin < end && !IsletterOrNun(s[end]))
			{
				end--;
			}
			if (s[begin] != s[end])
			{
				//有一个是数字,就不存在大小写比较问题
				if (s[begin] < 'A' || s[end] < 'A')
				{
					return false;
				}
				//忽略字母的大小写
				else if (s[begin] < s[end] && s[begin] + 32 == s[end])
				{
					begin++;
					end--;
				}
				else if (s[end] < s[begin] && s[end] + 32 == s[begin])
				{
					begin++;
					end--;
				}
				else
				{
					return false;
				}
			}
			else
			{
				begin++;
				end--;
			}
		}
		return true;
	}
};

字符串相加OJ

class Solution
{
public:
	string addStrings(string num1, string num2)
	{
		string retStr;
		int end1 = num1.size() - 1;
		int end2 = num2.size() - 1;
		int carry = 0;//进位
		while (end1 >= 0 || end2 >= 0)
		{
			int val1 = 0;
			int val2 = 0;
			if (end1 >= 0)
			{
				val1 = num1[end1] - '0';//转换成整数
				end1--;
			}
			if (end2 >= 0)
			{
				val2 = num2[end2] - '0';//转换成整数
			}
			int ret = val1 + val2 + carry;
			if (ret > 9)
			{
				ret -= 10;
				carry = 1;
			}
			else
			{
				carry = 0;
			}
			retStr.insert(retStr.begin(), '0' + ret);
			//retStr += ('0' + ret);
		}
		if (carry == 1)
		{
			retStr.insert(retStr.begin(), '1');
			//retStr += '1';
		}
		reverse(retStr.begin(), retStr.end());
		return retStr;
	}
};

四,深浅拷贝

深拷贝的传统写法:

浅拷贝

指向同一块空间

第一:析构两次空间

第二:其中一个去修改值,会影响另一个

深拷贝

拷贝构造,新开一块跟原对象一样大的空间,再把原对象空间上的值拷贝过来

namespace bit
{
	class string
	{
	public:
		string(char* str)
			:_str(new char[strlen(str)+1])
		{
			strcpy(_str, str);
		}
		char& operator[](size_t pos)
		{
		     return _str[pos];  
		} 
		//s2(s1)深拷贝
		string(const string& s)
			:_str(new char[strlen(s._str)+1])
		{
			strcpy(_str, s._str);
		}
		~string()
		{
			delete[] _str;
			_str = nullptr;
		}
	private:
		char* _str;
	};
	void test_string1()
	{
		string s1("hello");
		s1[0] = 'x';
		string s2(s1);
		s2[0] = 'y';
	}
}

赋值:

思考:下面这段代码的问题??? 有何缺陷?

——>>>万一假设new失败了,那么把s1对象给释放了

//s1 = s3
		string& operator=(const string& s)
		{
			if (this != &s)
			{
				delete[] _str;
				_str = new char[strlen(s._str) + 1];
				strcpy(_str, s._str);
			}
		}

——>改造:?

string& operator=(const string& s)
		{
			if (this != &s)
			{
				char* tmp = new char[strlen(s._str) + 1];
				delete[] _str;
				_str = tmp;
				strcpy(_str, s._str);
			}
			return *this;
		}

深拷贝的现代写法:

//深拷贝的现代写法
		string(const string& s)
			:_str(nullptr)
		{
			string tmp(s._str);
			swap(_str, tmp._str);
		}

赋值:?

//s1=s3
		string &operator = (const string &s)
		{
			if (this != &s)
			{
				string tmp(s._str);
				swap(_str, tmp._str);
			}
			return *this;
		}

最简洁的现代写法:

string& operator = (string s)
		{
			swap(_str, s._str);
			return *this;
		}
  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-11-11 12:32:24  更:2021-11-11 12:32:43 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 5:28:19-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码