gpt4 book ai didi

c++ - 阅读多行,但特别是......有效地解析它们

转载 作者:行者123 更新时间:2023-11-30 04:32:14 26 4
gpt4 key购买 nike

我需要阅读开头带有特定关键字的多行。我有一个基本问题,需要帮助。

这里是输入的种类:

keyword1 0.0 0.0
keyword1 1.0 5.0
keyword2 10.0
keyword3 0.5
keyword4 6.0

规则是:

  • 包含 keyword1 和 keyword2 的行应该按此顺序排列并位于任何其他行之前。

  • 包含 keyword3 和 keyword4 的行可以任意顺序

  • keyword1 必须后跟 2 double

  • 关键字 2、3 和 4 必须后跟 1 个双数

  • 在包含所有四个关键字及其 double 的行的末尾,“循环”中断并触发计算。

这是我的来源:

using namespace std;

int main (int argc, const char * argv[]) {
vector<double> arrayInputs;
string line;
double keyword1_first, keyword1_second, keyword4,
keyword3, keyword2;
bool inside_keyword1=false, after_keyword2=false,
keyword4_defined=false, keyword3_defined=false ;

//cin.ignore();

while (getline(cin, line)) {
if (inside_keyword1 && after_keyword2 && keyword3 && keyword4) {
break;
}
else
{
std::istringstream split(line);
std::vector<std::string> tokens;
char split_char = ' ';
for (std::string each; std::getline(split, each, split_char); tokens.push_back(each));

if (tokens.size() > 2)
{
if (tokens[0] != "keyword1") return EXIT_FAILURE; // input format error
else
{
keyword1_first = atof(tokens[1].c_str());
keyword1_second = atof(tokens[2].c_str());

inside_keyword1 = true;
}
}
else
{
if (tokens[0] == "keyword2")
{
if (inside_keyword1)
{
keyword2 = atof(tokens[1].c_str());
after_keyword2 = true;
}

else return EXIT_FAILURE; // cannot define anything else keyword2 after keyword1 definition

}
else if (tokens[0] == "keyword3")
{
if (inside_keyword1 && after_keyword2)
{
keyword3 = atof(tokens[1].c_str());
keyword3_defined = true;
}
else return EXIT_FAILURE; // cannot define keyword3 outside a keyword1
}
else if (tokens[0] == "keyword4")
{
if (inside_keyword1 && after_keyword2)
{
keyword4 = atof(tokens[1].c_str());
keyword4_defined = true;
}
else return EXIT_FAILURE; // cannot define keyword4 outside a keyword1
}
}
}
}

// Calculation


// output


return EXIT_SUCCESS;
}

我的问题是:除了在读取/解析循环中使用 bool 值之外,还有更有效的方法吗?

最佳答案

您问的是“更高效”的东西,但您似乎没有特定的性能目标。所以你在这里想要的可能更像是代码审查。有一个网站,特别是:

https://codereview.stackexchange.com/

但是无论如何...

您的直觉是正确的,这里并不是真正需要四个 bool 值。那是 2^4 = 16 种不同的“状态”,其中许多是您永远无法到达的。 (例如,您的规范明确禁止在 keyword3_defined == true 时使用 after_keyword1 == false)。

当然,程序状态可以保存在枚举和 bool 值中。这使得“健忘”循环有可能在不同情况下重新访问一行代码,但仍然记得它处于处理的哪个阶段。它在许多情况下都很有用,包括在复杂的解析器中。但是,如果您的任务是线性且简单的,则最好隐式地“了解”基于已到达特定代码行的状态。

作为展示我正在谈论的对比的教育示例,这是一个愚蠢的状态机,可以在一封信中阅读 A后跟任意数量的字母 B小号:

enum State {
beforeReadingAnA,
haveReadAnA,
readingSomeBs,
doneReadingSomeBs
};

State s = beforeReadingAnA;
char c;
while(true) {
switch (s) {
case beforeReadingAnA:
cin >> c;
if (cin.good() && c == 'A') {
// good! accept and state transition to start reading Bs...
s = haveReadAnA;
} else {
// ERROR: expected an A
return EXIT_CODE_FAILURE;
};
break;

case haveReadAnA:
// We've read an A, so state transition into reading Bs
s = readingSomeBs;
break;

case readingSomeBs:
cin >> c;
if (cin.good() && c == 'B') {
// good! stay in the readingSomeBs state
} else if (cin.eof()) {
// reached the end of the input after 0 or more Bs
s = doneReadingSomeBs;
} else {
// ERROR: expected a B or the EOF
return EXIT_CODE_FAILURE;
}
break;

case doneReadingSomeBs:
// all done!
return EXIT_CODE_SUCCESS;
}
}

如前所述,这是一种非常非常有用的风格编码。然而,对于这种情况,这是荒谬的。与执行相同操作的简单线性代码进行比较:

// beforeReadingAnA is IMPLICIT

char c;
cin >> c;
if (cin.fail() || c != 'A')
return EXIT_CODE_FAILURE;

// haveReadAnA is IMPLICIT

do {
// readingSomeBs is IMPLICIT

cin >> c;
if (cin.eof())
return EXIT_CODE_SUCCESS;
if (cin.fail() || c != 'B')
return EXIT_CODE_FAILURE;
}

// doneReadingSomeBs is IMPLICIT

所有的状态变量都消失了。它们是不必要的,因为程序只是“知道它在哪里”。如果您重新考虑您的示例,那么您可能也可以这样做。您不需要四个 bool 值,因为您可以将光标放在一行代码上,然后自信地说出如果该行代码恰好在运行,这四个 bool 值必须是。 p>

就效率而言,<iostream>类可以让生活比你在这里更轻松,并且更符合 C++ 的习惯,而无需调用像 atof 这样的 C 主义。或者不得不使用 c_str() .让我们看一下您的代码的简化摘录,它只读取与“keyword1”关联的 double 值。

string line;
getline(cin, line);
istringstream split(line);
vector<string> tokens;
char split_char = ' ';
string each;
while (getline(split, each, split_char)) {
tokens.push_back(each);
}
double keyword1_first, keyword1_second;
if (tokens.size() > 2) {
if (tokens[0] != "keyword1") {
return EXIT_FAILURE; // input format error
} else {
keyword1_first = atof(tokens[1].c_str());
keyword1_second = atof(tokens[2].c_str());
}
}

对比一下:

string keyword;
cin >> keyword;
if (keyword != "keyword1") {
return EXIT_FAILURE;
}
double keyword1_first, keyword1_second;
cin >> keyword1_first >> keyword1_second;

魔法。 Iostreams 可以检测您尝试读取或写入的类型。如果它在按照您要求的方式解释输入时遇到问题,那么它会将输入保留在缓冲区中,以便您可以尝试以另一种方式读取它。 (在请求字符串的情况下,行为是读取一系列字符直到空格...如果您真的想要整行,您可以像以前那样使用 getline。)

但是,错误处理是您必须处理的事情。可以告诉 iostreams 使用异常处理方法,以便遇到问题(例如在预期为 double 的地方的随机词)的标准响应将是使您的程序崩溃。但是默认是设置一个你需要测试的失败标志:

cin erratic behaviour

iostream 有细微差别,所以您可能想做一些问答调查...我最近在此处回答/提问时自己也学到了一些东西:

Output error when input isn't a number. C++

When to use printf/scanf vs cout/cin?

关于c++ - 阅读多行,但特别是......有效地解析它们,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7784200/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com