网站建设模板删不掉广州seo优化费用
1.为什么要学习String
(1) c语言的字符串是以‘\0’结尾的字符集合,为了方便操作,c标准库提供了一系列str系列函数。但是这些库函数与字符串是分离的,不太符合OOP的思想,而且底层空间需要用户自己管理,会有越界等的分险。
(2)在Oj题或者平常工作使用中,String的出现会让对字符串的操作更加检点,方便和快捷。
2.认识String
2.1 了解string
(1).字符串是表示字符序列的对象
(2).标准的字符串类提供了对此对象的支持,其接口类似于标准子符容器的接口,但添加了专门用于操作单字符串的设计特性。
(3).string类是使用char(即作为它的字符类型, 使用它的默认char_traits和分配器类型)
(4).string类是basic_string模版类的一个实例, 它使用char来实例化basic_string模版类, 并用char_traits和allocator作为basic_taring的默认参数。
(5). 注意:这个类独立于左右的编码来处理字节,如果用来处理多字节或变长字符(如UTF-8)的序列, 这个类的做优成员(如长度或大小)以及她的迭代器, 将任然按照字节(而不是实际编码的字符)来操作。
总结:
1.string是表示字符串的字符串类
2.该类的接口与常规容器的接口基本相同,再添加了一些专门用来操作string的常规操作。
3.string在底层实际是:basic_string类模板的别名,typedef basic_sting<char, char_traits, allocator> string;
4.不能操作多字节或者变长字符的序列。
在使用string 类时, 必须包含#include头文件以及using namespace std;
2.2 string的常用接口说明
函数名称 | 功能说明 |
---|---|
string() | 构造函数,构造空的string类对象, 即空字符串 |
string(const char* s) | 用C-string来构造string类对象 |
string(size_t n, char c) | string类对象中包含n个字符C |
string(const string&s) | 拷贝构造函数 |
示例 | void Teststring () { string s1 ; // 构造空的 string 类对象 s1 string s2 ( "hello bit" ); // 用 C 格式字 符串构造 string 类对象 s2 string s3 ( s2 ); // 拷贝构造 s3 } |
size() | 返回字符串有效字符长度 |
length() | 返回字符串有效字符长度 |
capacity() | 返回空间总大小 |
empty() | 检测字符串释放为空串, 是返回true 否则返回false |
clear() | 清空有效字符 |
reserve() | 为空字符串预留空间 |
resize() | 将有效祖父的个数改成n个,多出来的用字符c填充 |
operator[] | 返回pos位置的字符, coset string类对象调用 |
begin + end | begin 获取一个字符的迭代器 + end 获取最后一个字符下一个位置的迭代器 |
rbegun + read | begin获取一个字符的迭代器 + end获取最后一个字符下一个位置的迭代器 |
范围for | c++支持更简洁的范围for的新遍历方式 |
push_back | 在字符串后尾插字符c |
append | 在字符串后追加一个字符串 |
operator+= | 在字符串后追加字符串str |
c_str | 返回c格式字符串 |
find + npos | 从字符串pos位置开始往后找字符c, 返回改字符在字符串中的位置 |
rfind | 从字符串 pos 位置开始往前找字符 c ,返回该字符在字符串中的位置 |
substr | 在 str 中从 pos 位置开始,截取 n 个字符,然后将其返回 |
operator+ | 尽量少用,传值返回,导致深拷贝效率低 |
operator>> | 输入运算符重载 |
operator<< | 输出运算符重载 |
grtline | 获取一行字符串 |
relational_operators | 比较两个string的大小 |
注:1.在string尾部追加字符时, s.push_back(c) / s.append(1, c) / s += 'c'三种的实现方式差不多,一般 情况下string类的+=操作用的比较多,+=操作不仅可以连接单个字符,还可以连接字符串。
3.vs 和 g++ 下string结构的说明
32位平台下
vs下string的结构共占28个字符, 内部结构稍微复杂一点, 先是有一个联合体,联合体用来定义string 中祖父床的存储空间:
1.当字符串长度小于1时,使用内部固定的字符数组来存放
2.大于等于16 ,从堆上开辟
union _Bxty
{ // storage for small buffer or pointer to larger onevalue_type _Buf[_BUF_SIZE];pointer _Ptr;char _Alias[_BUF_SIZE]; // to permit aliasing
} _Bx;
struct _Rep_base
{size_type _M_length; // 字符串有效长度size_type _M_capacity; // 空间总大小_Atomic_word _M_refcount; //引用计数
};
4.实现简单的string,以便于理解
mystring.h
#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
#include <string>
#include <string.h>using namespace std;
namespace my_string
{class string {typedef char* iterator;typedef const char* const_iterator;public:string(const char* str = "");~string();string(const string& s);string& operator=(const string& s);size_t capaccite();size_t szie();char* c_str();size_t find(char ch, size_t pos = 0);size_t find(char* str, size_t pos = 0);void insert(size_t pos, char ch);void swap(string& s);void reserve(size_t n);void resize(size_t n, char c = '\0');void append(const char* str);void push_back(char ch);iterator begin();iterator end();const_iterator begin() const;const_iterator end() const;string& operator+=(char ch);string& operator+=(char* str);char& operator[](size_t pos);const char& operator[](size_t pos) const;void clear();void insert(size_t pos, const char* str);void erase(size_t pos, size_t len = npos);private:size_t __capacity;size_t __size;char* __str;public:const static size_t npos;};ostream& operator<<(ostream& out, const string& s);istream& operator >> (istream& in, string& s);
}//istream& operator>>(my_string::string::istream& _cin, my_string::string& s);
//ostream& operator<<(my_string::string::ostream& _cout, const my_string::string& s);
mystring.cpp
#include "myString.h"
const size_t my_string::string::npos = -1;my_string::string::string(const char* str):__capacity(strlen(str)),__size(__capacity)
{__str = new char[__capacity + 1];strcpy(__str, str);
}my_string::string::string(const string& s)
{string tmp(s.__str);swap(tmp);
}my_string::string& my_string::string::operator=(const string& s)
{string tmp(s);swap(tmp);return *this;
}void my_string::string::swap(string& s)
{std::swap(__str, s.__str);std::swap(__capacity, s.__capacity);std::swap(__size, s.__size);
}
size_t my_string::string::capaccite()
{return __capacity;
}
size_t my_string::string::szie()
{return __size;
}
char* my_string::string::c_str()
{return __str;
}my_string::string::~string()
{delete[] __str;
}void my_string::string::reserve(size_t n)
{if (n <= __capacity) return;if (n > __capacity){char* new_str = new char[n + 1];if (__str){strcpy(new_str, __str);}else {new_str[0] = '\0';}delete[] __str;__str = new_str;__capacity = n;}
}
void my_string::string::resize(size_t n, char c)
{if (n <= __capacity) {__str[n] = '\0';__size = n;}else {reserve(n);while(__size < n){__str[__size++] = c;}__str[__size] = '\0';}
}void my_string::string::push_back(char ch)
{if (__size >= __capacity){__capacity = __capacity == 0 ? 4 : __capacity * 2;reserve(__capacity);}__str[__size++] = ch;__str[__size] = '\0';
}my_string::string::iterator my_string::string::begin()
{return __str;
}
my_string::string::iterator my_string::string::end()
{return __str + __size;
}my_string::string::const_iterator my_string::string::begin() const
{return __str;
}
my_string::string::const_iterator my_string::string::end() const
{return __str + __size;
}
char& my_string::string::operator[](size_t pos)
{return __str[pos];
}const char& my_string::string::operator[](size_t pos) const
{return __str[pos];
}size_t my_string::string::find(char ch, size_t pos)
{while (__size > pos){if (__str[pos] == ch){return pos;}pos++;}return npos;
}size_t my_string::string::find(char* str, size_t pos)
{const char* p = strstr(__str + pos, str);if (p){return p - __str;}return npos;
}void my_string::string::clear()
{__str[0] = '\0';__size = 0;
}void my_string::string::append(const char* str)
{size_t len = strlen(str);if (__size + len > __capacity){reserve(__size + len);}strcpy(__str + __size, str);__size += len;
}my_string::string& my_string::string::operator+=(const char ch)
{push_back(ch);return *this;
}
my_string::string& my_string::string::operator+=(const char* str)
{append(str);return *this;
}void my_string::string::insert(size_t pos, char ch)
{if (pos <= __size) return;if (__size == __capacity){reserve(__capacity == 0 ? 4 : __capacity * 2);}size_t end = __size + 1;while (end > pos){__str[end] = __str[end + 1];--end;}__str[pos] = ch;__size++;}void my_string::string::insert(size_t pos, const char* str)
{if(pos <= __size) return;size_t len = strlen(str);if (__size + len > __capacity){reserve(__size + len);}// 挪动数据int end = __size;while (end >= (int)pos){__str[end + len] = __str[end];--end;}strncpy(__str + pos, str, len);__size += len;
}void my_string::string::erase(size_t pos, size_t len)
{if(pos < __size) return;if (len == npos || pos + len >= __size){__str[pos] = '\0';__size = pos;}else{size_t begin = pos + len;while (begin <= __size){__str[begin - len] = __str[begin];++begin;}__size -= len;}
}
ostream& operator<<(ostream& out, const my_string::string& s)
{for (auto ch : s){out << ch;}return out;
}istream& operator >> (istream& in, my_string::string& s)
{s.clear();char buff[129] = { 0 };size_t i = 0;char ch = in.get();while (ch != ' ' && ch != '\n'){buff[i++] = ch;if (i == 128){buff[i] = '\0';s += buff;i = 0;}ch = in.get();}if (i != 0){buff[i] = '\0';s += buff;}return in;
}int main(){my_string::string s("str");s += "string";for (auto str : s){std::cout << str << " ";}std::cout << std::endl;const my_string::string s1 = s;for (const auto str : s1){std::cout << str << " ";}std::cout << std::endl;my_string::string s2(s);for (auto str : s2){std::cout << str << " ";}std::cout << std::endl;return 0;
}