标准库中的string类(上)——“C++”

简介: 标准库中的string类(上)——“C++”

各位CSDN的uu们好呀,好久没有更新小雅兰的C++专栏的知识啦,接下来一段时间,小雅兰就又会开始更新C++这方面的知识点啦,以及期末复习的一些知识点,下面,让我们进入西嘎嘎string的世界吧!!!



string类的常用接口说明


string类的常用接口说明

string类对象的常见构造


函数名称 功能说明
string() (重点) 构造空的string类对象,即空字符串
string(const char* s) (重点) 用C-string来构造string类对象
string(const string&s) (重点) 拷贝构造函数
string(size_t n, char c) string类对象中包含n个字符c
int main()
{
  string s1;//构造空的string类对象s1
  string s2("hello world");//用C格式字符串构造string类对象s2
  string s3 = s2;//拷贝构造s3
  string s4(s2);//拷贝构造s4
}

如果是想要把这些内容打印出来的话,就直接cout就可以了,因为库函数中已经重载了opeator<<!!!

#include<iostream>
#include<string>
using namespace std;
int main()
{
  string s1;//构造空的string类对象s1
  string s2("hello world");//用C格式字符串构造string类对象s2
  string s3 = s2;//拷贝构造s3
  string s4(s2);//拷贝构造s4
  cout << s1 << endl;
  cout << s2 << endl;
  cout << s3 << endl;
  cout << s4 << endl;
  return 0;
}

这些就是最常见的,其余的只需要了解一下就可以了,需要的时候直接查文档!

string (const string& str, size_t pos, size_t len = npos);

substring constructor
Copies the portion of str that begins at the character position pos and spans len characters (or until the end of str, if either str is too short or if len is string::npos).

str:Another string object, whose value is either copied or acquired.

pos:Position of the first character in str that is copied to the object as a substring.
If this is greater than str's length, it throws out_of_range.
Note: The first character in str is denoted by a value of 0 (not 1).

len:Length of the substring to be copied (if the string is shorter, as many characters as possible are copied).
A value of string::npos indicates all characters until the end of str.

n:Number of characters to copy.

int main()
{
  string s1;//构造空的string类对象s1
  string s2("hello world");//用C格式字符串构造string类对象s2
  string s3 = s2;//拷贝构造s3
  string s4(s2);//拷贝构造s4
  cout << s1 << endl;
  cout << s2 << endl;
  cout << s3 << endl;
  cout << s4 << endl;
  string s5(s2, 0, 5);
  cout << s5 << endl;
  return 0;
}

static const size_t npos = -1//整型的最大值

int main()
{
  string s1;//构造空的string类对象s1
  string s2("hello world");//用C格式字符串构造string类对象s2
  string s3 = s2;//拷贝构造s3
  string s4(s2);//拷贝构造s4
  cout << s1 << endl;
  cout << s2 << endl;
  cout << s3 << endl;
  cout << s4 << endl;
  string s5(s2, 0, 5);
  cout << s5 << endl;
  //下面这两种写法都是从字符串1的位置,取到结束
  string s6(s2, 1);
  string s7(s2, 1, 100);
  cout << s6 << endl;
  cout << s7 << endl;
  return 0;
}

string (const char* s, size_t n);

from buffer

Copies the first n characters from the array of characters pointed by s.

意思是从这个第n个字符开始拷贝,拷贝到目标字符串中!

int main()
{
   string s1;//构造空的string类对象s1
   string s2("hello world");//用C格式字符串构造string类对象s2
   string s3 = s2;//拷贝构造s3
   string s4(s2);//拷贝构造s4
   cout << s1 << endl;
   cout << s2 << endl;
   cout << s3 << endl;
   cout << s4 << endl;
   string s5(s2, 0, 5);
   cout << s5 << endl;
   //下面这两种写法都是从字符串1的位置,取到结束
   string s6(s2, 1);
   string s7(s2, 1, 100);
   cout << s6 << endl;
   cout << s7 << endl;
   string s8(s2, 5);
   cout << s8 << endl;
   return 0;
}

可是,最后的打印结果为什么会是这样的呢?怎么会是打印 world呢?难道不应该是打印hello吗?

原来是用错了!它自动匹配到了上一个函数:string (const string& str, size_t pos, size_t len = npos);

