C++中的字符串类
1,本文分析 c++ 中的字符串,c 语言中的字符串利用的是 c 语言中的字符数组, 在 c 语言中没有真正意义上的字符串,利用了字符数组表示了字符串,最初设 计 c 语言仅仅是为了开发 unix 操作系统,而开发操作系统要处理的仅仅是数 据本身,关于字符串的处理很少,所以说当时没有在 c 语言中内置一个字符串 现在绝大多数都是在用 c 语言开发应用程序,而开发应用程序中对字符串的处 理是非常多的,如果还是用字符数组表达字符串,一定会使得开发效率大大下 降,因此在 c++ 中有必要引入字符串的概念,不仅仅是用字符数组来模拟,而 是真正意义上的字符串;
2,历史遗留问题:
1,c 语言不支持真正意义上的字符串;
1,c++ 也不支持;
2,c 语言用字符数组和一组函数实现字符串操作;
1,c++ 同样支持;
3,c 语言不支持自定义类型,因此无法获得字符串类型;
1,c++ 支持自定义类型,因此可以获得字符串类型;
3,解决方案:
1,从 c 到 c++ 的进化过程引入了自定义类型;
2,在 c++ 中可以通过类完成字符串类型的定义;
4,c++ 中的原生类型系统是否包含字符串类型?
1,不包含;
5,标准库中的字符串类:
1,c++ 语言直接支持 c 语言的所有概念;
2,c++ 语言中没有原生的字符串类型;
3,c++ 标准库提供了 string 类型:
1,string 直接支持字符串连接;
1,重载 “+”;
2,string 直接支持字符串的大小比较;
1,重载大小操作符,可以对字符串进行排序;
3,string 直接支持子串查找和提取;
4,string 直接支持字符串的插入和替换;
5,查阅 c++ 标准库文档;
6,字符串类的使用编程实验:
1,main.cpp 文件:
1 #include <iostream> 2 #include <string> 3 4 using namespace std; 5 6 void string_sort(string a[], int len) 7 { 8 for(int i=0; i<len; i++) 9 { 10 for(int j=i; j<len; j++) 11 { 12 if( a[i] > a[j] ) // string 类重载了 “>”; 13 { 14 swap(a[i], a[j]); 15 } 16 } 17 } 18 } 19 20 string string_add(string a[], int len) 21 { 22 string ret = ""; 23 24 for(int i=0; i<len; i++) 25 { 26 ret += a[i] + "; "; // string 类重载了 “+=” 和 “+”; 27 } 28 29 return ret; 30 } 31 32 int main() 33 { 34 string sa[7] = 35 { 36 "hello world", 37 "d.t.software", 38 "c#", 39 "java", 40 "c++", 41 "python", 42 "typescript" 43 }; 44 45 string_sort(sa, 7); 46 47 for(int i=0; i<7; i++) 48 { 49 cout << sa[i] << endl; 50 } 51 52 cout << endl; 53 54 cout << string_add(sa, 7) << endl; 55 56 return 0; 57 }
2,输出结果:
1 c# 2 c++ 3 d.t.software 4 hello world 5 java 6 python 7 typescript 8 9 c#; c++; d.t.software; hello world; java; python; typescript;
3,c++ 中没有必要使用字符数组模拟字符串了,直接使用标准库中的 string 类型;
7,标准库中的字符串类:
1,字符串与数字的转换:
1,标准库中提供了相关的类对字符串和数字进行转换;
1,基于字符串流类 sstream 来进行转换;
2,sstream 类诞生的目的就是为了支持字符串和数字之间的相互转换;
2,字符串流类(sstream)用于 string 的转换:
1,<sstream> - 相关头文件;
2,istringstream - 字符串输入流;
3,ostringstream - 字符串输出流;
2,使用方法:
1,string ==> 数字;
1,istringstream iss("123.45");
2,double num;
3,iss >> num;
1,传输成功,表达式值为 true,失败则为 false;
4,上述三步,等价于 istringstream("123.45") >> num;
2,数字 ==> string:
1,ostringstream oss;
2,oss << 543.21;
1,返回值是 oss 本身;
3,string s = oss.str();
4,上述三步,等价于 s =(sotringstream() << 543.21).str();
3,输入输出是相对内存而言的;
8,字符串和数字的转换编程实验:
1,main.cpp 文件:
1 #include <iostream> 2 #include <sstream> 3 #include <string> 4 5 using namespace std; 6 7 /* 实际工程用法,目前为止(后续采用模板),只能通过 c 语言中的宏来只写一遍代码处理所有的因类型不同而要完成的函数重载 */ 8 #define to_number(s, n) (istringstream(s) >> n) // 宏要在一行代码中完成,直接调用构造函数产生临时对象,临时对象声明周期可以满足要求;这里定义了临时对象,并将临时对象传递到 n 中去; 9 #define to_string(n) (((ostringstream&)(ostringstream() << n)).str()) // 调用构造函数生成临时对象,这里 (ostringstream&) 为强制类型转换否则编译器显示 error: ‘struct std::basic_ostream<char, std::char_traits<char> >’ has no member named ‘str’这个错误; 10 11 int main() 12 { 13 double n = 0; 14 15 if( to_number("234.567", n) ) // 返回 bool 类型的变量; 16 { 17 cout << n << endl; 18 } 19 20 string s = to_string(12345); 21 22 cout << s << endl; 23 24 return 0; 25 }
9,面试题分析:
1,示例:abcdefg 循环右移 3 位后得到 efgabcd;
10,用 c++ 完成面试题编程实验:
1,main.cpp 文件:
1 #include <iostream> 2 #include <string> 3 4 using namespace std; 5 6 /* 将 string rignt_func(const string& s, unsigned int n) 直接更改名字变成右移操作符重载 */ 7 string operator >> (const string& s, unsigned int n) 8 { 9 string ret = ""; 10 unsigned int pos = 0; // 找子串右移开始的位置; 11 12 n = n % s.length(); // 防止右移位置很大的情况,让其合法; 13 pos = s.length() - n; // 得到最终想要的位置; 14 ret = s.substr(pos); // 从 pos 开始直到末尾提取子串; 15 ret += s.substr(0, pos); //原来的字符串并没有被破坏,提取到 pos 之前的字符; 16 17 return ret; 18 } 19 20 int main() 21 { 22 string s = "abcdefg"; 23 string r = (s >> 3); 24 25 cout << r << endl; 26 27 return 0; 28 }
2,输出结果:
efgabcd
3,整个过程没有出现字符数组,我们站在了更高的角度处理问题,并且函数内部实现也非常简单,没有 for 循环;
4,面试时,对于一个面试题,面试官一般不需要最后的答案,需要的是你如何思考,如何解决的,考察是思维能力和解决问题能力;
11,小结:
1,应用开发中大多数的情况都在进行字符串处理;
2,c++ 中没有直接支持原生的字符串类型;
3,标准库中通过 string 类支持字符串的概念;
4,string 类支持字符串和数字的相互转换;
5,string 类的应用使得问题的求解变得简单;