#include <iostream> #include <vector> #include <fstream> #include <iomanip> #include <map>
时间: 2024-07-03 18:01:14 浏览: 15
`#include <iostream>` 引入了输入/输出流库,这是C++中用于标准输入输出操作的基本库,例如 `std::cout` 和 `std::cin`。
`#include <vector>` 引入了动态数组容器(vector),它是C++标准模板库(STL)的一部分,提供了动态大小的数组功能,可以方便地存储和操作一系列元素。
`#include <fstream>` 包含了文件输入输出流库,允许程序读写文件。
`#include <iomanip>` 是格式化输入输出流库,提供了格式化输出(如左对齐、右对齐、设置精度等)的功能。
`#include <map>` 引入关联容器(map),这是一种键值对的数据结构,类似于字典或哈希表,通过键查找对应的值。
相关问题
优化这段代码#include <iostream> #include <iomanip> #include <stdio.h> #include <fstream> #include <string> #include <algorithm> #include <unordered_map> #include <map> #include <stack> #include <set> #include <vector> using namespace std; struct Production { char left; // 产生式的左部非终结符 string right; // 产生式的右部字符串 }; map<char, set<char>> firstSets; int main() { vector<Production> productions; ifstream infile("grammar.txt"); char left; string right; while (infile >> left >> right) { productions.push_back({ left, right }); } for (auto p : productions) { char left = p.left; string right = p.right; char firstChar = right[0]; if (isupper(firstChar)) { // 如果是非终结符 // 计算非终结符的first集合 set<char> firstSet = firstSets[firstChar]; for (int i = 0; i < right.length(); i++) { char ch = right[i]; if (isupper(ch)) { // 如果是非终结符 firstSet.insert(firstSets[ch].begin(), firstSets[ch].end()); if (firstSets[ch].find('$') == firstSets[ch].end()) { // 如果该非终结符没有空串 break; } } else { // 如果是终结符 firstSet.insert(ch); break; } } firstSets[left].insert(firstSet.begin(), firstSet.end()); } else { // 如果是终结符 firstSets[left].insert(firstChar); } } for (auto p : productions) { char left = p.left; cout << "First(" << left << ") = {"; for (auto ch : firstSets[left]) { cout << ch << ", "; } cout << "}" << endl; } }使得能正确求出frist集
以下是优化后的代码:
```c++
#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
#include <vector>
#include <map>
#include <set>
using namespace std;
// 产生式结构体
struct Production {
char left; // 产生式的左部非终结符
string right; // 产生式的右部字符串
};
// 计算first集合
set<char> calcFirstSet(char ch, const vector<Production>& productions, map<char, set<char>>& firstSets) {
// 如果该字符已经计算过first集合,直接返回
if (firstSets.find(ch) != firstSets.end()) {
return firstSets[ch];
}
set<char> result;
// 遍历所有产生式,查找该字符作为左部的产生式
for (auto p : productions) {
if (p.left == ch) {
// 如果右部第一个字符是终结符,则加入该字符
if (!isupper(p.right[0])) {
result.insert(p.right[0]);
}
// 如果右部第一个字符是非终结符,则计算该非终结符的first集合
else {
set<char> subResult = calcFirstSet(p.right[0], productions, firstSets);
result.insert(subResult.begin(), subResult.end());
// 如果该非终结符的first集合中包含空串,则计算下一个字符的first集合
for (int i = 1; i < p.right.length() && subResult.find('$') != subResult.end(); i++) {
if (!isupper(p.right[i])) {
result.insert(p.right[i]);
break;
} else {
subResult = calcFirstSet(p.right[i], productions, firstSets);
result.insert(subResult.begin(), subResult.end());
}
}
}
}
}
// 将计算得到的first集合插入到map中
firstSets.insert(make_pair(ch, result));
return result;
}
int main() {
vector<Production> productions;
ifstream infile("grammar.txt");
// 读取产生式
char left;
string right;
while (infile >> left >> right) {
productions.push_back({ left, right });
}
map<char, set<char>> firstSets;
// 计算每个非终结符的first集合
for (auto p : productions) {
if (isupper(p.right[0])) {
set<char> result = calcFirstSet(p.left, productions, firstSets);
firstSets.insert(make_pair(p.left, result));
} else {
firstSets.insert(make_pair(p.left, set<char>{p.right[0]}));
}
}
// 输出每个非终结符的first集合
for (auto p : productions) {
char left = p.left;
cout << "First(" << left << ") = {";
for (auto ch : firstSets[left]) {
cout << ch << ", ";
}
cout << "}" << endl;
}
}
```
优化后的代码主要是将计算first集合的部分提取出来,封装成了一个函数`calcFirstSet`。在计算每个非终结符的first集合时,只需调用该函数进行计算即可。同时,在计算非终结符的first集合时,使用了递归的方式,可以很方便地计算出包含空串的情况。
#include<bits/stdc++.h> 每一句的含义
`#include<bits/stdc++.h>` 是一个常用的 C++ 头文件引入语句,它包含了 C++ 标准库中的所有头文件。这样一来,我们就不需要单独引入每个标准库头文件,而可以直接使用它们。
具体来说,`#include` 是 C++ 中的预处理指令,用于引入头文件。`<bits/stdc++.h>` 是一个特殊的头文件,它实际上包含了以下常用的 C++ 头文件:
- `<iostream>`:用于输入输出操作。
- `<iomanip>`:用于流控制和格式化输出。
- `<fstream>`:用于文件输入输出。
- `<cstdio>`:用于 C 风格的输入输出。
- `<cstdlib>`:用于常用的函数和类型转换。
- `<cmath>`:用于数学运算。
- `<algorithm>`:用于算法操作。
- `<vector>`:用于向量容器。
- `<list>`:用于链表容器。
- `<queue>`:用于队列容器。
- `<stack>`:用于栈容器。
- `<set>`:用于集合容器。
- `<map>`:用于映射容器等。
通过包含这个头文件,我们可以直接使用这些头文件中定义的函数、类和常量等,而不需要逐个引入每个头文件。
需要注意的是,`#include<bits/stdc++.h>` 这种写法在一些编译器中支持,但并不是标准的 C++ 写法。它主要在竞赛编程中使用,方便快速引入常用的标准库头文件。在实际的开发中,建议根据需要引入具体的头文件,以减少编译时间和避免不必要的命名空间冲突。
相关推荐
![pdf](https://img-home.csdnimg.cn/images/20210720083512.png)
![doc](https://img-home.csdnimg.cn/images/20210720083327.png)
![pdf](https://img-home.csdnimg.cn/images/20210720083512.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![doc](https://img-home.csdnimg.cn/images/20210720083327.png)
![mp4](https://img-home.csdnimg.cn/images/20210720083504.png)
![docx](https://img-home.csdnimg.cn/images/20210720083331.png)