所以:string s8(s2, 5); 这句代码的意思是:从s2的第五个字符开始拷贝,一直拷贝到最后,直到后面再也没有内容!

应该这么写:

int main()
{
  string s1;//构造空的string类对象s1
  string s2("hello world");//用C格式字符串构造string类对象s2
  string s3 = s2;//拷贝构造s3
  string s4(s2);//拷贝构造s4
  cout << s1 << endl;
  cout << s2 << endl;
  cout << s3 << endl;
  cout << s4 << endl;
  string s5(s2, 0, 5);
  cout << s5 << endl;
  //下面这两种写法都是从字符串1的位置,取到结束
  string s6(s2, 1);
  string s7(s2, 1, 100);
  cout << s6 << endl;
  cout << s7 << endl;
  string s8(s2, 5);
  cout << s8 << endl;
  string s9("hello world", 5);
  cout << s9 << endl;
  return 0;
}

 

string (size_t n, char c);

fill constructor

Fills the string with n consecutive(连续的) copies of character c.

int main()
{
  string s1;//构造空的string类对象s1
  string s2("hello world");//用C格式字符串构造string类对象s2
  string s3 = s2;//拷贝构造s3
  string s4(s2);//拷贝构造s4
  cout << s1 << endl;
  cout << s2 << endl;
  cout << s3 << endl;
  cout << s4 << endl;
  string s5(s2, 0, 5);
  cout << s5 << endl;
  //下面这两种写法都是从字符串1的位置,取到结束
  string s6(s2, 1);
  string s7(s2, 1, 100);
  cout << s6 << endl;
  cout << s7 << endl;
  string s8(s2, 5);
  cout << s8 << endl;
  string s9("hello world", 5);
  cout << s9 << endl;
  string s10(10, 'l');
  cout << s10 << endl;
  return 0;
}

string的析构函数:

赋值运算符重载:

int main()
{
  string s1;//构造空的string类对象s1
  string s2("hello world");//用C格式字符串构造string类对象s2
  string s3 = s2;//拷贝构造s3
  string s4(s2);//拷贝构造s4
  cout << s1 << endl;
  cout << s2 << endl;
  cout << s3 << endl;
  cout << s4 << endl;
  string s5(s2, 0, 5);
  cout << s5 << endl;
  //下面这两种写法都是从字符串1的位置,取到结束
  string s6(s2, 1);
  string s7(s2, 1, 100);
  cout << s6 << endl;
  cout << s7 << endl;
  string s8(s2, 5);
  cout << s8 << endl;
  string s9("hello world", 5);
  cout << s9 << endl;
  string s10(10, 'l');
  cout << s10 << endl;
  cout<<endl;
  s1 = s2;
  cout << s1 << endl;
  s1 = "world";
  cout << s1 << endl;
  s1 = 'l';
  cout << s1 << endl;
  return 0;
}

这个赋值支持得很宽泛!因为写了很多重载版本!但是平时用的比较多的是第一种!!!


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

函数名称 功能说明
operator[] (重 点) 返回pos位置的字符,const string类对象调用
begin+end begin获取一个字符的迭代器 + end获取最后一个字符下一个位置的迭 代器
rbegin+end begin获取一个字符的迭代器 + end获取最后一个字符下一个位置的迭 代器
范围for C++11支持更简洁的范围for的新遍历方式

opetator[]

int main()
{
  string s1("hello world");
  cout << s1.size() << endl;
  cout << s1.length() << endl;
  for (size_t i = 0; i < s1.size(); i++)
  {
    cout << s1[i] << " ";
  }
  cout << endl;
}

int main()
{
   string s1("hello world");
   cout << s1.size() << endl;
   cout << s1.length() << endl;
   for (size_t i = 0; i < s1.size(); i++)
   {
       //cout << s1[i] << " ";
       cout << s1.operator[](i);————底层原理
   }
   cout << endl;
}

[]既可以读,又可以写!!!

int main()
{
  string s1("hello world");
  cout << s1.size() << endl;
  cout << s1.length() << endl;
  for (size_t i = 0; i < s1.size(); i++)
  {
    cout << s1[i] << " ";
    //cout << s1.operator[](i);
  }
  cout << endl;
  s1[0] = 'z';
  cout << s1 << endl;
}

那如果我现在想要把string逆置一下,那就简单了!

