实验3 数组、指针与现代C++标准库
实验任务2 string类的用法
1 #include <iostream> 2 #include <string> 3 4 int main() { 5 using namespace std; 6 7 string s1, s2; 8 s1 = "nuist"; // 赋值 9 s1[0] = 'N'; // 支持通过[]和索引方式访问 10 s1.at(1) = 'U'; // 支持通过xx.at()方法访问 11 cout << boolalpha << (s1 == "nuist") << endl; // 字符串比较 12 cout << s1.length() << endl; // 字符串长度 13 cout << s1.size() << endl; // 字符串长度 14 s2 = s1 + ", 2050"; // 字符串连接 15 cout << s2 << endl; 16 17 string email{"xyz@gmail.com"}; 18 auto pos = email.find("@"); // 查找子串"@"第一次出现的索引位置,如果失败,返回string::npos 19 if (pos == string::npos) 20 cout << "illegal email address"; 21 else { 22 auto s1 = email.substr(0, pos); // 取子串, 从索引0 ~ pos-1 23 auto s2 = email.substr(pos + 1); // 取子串,从pos+1到末尾 24 cout << s1 << endl; 25 cout << s2 << endl; 26 } 27 28 string phone{"15216982937"}; 29 cout << phone.replace(3, 5, string(5, '*')) << endl; // 把从索引位置为3开始的连续5个字符替换成* 30 31 string s3{"cosmos"}, s4{"galaxy"}; 32 cout << "s3: " + s3 + " s4: " + s4 << endl; 33 s3.swap(s4); // 交换 34 cout << "s3: " + s3 + " s4: " + s4 << endl; 35 36 string s5{"abc"}; 37 const char *pstr = s5.c_str(); // 方法c_str()把string类字符串组转换成C风格的字符串 38 cout << pstr << endl; 39 40 string s6{"12306"}; 41 int x1 = stoi(s6); // 把string转换成int 42 cout << x1 << endl; 43 44 int x2 = 12306; 45 string s7 = to_string(x2); // 把int转换成string 46 cout << s7 << endl; 47 48 double x3 = 123.06; 49 string s8 = to_string(x3); // 把double转换成string 50 cout << s8 << endl; 51 }
测试结果截图:
普通数组、array、vector的相关性,以及,区别
共同点
(1)都和数组相似,都可以使用标准数组的表示方法来访问每个元素(array和vector都对下标运算符[ ]进行了重载)
(2)三者的存储都是连续的,可以进行随机访问
不同点
(0)数组是不安全的,array和vector是比较安全的(有效的避免越界等问题)
(1)array对象和数组存储在相同的内存区域(栈)中,vector对象存储在自由存储区(堆)
(2)array可以将一个对象赋值给另一个array对象,但是数组不行
(3)vector属于变长的容器,即可以根据数据的插入和删除重新构造容器容量;但是array和数组属于定长容器
(4)vector和array提供了更好的数据访问机制,即可以使用front()和back()以及at()(at()可以避免a[-1]访问越界的问题)访问方式,使得访问更加安全。而数组只能通过下标访问,在写程序中很容易出现越界的错误
(5)vector和array提供了更好的遍历机制,即有正向迭代器和反向迭代器
(6)vector和array提供了size()和Empty(),而数组只能通过sizeof()/strlen()以及遍历计数来获取大小和是否为空
(7)vector和array提供了两个容器对象的内容交换,即swap()的机制,而数组对于交换只能通过遍历的方式逐个交换元素
(8)array提供了初始化所有成员的方法fill()
(9)由于vector的动态内存变化的机制,在插入和删除时,需要考虑迭代的是否有效问题
(10)vector和array在声明变量后,在声明周期完成后,会自动地释放其所占用的内存。对于数组如果用new[ ]/malloc申请的空间,必须用对应的delete[ ]和free来释放内存
迭代器与指针相关性,以及,区别
关系:
(1)范围——指针属于迭代器的一种(指针可以用来遍历容器[数组])
(2)功能——迭代器有着比指针更细的划分并对应能力不同的功能(重载不同的运算符)
(3)行为——迭代器比指针更统一和良好的用法(更轻易使用begin()和end(),不用担心越界)。
迭代器:
(1)迭代器不是指针,是类模板,表现的像指针。模拟了指针的一些功能,通过重载了指针的一些操作符,->,++ --等封装了指针,是一个“可遍历STL( Standard Template Library)容器内全部或部分元素”的对象, 本质是封装了原生指针,是指针概念的一种提升(lift),提供了比指针更高级的行为,相当于一种智能指针,他可以根据不同类型的数据结构来实现不同的++,–等操作;
(2)迭代器返回的是对象引用,而不是对象的值,cout只能输出迭代器使用 * 取值后的值,不能直接输出自身;
(3)能一次访问容器中的各个元素,通过迭代器,容器和算法可以结合起来,对算法给与不用的迭代器,就可以对不同容器进行相同的操作。
指针:
指针能指向函数,迭代器不行,只能指向容器,指针只能指向某些特定容器。
C风格字符串与string区别
C风格字符串
(1)C风格字符串并不是一种类型,它指的是一种编程习惯,指C语言中以'\0'结尾的字符串。
(2)C语言中没有字符串类型,通常用字符串数组来存放一个字符串;可以直接将一个字符串直接量(字面量)直接赋值给数组(可以定义长度也可以不指定),编译器会在字符数组末尾自动的添加'\0'作为串的结束符。
(3)用字符串给字符数组赋值时由于要添加结束符'\0',因此数组的长度要比字符串的长度大1.
(4)puts和printf在输出字符串时会逐个扫描字符,直到遇见'\0'才结束。
(5)C语言中字符串定义方式有两种:char *s或者char s[],都属于C风格字符串,其区别是char *s定义的字符串直接量保存在内存的数据段中且不可更改,字符数组保存在栈内存中
string类
(1)C++语言中预定义了字符串类(string类),string类提供了对字符串进行处理所需的操作。
(2)string类具有接收const char*类型的构造函数,因此字符串常量和用字符数组·表示的字符串变量都可以隐含地转换为string对象,可以直接使用字符串常量对string对象初始化。
实验任务5
1 #pragma once 2 #include<iostream> 3 #include<iomanip> 4 #include<string> 5 #include<vector> 6 7 using namespace std; 8 9 class Info { 10 public: 11 Info(string nickname0, string contact0, string city0, int n0) : 12 nickname{ nickname0 }, contact{ contact0 }, city{ city0 }, n{ n0 } {} //构造函数 13 14 void print() const; //成员函数,打印信息 15 16 private: 17 string nickname; 18 string contact; 19 string city; 20 int n; 21 }; 22 23 void Info::print() const 24 { 25 cout << "昵称:\t\t" << nickname << endl 26 << "联系方式:\t" << contact << endl 27 << "所在城市:\t" << city << endl 28 << "预订人数:\t" << n << endl; 29 }
1 #include"Info.hpp" 2 #include<iostream> 3 #include<iomanip> 4 #include<string> 5 #include<vector> 6 7 using namespace std; 8 9 10 int main() 11 { 12 const int capacity = 100; 13 int n, i = 0; 14 static int count = 0; 15 string nickname, contact, city; 16 vector<Info>audience_info_list; 17 18 cout << "录入信息:\n\n"; 19 cout << "昵称\t" << "联系方式(邮箱/手机号)\t\t" << "所在城市\t" << "预定参加人数" << endl; 20 21 while (cin >> nickname >> contact >> city >> n) 22 { 23 24 if (capacity - (count + n) >= 0) 25 { 26 Info get(nickname, contact, city, n); 27 audience_info_list.push_back(get); 28 count += n; 29 30 } 31 else if (capacity - (count + n) < 0) 32 { 33 cout << "对不起,只剩" << capacity - count << "个位置。" << endl 34 << "1.输入u,更新(update)预定信息" << endl 35 << "2.输入q,退出预定" << endl 36 << "你的选择:"; 37 string uq; 38 cin >> uq; 39 40 if (uq == "q") 41 break; 42 else if (uq == "u") 43 { 44 cout << "录入信息:" << endl; 45 continue; 46 } 47 } 48 } 49 50 cout << "截至目前,一共有" << count << "位听众预定参加。预定听众信息如下:" << endl; 51 for (auto i=0;i< audience_info_list.size();i++) 52 { 53 audience_info_list.at(i).print(); 54 cout << endl; 55 } 56 }
测试截图:
实验任务6
1 #pragma once 2 #include <iostream> 3 #include <string> 4 5 using namespace std; 6 7 class TextCoder { 8 private: 9 string text; 10 void encoder(); 11 void decoder(); 12 13 public: 14 TextCoder(string text0) : text{ text0 } {} 15 string get_ciphertext() ; 16 string get_deciphertext() ; 17 }; 18 19 void TextCoder::encoder() { 20 for (int i=0;i<text.length();i++) 21 { 22 if (text.at(i) >= 'a' && text.at(i) <= 'u') 23 text.at(i) += 5; 24 else if (text.at(i) >= 'v' && text.at(i) <= 'z') 25 text.at(i) -= 21; 26 else if (text.at(i) >= 'A' && text.at(i) <= 'U') 27 text.at(i) += 5; 28 else if (text.at(i) >= 'V' && text.at(i) <= 'Z') 29 text.at(i) -= 21; 30 31 } 32 } 33 34 void TextCoder::decoder() { 35 for (int i=0;i<text.length();i++) 36 { 37 if (text.at(i) >= 'f' && text.at(i) <= 'z') 38 text.at(i) -= 5; 39 else if (text.at(i) >= 'a' && text.at(i) <= 'e') 40 text.at(i) += 21; 41 else if (text.at(i) >= 'F' && text.at(i) <= 'Z') 42 text.at(i) -= 5; 43 else if (text.at(i) >= 'A' && text.at(i) <= 'E') 44 text.at(i) += 21; 45 46 } 47 } 48 49 string TextCoder::get_ciphertext() { 50 encoder(); 51 return text; 52 } 53 54 string TextCoder::get_deciphertext() { 55 decoder(); 56 return text; 57 }
1 #include "textcoder.hpp" 2 #include <iostream> 3 #include <string> 4 5 void test() { 6 using namespace std; 7 8 string text, encoded_text, decoded_text; 9 10 cout << "输入英文文本: "; 11 while (getline(cin, text)) { 12 encoded_text = TextCoder(text).get_ciphertext(); // 这里使用的是临时无名对象 13 cout << "加密后英文文本:\t" << encoded_text << endl; 14 15 decoded_text = TextCoder(encoded_text).get_deciphertext(); // 这里使用的是临时无名对象 16 cout << "解密后英文文本:\t" << decoded_text << endl; 17 cout << "\n输入英文文本: "; 18 } 19 } 20 21 int main() { 22 test(); 23 }
测试截图: