C++字符串、向量和数组2-- 标准库类型vector

本文深入探讨C++标准库中的vector容器,介绍其定义、初始化方式,包括列表初始化和指定元素数量的初始化。同时,文章讲解如何使用push_back方法添加元素,以及vector的常用操作如empty、size、下标访问等。

   标准库vector表示对象的集合,其中所有对象的类型都相同。集合中的每个对象都有一个与之对应的索引,索引用于访问对象,vector也叫容器。
   C++既有类模板,也有函数模板,vector属于类模板。对于类模板来说,我们通过提供一些额外信息来指定模板到底实例化成什么样的类。以vector为例,提供的额外信息是vector内所存放对象的类型:

vector<int> ivec;         //ivec保存int类型的对象
vector<Person> pvec;      //保存Person类型的对象
vector<vector<string>>;  //该向量的元素是vector类型

   vector能容纳绝大部分对象作为其元素,但是因为引用不是对象,所以不存在包含引用的vector。需要指出的是,在早期版本的C++标准中,如果vector的元素还是vector,则其定义形式与现在的C++11新版本略有不同。过去,必须在外层vector对象的右尖括号和其元素之间添加一个空格,比如vector<vector>应该写成vector<vector >。

1.定义和初始化vector

   下面列出来常用的定义vector的方法:

定义描述
vector v1v1是个空的vector,它的元素是T类型,执行默认初始化
vector v2(v1)v2中包含v1所有元素的副本
vector v2=v1等价于v2(v1)
vector v3(n,val)v3中包含了n个元素,每个元素的值都是val
vector v4(n)v4包含了n个重复地执行了初始化的对象
vector v5{a,b,c…}v5包含了初始个数的元素,每个元素被赋予相应的初始值
vector v5={a,b,c…}等价于v5{a,b,c…}

列表初始化vector
   C++新标准还提供了另外一种为vector初始化的方法,即列表初始化。此时,用花括号扩起来的0个或多个初始元素值被赋给vector对象,比如v5。如果提供的是初始值列表,则只能把初始值都放在花括号里进行列表初始化,而不能放在圆括号里。

创建指定数量的元素
   还可以用vector对象容纳的元素数量和所有元素的统一初始值来初始化vector对象,比如v3。

列表初始值还是元素数量
   在某些情况下,初始化的真实含义依赖于传递初始值时用的是花括号还是圆括号。如果是圆括号,可以说提供的值是用来构造vector对象的。如果是花括号,可以表述成我们想要列表初始化该vector对象:

vector<int> v1(10);   //v1有10个元素,每个元素的值都是0
vector<int> v2{10};   //v1有1个元素,该元素的值是10
vector<int> v3(10,1); //v3有10个元素,每个元素的值是1
vector<int> v4{10,1}  //v4有2个元素,值分别是10和1

   另一方面,如果初始时使用了花括号的形式但是提供的值又不能用来列表初始化,就要考虑用这样的值来构造vector对象了:

vector<string> v5{"hi"};  //列表初始化:v5有一个元素,其值是"hi"
vector<string> v6("hi");  //错误,不能使用字符串字面值构建vector对象
vector<string> v7{10};    //因为10无法初始化string对象,所以花括号初始化变成了圆括号初始化,v7有10个默认初始化的元素
vector<string> v8{10, "hi"}; //同v7,10不能初始化string对象,v8有10个值为"hi"的元素

2.向vector对象中添加元素

   vector提供了push_back方法用于把一个值当成vector对象的尾元素“压到”vector对象的“尾端”:

vector<int> v;                    //空vector对象
for(auto i=0; i!=100; ++i)
{
	v.push_back(i);           //依次把整数值放到v的尾端
}//循环结束后v有100个元素,值从0到99

需要注意,如果循环体内包含有向vector对象添加元素的语句,则不能使用范围for循环。

3.其他vector操作

操作描述
v.empty()判断v是否为空
v.size()返回v中元素的个数
v.push_back(t)向v的尾端添加一个值为t的元素
v.[n]返回v中第n个位置上元素的引用
v1=v2用v2中的元素拷贝替换v1中的元素
v1 = {a,b,c…]用列表中的元素拷贝替换v1中的元素
v1==v2当v1和v2元素数量相同并且对应位置的元素值相同是返回true,否则返回false
v1!=v2当v1和v2元素数量相同并且对应位置的元素值相同是返回true,否则返回false
<,=,>,>=以字典顺序进行比较

   vector对象的下标运算符可用于访问已存在的元素,而不能用于添加元素。试图用下标的形式去访问一个不存在的元素将引发错误,不过这错误不会被编译器发现,而是在运行时产生一个不可预知的值,所谓缓冲区溢出指的就是这类错误。这也是导致PC及其它设备上应用程序出现安全问题的一个原因。