int main()
{
  string s1("hello world");
  cout << s1.size() << endl;
  cout << s1.length() << endl;
  for (size_t i = 0; i < s1.size(); i++)
  {
    cout << s1[i] << " ";
    //cout << s1.operator[](i);
  }
  cout << endl;
  s1[0] = 'z';
  cout << s1 << endl;
 
  //把string逆置一下
  int begin = 0;
  int end = s1.size() - 1;
  while (begin < end)
  {
    char tmp = s1[begin];
    s1[begin] = s1[end];
    s1[end] = tmp;
    begin++;
    end--;
  }
  cout << s1 << endl;
  return 0;
}

这只是其中一种写法,可是,在西嘎嘎中,写这个交换,其实是没有意义的,因为:库函数中给我们提供了这个接口!!!

int main()
{
   string s1("hello world");
   cout << s1.size() << endl;
   cout << s1.length() << endl;
   for (size_t i = 0; i < s1.size(); i++)
   {
       cout << s1[i] << " ";
       //cout << s1.operator[](i);
   }
   cout << endl;
   s1[0] = 'z';
   cout << s1 << endl;

   //把string逆置一下
   int begin = 0;
   int end = s1.size() - 1;
   while (begin < end)
   {
       /*char tmp = s1[begin];
       s1[begin] = s1[end];
       s1[end] = tmp;*/
       swap(s1[begin], s1[end]);
       begin++;
       end--;
   }
   cout << s1 << endl;
   return 0;
}

 

第二种遍历方式:iterator(迭代器)

string::iterator it = s1.begin();
while (it != s1.end())
{
  cout << *it << " ";
  ++it;
}
cout << endl;

也可以修改!

string::iterator it = s1.begin();
while (it != s1.end())
{
  *it += 1;
  cout << *it << " ";
  ++it;
}
cout << endl;

iterator的用法有点像指针!!!但是只是像指针,而不是就是指针!

vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
vector<int>::iterator vit = v.begin();
while (vit != v.end())
{
  cout << *vit << " ";
  ++vit;
}
cout << endl;
list<double> lt;
lt.push_back(1.1);
lt.push_back(2.1);
lt.push_back(3.1);
lt.push_back(4.1);
list<double>::iterator lit = lt.begin();
while (lit != lt.end())
{
  cout << *lit << " ";
  ++lit;
}
cout << endl;


reverse

string::iterator it = s1.begin();
while (it != s1.end())
{
   *it += 1;
   cout << *it << " ";
   ++it;
}
cout << endl;
reverse(s1.begin(), s1.end());
cout << s1 << endl;

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

list<double> lt;
lt.push_back(1.1);
lt.push_back(2.1);
lt.push_back(3.1);
lt.push_back(4.1);
list<double>::iterator lit = lt.begin();
while (lit != lt.end())
{
   cout << *lit << " ";
   ++lit;
}
cout << endl;
reverse(lt.begin(), lt.end());
lit = lt.begin();
while (lit != lt.end())
{
   cout << *lit << " ";
   ++lit;
}
cout << endl;


之前,我们手撕了一个string的逆置,但其实,西嘎嘎的库函数里面就有这个函数!

string、vector、list都逆置过来了!!!

之前的那个operator[],提供了两个版本:

    char& operator[] (size_t pos);

const char& operator[] (size_t pos) const;

第一个可以编译通过,第二个不能编译通过!

编译器会去找更匹配的!

int main()
{
  string s1("hello world");
  const string s2("hello world");
  s1[0] = 'x';
  //s2[0] = 'x';
  cout << s2[0] << endl;
 
  string::const_iterator it = s2.begin();
  while (it != s2.end())
  {
    //*it += 1;
    cout << *it << " ";
    ++it;
  }
  cout << endl;
  return 0;
}

for (auto e : s1)
{
   cout << e << " ";
}
cout << endl;

但是实际上,迭代器才是yyds!


所以,现在我们遍历,就有三种方法:

  • 下标+[]
  • 迭代器
  • 范围for

但是,主流还是迭代器!!!

void func(const string& s)
{
  string::const_reverse_iterator it = s.rbegin();
  while (it != s.rend())
  {
    cout << *it << " ";
    ++it;
  }
  cout << endl;
}
int main()
{
  string s1("hello world");
  string::reverse_iterator it1 = s1.rbegin();
  while (it1 != s1.rend())
  {
    cout << *it1 << " ";
    ++it1;
  }
  cout << endl;
  func(s1);
  return 0;
}



