C++知识点复习 ---- C++中的字符串类

一. 历史遗留问题

  • C语言不支持真正意义上的字符串
  • C语言字符串数组和一组函数实现字符串操作
  • C语言不支持自定义类型,因此无法获得字符串类型

解决方案:

  • 从C到C++的进化过程引入了自定义类型
  • 在C++中可以通过类完成字符串类型的定义

问题:
C++中的原生类型系统是否包含字符串类型?

二. 标准库中的字符串类

  • C++语言直接支持C语言的所有概念
  • C++语言中没有原生的字符串类型
  • C++标准库提供了string类型
    (1)string直接支持字符串连接
    (2)string直接支持字符串的大小比较
    (3)string直接支持子串查找和提取
    (4)string直接支持字符串的插入和替换

字符串类的使用示例:

#include <iostream>
#include <string>
using namespace std;
//字符串排序,基于字典顺序
void string_sort(string a[], int len)
{
	for(int i = 0; i<len; i++)
	{
		for(int j = i; j<len; j++)
		{
			if(a[i] > a[j])
			{
				swap(a[i], a[j]);
			}
		}
	}
}
//字符串连接
string string_add(string a[], int len)
{
	string ret = "";	
    for(int i = 0; i<len; i++)
	{
		ret += a[i] + ";" ;    //字符串类中进行了操作符重载
	}	
	return ret;	
}

int main()
{
    string sa[7] =
	{
		"Hello World",
		"Super man",
		"C#",
		"Java",
		"C++",
		"Python",
		"TypeScript"
	};	
	string_sort(sa, 7);
	for(int i = 0; i<7; i++)
	{
		cout << sa[i] << endl;
	}
	cout << endl;
	cout << string_add(sa, 7) << endl;
    return 0;
}
编译结果:
C#
C++
Hello World
Java
Python
Super man
TypeScript

C#;C++;Hello World;Java;Python;Super man;TypeScript;

三. 标准库中的字符串类

字符串与数字的转换:
1.标准库中提供了相关的类对字符串和数字进行转换
2.字符串流类(sstream)用于string的转换
1) < sstream > – 相关头文件
2)istringstream – 字符串输入流
3)ostringstream – 字符串输出流

使用方法:
1.string --> 数字
istringstream iss(“123.45”);
double num;
iss >> num;
2. 数字 --> string
ostringstream oss;
oss << 543.21;
string s = oss.str();

字符串和数字的转换示例:

#include <iostream>
#include <string>
#include <sstream>
using namespace std;

//字符串转数字
#define TO_NUMBER(s, n) (istringstream(s) >> n)
/*
bool to_number(const string& s, int& n)  //考虑模板
{
    istringstream iss(s);
    return iss >> n;
}
*/
//数字转字符串
#define TO_STRING(n) (((ostringstream&)(ostringstream() << n)).str())
//强制类型转换成字符串输出流
/*
string to_string(int n)  //考虑模板
{
    ostringstream oss;
    oss << n;
    return oss.str();
}
*/

int main()
{
	double n = 0;
	if( TO_NUMBER("125.7896", n))
	{
		cout << n << endl;
	}
	string s = TO_STRING(123456);
	cout << s << endl;
    return 0;
}

/*  
原始版本:
int main()
{
    istringstream iss("123.45");
    double num;
    iss >> num;  // if (iss >> num)
	cout << num << endl;  //123.45
	
    ostringstream oss;
    oss << 543.21; // oss << 543 << "." << 21;
    string s = oss.str();
	cout << s << endl;  //543.21
	
    return 0;
}
*/

四. 面试题解析

1.字符串循环右移
问题 :abcdefg循环右移3位后得到efgabcd

代码示例:

#include <iostream>
#include <string>
using namespace std;
string right_func(const string& s, unsigned int n) //字符串引用,右移n位
{
    string ret = "";
    unsigned int pos = 0; //找到位置
    
    //abcdefg==>3  efg abcd   右移三位的字符串子类提取出来
    //abc==> 1 cab
    //abc==> 3 abc ==> 1 cab  右移一位和右移四位效果相同
    n = n % s.length();  // 取余,取多少位都是合法的
    pos = s.length() - n; //查位置
    ret = s.substr(pos); //查子串,将后面的部分提取出来
    ret += s.substr(0, pos); //提取子串,从0开始,到pos结束
    //abcdefg ==> 8
    //abcdefg ==> 1
    //8 % 7 ==> 1
    // 7-1==> 6
    //abcdef g
    // ret ==> g
    //ret = g+ abcdef
    //ret = gabcdefg
    return ret;
}
/*
如果转换函数替换成操作符重载
string operator >> (const string& s, unsigned int n)
*/
int main()
{
    string r = right_func("abcdefg", 8);
    /* 
    操作符重载的方式
    string r = "abcdefg"; 
    string r = (s>>3);
    */
    cout << r << endl;
    return 0;
}
运行结果
gabcdef

小结:
应用开发中大多数的情况都在进行字符串处理
C++中没有直接支持原生的字符串类型
标准库中通过string类支持字符串的概念
string类支持字符串和数字的相互转换
string类的应用使得问题的求解变得简单

五 . string类型使用注意事项

  • 应用示例1:
#include <iostream>
#include <string>

using namespace std;

int main()
{
    string s = "12345";
    const char* p = s.c_str();
        
    cout << p << endl;  //预计输出 12345
        
    s.append("abced");  // p 成为了野指针
        
    cout << p << endl;  //预计输出 12345abcde    
    return 0;
}
输出结果:
12345
12345

结果不是12345abcde,插入失败。
string s ,s是字符串类。
const char* p = s.c_str();
s.c_str()将返回一个C语言方式的字符串。
说明这段代码混合了C语言和C++的编程方式。
将 cout << p << endl;
改成:
cout << s<< endl;
j结果就是12345abcde

在这里插入图片描述
问题分析:
在string类的内部有一个字符指针m_cstr,当s="12345"时(赋值或初始化),字符指针将指向一个堆空间,并且这个堆空间存储了这个字符串。
p=s.c_str();通过一个指针指向这个堆空间,p这个字符指针所代表的字符串就是12345
s.append(“abced”);字符指针所指向的堆空间变成了新的内容。但是新的字符指针并没有指向原来的地址。
也就是说string对象内部维护的char指针,在运行时改变了,原来的指针会被释放,释放后char p就是一个野指针了。
避免方法:不要混合C语言和C++编程思想。

  • 应用示例2:
#include <iostream>
#include <string>

using namespace std;

int main()
{
    const char* p = "12345";
    string s = "";        
    s.reserve(10); //将字符串对象内部的数据指针的大小变成10个字节 
    // 不要使用 C 语言中的方式操作 C++ 中的字符串
    for(int i=0; i<5; i++)
    {
        s[i] = p[i];
    }
    if(!s.empty())
    {
        cout << s << endl;
    }
    return 0;
}
无输出

如果
for(int i=0; i<5; i++)
{
cout << s[i] << endl;
}
将输出1 2 3 4 5
在这里插入图片描述
for前后m_length始终为0,字符串本身长度没有变化,仍然为空串
解决方法,不需要for循环,避免指针的使用

const string p = "12345";
string s = "";
s = p
cout << s << endl;

小结:
string类通过一个数据空间保存字符数据
string类通过一个成员变量保存当前字符串的长度
C++开发是进来避开C语言中惯用的编程思想

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值