<think> 根据用户的问题,用户需要了解C++字符串二维数的输入输出方法。结合引用内容,我注意到引用[1]和引用[3]提供了相关的方法。特别是引用[3]中有一个示例函数`stringToIntegerMatrix1`,它处理的是整数二维数,但我们可以借鉴其思路来处理字符串二维数。 用户要求的是字符串二维数,所以需要存储的是`string`类型。我们可以考虑以下情况: 1. 输入格式:用户可能以不同的格式输入,比如每行一个字符串,用空格分隔,然后多行输入;或者输入一个类似`[[str1,str2],[str3,str4]]`的格式(如引用[3]中的整数矩阵输入)。 2. 输出格式:相应地输出二维字符串。 但是,用户并没有指定输入格式,所以我们需要提供常见的几种输入方式。 根据引用[1]中的内容,有几种输入方式: - 输入多个字符串,每个串之间以空格作为结束;最终结束是回车(即一行字符串,空格分隔,回车结束一行,然后可以有多行) - 输入不定矩阵,以回车结尾(即行数不定,每行字符串数也不定?) 另外,引用[3]提供了一种解析特定格式字符串的方法(例如`[[1,2,3],[4,5,6]]`),我们可以将其扩展到字符串。 因此,我将提供两种常见情况的示例: 情况1:逐行输入,每行由空格分隔的多个字符串成,直到遇到空行或结束标志。 情况2:输入一个类似`[["str1","str2"],["str3","str4"]]`的字符串,然后解析成二维字符串。 同时,输出时,我们可以按照行输出,每行内的字符串用空格分隔,或者按照类似二维数的格式输出。 由于用户要求输入输出方法,我将分别给出输入和输出的代码示例。 注意:在C++中,字符串二维数通常用`vector<vector<string>>`来表示,这样更灵活。 方案1:逐行输入,每行用空格分隔多个字符串,直到输入空行(或指定行数) 方案2:解析特定格式的字符串(如JSON格式,但这里简化处理) 下面分别给出两种方案的代码: 方案1:逐行输入,直到遇到空行(或者也可以指定行数) 输入示例: hello world this is a test (然后输入一个空行结束) 代码: ```cpp #include <iostream> #include <vector> #include <string> #include <sstream> using namespace std; int main() { vector<vector<string>> str2DArray; string line; cout << "请输入字符串矩阵,每行用空格分隔多个字符串,空行结束:" << endl; while (getline(cin, line)) { if (line.empty()) // 空行结束输入 break; vector<string> row; stringstream ss(line); string word; while (ss >> word) { row.push_back(word); } str2DArray.push_back(row); } // 输出二维字符串 cout << "输出结果:" << endl; for (const auto& row : str2DArray) { for (const auto& s : row) { cout << s << " "; } cout << endl; } return 0; } ``` 方案2:解析特定格式的字符串,如`[["str1","str2"],["str3","str4"]]`。注意,这个解析相对复杂,因为字符串中可能包含逗号、空格等。我们假设输入的字符串格式是标准的,每个字符串用双引号括起来,且字符串内不包含双引号和逗号(或者我们可以用转义,但这里简化处理)。 我们参考引用[3]中的整数矩阵解析方法,修改为处理字符串。 输入示例:`[["hello","world"],["this","is","a","test"]]` 代码: ```cpp #include <iostream> #include <vector> #include <string> #include <sstream> #include <cctype> using namespace std; vector<vector<string>> parseStringMatrix(string input) { vector<vector<string>> matrix; // 去除输入字符串首尾的方括号 if (input.front() == '[') input = input.substr(1, input.size()-2); else return matrix; vector<string> row; string token; bool inQuotes = false; bool inBracket = false; // 是否在行向量中(即[ ... ]内部) for (size_t i=0; i<input.size(); ) { if (input[i]=='[') { inBracket = true; row.clear(); i++; } else if (input[i]==']') { inBracket = false; // 将当前行加入矩阵 matrix.push_back(row); row.clear(); // 跳过逗号和可能的空格 i++; while (i<input.size() && (input[i]==',' || input[i]==' ')) i++; } else if (inBracket && input[i]=='"') { // 开始一个字符串 inQuotes = true; token = ""; i++; while (i<input.size() && inQuotes) { if (input[i]=='\\') { // 转义字符 if (i+1 < input.size()) { token += input[i+1]; i += 2; } } else if (input[i]=='"') { inQuotes = false; i++; } else { token += input[i]; i++; } } // 将token加入当前行 row.push_back(token); // 跳过逗号和空格 while (i<input.size() && (input[i]==',' || input[i]==' ')) i++; } else { i++; // 其他情况,跳过(比如空格等) } } return matrix; } int main() { string input; cout << "请输入格式为[[\"str1\",\"str2\"],[\"str3\"]]的字符串:" << endl; getline(cin, input); vector<vector<string>> matrix = parseStringMatrix(input); // 输出 cout << "解析后的二维字符串:" << endl; for (const auto& row : matrix) { for (const auto& s : row) { cout << s << " "; } cout << endl; } return 0; } ``` 注意:方案2的解析器是一个简化版本,它假设输入的格式是严格正确的。实际应用中可能需要更健壮的解析,比如处理转义字符、错误格式等。 另外,引用[1]中还提到了其他输入方式,比如输入单字符串、多个字符串等,但用户特别关注二维数,所以我们重点在二维数的输入输出。 总结:在C++中,处理字符串二维数的输入输出,通常使用`vector<vector<string>>`来存储。输入方式可以根据实际需要选择逐行读取空格分隔的字符串,或者解析特定格式的字符串。 根据用户的问题,我提供了两种常见的方法。用户可以根据自己的输入格式选择合适的方法。 注意:在方案2中,我们假设字符串是用双引号括起来的。如果输入中没有双引号,而是用单引号或者没有引号,则需要调整解析逻辑。 最后,我们也可以使用现有的库(如JSON库)来解析复杂的格式,但这里为了简单,我们自行解析。 如果用户需要更详细的信息,可以参考引用[1]和引用[3]中的方法。 希望这些方法能够帮助用户解决问题。 </think>### C++字符串二维数的输入输出方法 在C++中处理字符串二维数的输入输出需要根据不同的数据格式灵活实现。以下是常见的三种实现方式,涵盖不同输入场景: #### 1. **逐行输入空格分隔的字符串(动态行数列数)** ```cpp #include <iostream> #include <vector> #include <string> #include <sstream> using namespace std; int main() { vector<vector<string>> str2D; string line; // 输入:每行多个空格分隔的字符串,空行结束 cout << "输入字符串矩阵(空格分隔,空行结束):\n"; while (getline(cin, line) && !line.empty()) { vector<string> row; stringstream ss(line); string word; while (ss >> word) { row.push_back(word); } str2D.push_back(row); } // 输出二维数 cout << "输出结果:\n"; for (auto &row : str2D) { for (auto &s : row) { cout << s << " "; } cout << "\n"; } return 0; } ``` **输入示例**: ``` hello world cpp 2d array [空行] ``` **输出**: ``` hello world cpp 2d array ``` #### 2. **解析JSON格式的字符串矩阵(如`[["a","b"],["c"]]`)** ```cpp #include <iostream> #include <vector> #include <string> using namespace std; vector<vector<string>> parseStringMatrix(string input) { vector<vector<string>> matrix; vector<string> row; string token; bool inString = false; bool inVector = false; for (char c : input) { if (c == '[') { if (inVector) row.clear(); inVector = true; } else if (c == ']') { if (!token.empty()) { row.push_back(token); token = ""; } if (inVector && !row.empty()) { matrix.push_back(row); row.clear(); } inVector = false; } else if (c == '\"') { inString = !inString; if (!inString && !token.empty()) { row.push_back(token); token = ""; } } else if (inString) { token += c; } } return matrix; } int main() { string input = R"([["Hello","World"],["C++","2D","Array"]])"; auto matrix = parseStringMatrix(input); // 输出结果 for (auto &row : matrix) { for (auto &s : row) { cout << s << " "; } cout << "\n"; } return 0; } ``` **输出**: ``` Hello World C++ 2D Array ``` #### 3. **固定行数的逗号分隔输入** ```cpp #include <iostream> #include <vector> #include <string> #include <sstream> using namespace std; int main() { int rows; cout << "输入行数: "; cin >> rows; cin.ignore(); // 清除换行符 vector<vector<string>> str2D(rows); for (int i = 0; i < rows; ++i) { string line; cout << "输入第" << i+1 << "行(逗号分隔): "; getline(cin, line); stringstream ss(line); string cell; while (getline(ss, cell, ',')) { str2D[i].push_back(cell); } } // 输出 for (auto &row : str2D) { for (int j = 0; j < row.size(); ++j) { cout << row[j]; if (j < row.size()-1) cout << ", "; } cout << "\n"; } return 0; } ``` **输入示例**: ``` 3 apple,banana C++,Python,Java one,two,three ``` **输出**: ``` apple, banana C++, Python, Java one, two, three ``` ### 关键点说明 1. **输入处理**: - 使用`getline()`读取整行避免空格截断[^1] - 通过`stringstream`分割单词/逗号分隔值 - 引号处理需手动解析字符串边界 2. **数据结构**: - 推荐`vector<vector<string>>`动态存储 - 每行可以是不同长度的字符串[^4] 3. **特殊格式**: - JSON格式需处理`[ ] , " `等符号边界 - 引号内内容需完整保留(含空格)[^3] 4. **输出控制**: - 内层循环输出每行元素 - 分隔符保持与输入一致 > 提示:实际应用时需根据输入格式选择对应方案,对带空格的字符串建议用双引号包裹保证完整性[^1][^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值