好啦,小雅兰今天的西嘎嘎string的使用部分就到这里啦,下一篇博客继续string的使用,后续还会写string模拟实现,加油!!!


相关文章
|
7天前
|
存储 编译器 C++
【c++】类和对象(中)(构造函数、析构函数、拷贝构造、赋值重载)
本文深入探讨了C++类的默认成员函数,包括构造函数、析构函数、拷贝构造函数和赋值重载。构造函数用于对象的初始化,析构函数用于对象销毁时的资源清理,拷贝构造函数用于对象的拷贝,赋值重载用于已存在对象的赋值。文章详细介绍了每个函数的特点、使用方法及注意事项,并提供了代码示例。这些默认成员函数确保了资源的正确管理和对象状态的维护。
33 4
|
8天前
|
存储 编译器 Linux
【c++】类和对象(上)(类的定义格式、访问限定符、类域、类的实例化、对象的内存大小、this指针)
本文介绍了C++中的类和对象,包括类的概念、定义格式、访问限定符、类域、对象的创建及内存大小、以及this指针。通过示例代码详细解释了类的定义、成员函数和成员变量的作用,以及如何使用访问限定符控制成员的访问权限。此外,还讨论了对象的内存分配规则和this指针的使用场景,帮助读者深入理解面向对象编程的核心概念。
27 4
|
28天前
|
安全 Java 测试技术
Java零基础-StringBuffer 类详解
【10月更文挑战第9天】Java零基础教学篇,手把手实践教学!
24 2
|
1月前
|
存储 编译器 对象存储
【C++打怪之路Lv5】-- 类和对象(下)
【C++打怪之路Lv5】-- 类和对象(下)
27 4
|
1月前
|
编译器 C语言 C++
【C++打怪之路Lv4】-- 类和对象(中)
【C++打怪之路Lv4】-- 类和对象(中)
23 4
|
1月前
|
存储 安全 C++
【C++打怪之路Lv8】-- string类
【C++打怪之路Lv8】-- string类
21 1
|
2月前
|
Java 索引
java基础(13)String类
本文介绍了Java中String类的多种操作方法,包括字符串拼接、获取长度、去除空格、替换、截取、分割、比较和查找字符等。
38 0
java基础(13)String类
|
1月前
|
Java
【编程基础知识】(讲解+示例实战)方法参数的传递机制(值传递及地址传递)以及String类的对象的不可变性
本文深入探讨了Java中方法参数的传递机制,包括值传递和引用传递的区别,以及String类对象的不可变性。通过详细讲解和示例代码,帮助读者理解参数传递的内部原理,并掌握在实际编程中正确处理参数传递的方法。关键词:Java, 方法参数传递, 值传递, 引用传递, String不可变性。
55 1
【编程基础知识】(讲解+示例实战)方法参数的传递机制(值传递及地址传递)以及String类的对象的不可变性
|
1月前
|
数据可视化 Java
让星星月亮告诉你,通过反射创建类的实例对象,并通过Unsafe theUnsafe来修改实例对象的私有的String类型的成员属性的值
本文介绍了如何使用 Unsafe 类通过反射机制修改对象的私有属性值。主要包括: 1. 获取 Unsafe 的 theUnsafe 属性:通过反射获取 Unsafe类的私有静态属性theUnsafe,并放开其访问权限,以便后续操作 2. 利用反射创建 User 类的实例对象:通过反射创建User类的实例对象,并定义预期值 3. 利用反射获取实例对象的name属性并修改:通过反射获取 User类实例对象的私有属性name,使用 Unsafe`的compareAndSwapObject方法直接在内存地址上修改属性值 核心代码展示了详细的步骤和逻辑,确保了对私有属性的修改不受 JVM 访问权限的限制
50 4
|
2月前
|
安全 Java
String类-知识回顾①
这篇文章回顾了Java中String类的相关知识点,包括`==`操作符和`equals()`方法的区别、String类对象的不可变性及其好处、String常量池的概念,以及String对象的加法操作。文章通过代码示例详细解释了这些概念,并探讨了使用String常量池时的一些行为。
String类-知识回顾①