【问题标题】:How can I compare the next character which the file contains?如何比较文件包含的下一个字符?
【发布时间】:2020-02-28 03:00:51
【问题描述】:

我在阅读代码时遇到了一些问题。这是文本文件。

2X^6+3X^3+4X^0=0
5X^6+X^2+X^1-4X^0=0

我得到了第一行的正确输入,但在第二行首先我需要忽略。我在这里搜索并找到了如何使用它,它可以忽略第一行的所有剩余字符而进入下一行。

你可以在第二行看到 X 没有整数,现在问题是第二个 while 循环连续运行。如果我在带有 X 的文本文件中添加 1 ,则文件会完美读取。另外我如何设置一个条件来满足这一点,即当直接存在 X-X 时,它应该存储 1- 1 并转到下一个字符?您还可以看到 ^ 我必须将它存储在一个变量中,而我应该忽略它但没有如何忽略它?

提前致谢

int main()
{
int in;
int power;
char x;
char f;
fstream fin;
fin.open("input1.txt");
list l1,l2;

while(fin.peek() != 61)
{
        fin>>in;
        fin>>x;
        fin>>f;
        fin>>power;
        cout<<in<<endl<<x<<endl<<f<<endl<<power<<endl;
        l1.addtoend(in,power,x);
        cout<<endl;
}
fin.ignore(2,'\n');

while(fin.peek() != 61)
{
        fin>>in;
        fin>>x;
        fin>>f;
        fin>>power;
        cout<<in<<endl<<x<<endl<<f<<endl<<power<<endl;
        l2.addtoend(in,power,x);
        cout<<endl;
}
l1.display();
l2.display();
}

【问题讨论】:

  • 将整行作为字符串读入并解析字符串,将其分解为各个组件。不应该这样做。
  • @PaulMcKenzle 我知道这样,但需要很多条件才能获得正确的输入。
  • 我知道这种方式 -- 那就是这样做的方式。 -- 但它需要很多条件才能获得正确的输入 -- 哈哈。这正是你最终要做的——这就是任务的本质。标记化,使用正则表达式,解析等。这就是这一切的工作原理。您期望输入例程来解析您的字符串——同样,它几乎从未以这种方式完成。

标签: c++ dev-c++


【解决方案1】:

不幸的是,这并不像预期的那么简单。

我们需要将任务分成更小的部分。

您想要做的是拆分方程并从中提取系数和指数。

将某些内容拆分为相似的部分也称为标记化。

因此,您的等式由项组成,它们都遵循相同的模式。首先是可选符号,然后是系数,然后是“X^”,最后是指数(可能有符号也可能没有符号)。

由于所有术语都有相同的模式,我们可以使用所谓的正则表达式找到它们。 C++ 支持此功能。此外,为了将文本拆分为较小的标记/术语/模式匹配,我们有一个特殊的迭代器 std::sregex_token_iterator。与 C++ 中的任何其他迭代器一样,它迭代源字符串并提取(和复制)所有匹配的模式。

好的,那么我们已经找到了第一个子任务的解决方案。提取所有术语并将它们放入std::vector。我们将使用std::vectors 范围构造函数来执行此操作,同时定义变量。

下一步是获取系数。在这里我们需要一些特殊的处理,因为假设 1 可以省略系数。使用这个假设,我们将读取该术语并将系数转换为整数。因为我们想在一个语句中做到这一点,所以我们使用 STL 算法库中的std::transform

获取指数更容易。我们只需将“^”符号后面的术语中的任何内容转换为整数。我们再次使用std::transform 在一份声明中处理所有条款。

最后但同样重要的是,我们将得到等式的右侧并将其也转换为整数。

请注意:

所有这些都可以使用浮点类型值来完成 我们也可以在等式中允许空格

为此,我们将简单地修改std::regex-string。

请看下面的完整示例:

#include <iostream>
#include <string>
#include <vector>
#include <iterator>
#include <regex>
#include <algorithm>
#include <iomanip>

int main() {

    std::string equation{ "5X^6+X^2+X^1-4X^0=0" };

    const std::regex re(R"(([+-]?\d?X\^[+-]?\d+))");
    std::vector<std::string> terms{ std::sregex_token_iterator(equation.begin(), equation.end(), re,1),std::sregex_token_iterator() };


    std::vector<int> coefficients(terms.size());
    std::vector<int> exponents(terms.size());
    int rightHandSite{ 0 };

    // Everything in front of X is the coefficient. Handle special case, when no digit is given
    std::transform(terms.begin(), terms.end(), coefficients.begin(), [](const std::string& s) {
        std::string temp = s.substr(0U, s.find('X'));
        if (1 == temp.size() && !std::isdigit(temp[0])) temp += '1';
        return std::stoi(temp); });

    // Get all exponents
    std::transform(terms.begin(), terms.end(), exponents.begin(), [](const std::string & s) {
        return std::stoi(s.substr(s.find('^') + 1)); });

    // Get right Hand site of equation
    rightHandSite = std::stoi(equation.substr(equation.find('=') + 1));

    // Show result
    std::cout << "\nEquation: " << equation << "\n\nFound '" << terms.size() << "' terms.\n\nCoeffient  Exponent\n";
    for (size_t i = 0U; i < terms.size(); ++i)
        std::cout << std::right << std::setw(9) << coefficients[i] << std::setw(10) << exponents[i] << "\n";
    std::cout << "\n                  --> " << rightHandSite << "\n";

    return 0;
}

还有许多其他可能的解决方案。但也许它会给你一些关于你能做什么的想法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-11-12
    • 2018-04-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多