如何从文本文件 until/after 特定位置读取输入 [C++]?
How to read input from the text file until/after a specific location [C++]?
在我的项目中,我需要从文本文件中获取有关电路的数据,然后我需要解析它并生成输出数据。
这是文本文件的示例数据
AND1 Adder1-3 Adder1-4 // Means AND1 gate gets its first input from
Adder1's 3rd output and its second input from Adder1's 4th output
AND2 Adder1-4 Adder1-2
OR1 AND1-1 AND2-1 //OR1's two inputs are from AND1's 1st output and
AND2's 1st output
现在我需要先读取组件名称,这很简单:
infile>>componentName;
但是对于第二部分,我虽然可以通过多种方式解决这个问题
- 读取整个数据并将其分成两部分:ComponentName -
thOutput.
- 读到“-”放入字符串变量再读
在“-”之后并将其放入整数变量并为所有重复此操作
行。
我尝试了第一种方法,但我真的坚持将字符串转换为整数(我尝试使用 stoi 但它仅适用于 C++ :( 并且还遇到了几个问题)但我虽然第二种方法会更容易但是我不知道该怎么做。
那你能帮我解决这个问题吗?
基本上我需要将组件名称(“-”之前)放入字符串变量并将整数(“-”之后)放入整数变量。
注意:抱歉我的英语很差,不是母语人士。由于项目很大,我没有在上面放置不必要的代码。
这是相当基础的,但应该可以帮助您入门。我更喜欢 scanf
家庭来完成这些任务。
#include <stdio.h>
#include <iostream>
using namespace std;
int main() {
FILE *fp=fopen("tmpfile", "r");
char oper[5], dev1[10], dev2[10];
int op1, op2;
fscanf(fp, "%s %[^-]-%d %[^-]-%d", oper, dev1, &op1, dev2, &op2);
cout<<oper<<endl;
cout<<dev1<<endl;
cout<<op1<<endl;
cout<<dev1<<endl;
cout<<op2<<endl;
fclose(fp);
}
为 AND2 Adder1-4 Adder1-2
生成的输出:
AND2
Adder1
4
Adder1
2
您可以使用 Boost.Spirit 来完成此解析任务。它允许您将结果直接解析为结构。
#include <iostream>
#include <sstream>
#include <string>
#include <boost/fusion/adapted.hpp>
#include <boost/spirit/home/x3.hpp>
struct Entry
{
std::string op;
std::string dev1;
int n1;
std::string dev2;
int n2;
};
BOOST_FUSION_ADAPT_STRUCT(
Entry,
op,
dev1, n1,
dev2, n2)
Entry parse(std::string const &input)
{
auto iter = input.begin();
using namespace boost::spirit::x3;
auto op = rule<class op, std::string>{}
= lexeme[upper >> *(upper | digit)];
auto dev = rule<class dev, std::string>{}
= lexeme[upper >> *alnum];
Entry result;
bool r = phrase_parse(iter, input.end(),
op > dev > lit('-') > int_ > dev > lit('-') > int_,
space, result);
if (!r)
{
std::string rest(iter, input.end());
throw std::invalid_argument("Parsing failed at " + rest);
}
return result;
}
int main()
{
// This could be a file instead with std::ifstream
std::istringstream input;
input.str(
"AND1 Adder1-3 Adder1-4 // Means AND1 gate gets its first input from Adder1's 3rd output and its second input from Adder1's 4th output\n"
"AND2 Adder1-4 Adder1-2\n"
"OR1 AND1-1 AND2-1 //OR1's two inputs are from AND1's 1st output and AND2's 1st output\n");
for (std::string line; std::getline(input, line); )
{
Entry e = parse(line);
std::cout << "Found the following entries:\n"
<< " Operation: " << e.op << "\n"
<< " Device 1: " << e.dev1 << "-" << e.n1 << "\n"
<< " Device 2: " << e.dev2 << "-" << e.n2 << "\n";
}
}
在我的项目中,我需要从文本文件中获取有关电路的数据,然后我需要解析它并生成输出数据。 这是文本文件的示例数据
AND1 Adder1-3 Adder1-4 // Means AND1 gate gets its first input from Adder1's 3rd output and its second input from Adder1's 4th output
AND2 Adder1-4 Adder1-2
OR1 AND1-1 AND2-1 //OR1's two inputs are from AND1's 1st output and AND2's 1st output
现在我需要先读取组件名称,这很简单:
infile>>componentName;
但是对于第二部分,我虽然可以通过多种方式解决这个问题
- 读取整个数据并将其分成两部分:ComponentName - thOutput.
- 读到“-”放入字符串变量再读 在“-”之后并将其放入整数变量并为所有重复此操作 行。
我尝试了第一种方法,但我真的坚持将字符串转换为整数(我尝试使用 stoi 但它仅适用于 C++ :( 并且还遇到了几个问题)但我虽然第二种方法会更容易但是我不知道该怎么做。
那你能帮我解决这个问题吗? 基本上我需要将组件名称(“-”之前)放入字符串变量并将整数(“-”之后)放入整数变量。
注意:抱歉我的英语很差,不是母语人士。由于项目很大,我没有在上面放置不必要的代码。
这是相当基础的,但应该可以帮助您入门。我更喜欢 scanf
家庭来完成这些任务。
#include <stdio.h>
#include <iostream>
using namespace std;
int main() {
FILE *fp=fopen("tmpfile", "r");
char oper[5], dev1[10], dev2[10];
int op1, op2;
fscanf(fp, "%s %[^-]-%d %[^-]-%d", oper, dev1, &op1, dev2, &op2);
cout<<oper<<endl;
cout<<dev1<<endl;
cout<<op1<<endl;
cout<<dev1<<endl;
cout<<op2<<endl;
fclose(fp);
}
为 AND2 Adder1-4 Adder1-2
生成的输出:
AND2
Adder1
4
Adder1
2
您可以使用 Boost.Spirit 来完成此解析任务。它允许您将结果直接解析为结构。
#include <iostream>
#include <sstream>
#include <string>
#include <boost/fusion/adapted.hpp>
#include <boost/spirit/home/x3.hpp>
struct Entry
{
std::string op;
std::string dev1;
int n1;
std::string dev2;
int n2;
};
BOOST_FUSION_ADAPT_STRUCT(
Entry,
op,
dev1, n1,
dev2, n2)
Entry parse(std::string const &input)
{
auto iter = input.begin();
using namespace boost::spirit::x3;
auto op = rule<class op, std::string>{}
= lexeme[upper >> *(upper | digit)];
auto dev = rule<class dev, std::string>{}
= lexeme[upper >> *alnum];
Entry result;
bool r = phrase_parse(iter, input.end(),
op > dev > lit('-') > int_ > dev > lit('-') > int_,
space, result);
if (!r)
{
std::string rest(iter, input.end());
throw std::invalid_argument("Parsing failed at " + rest);
}
return result;
}
int main()
{
// This could be a file instead with std::ifstream
std::istringstream input;
input.str(
"AND1 Adder1-3 Adder1-4 // Means AND1 gate gets its first input from Adder1's 3rd output and its second input from Adder1's 4th output\n"
"AND2 Adder1-4 Adder1-2\n"
"OR1 AND1-1 AND2-1 //OR1's two inputs are from AND1's 1st output and AND2's 1st output\n");
for (std::string line; std::getline(input, line); )
{
Entry e = parse(line);
std::cout << "Found the following entries:\n"
<< " Operation: " << e.op << "\n"
<< " Device 1: " << e.dev1 << "-" << e.n1 << "\n"
<< " Device 2: " << e.dev2 << "-" << e.n2 << "\n";
}
}