0

我在这里束手无策。我正在用 C++ 编写一个程序,它将读取一个包含以下内容的文本文件作为一个简短的示例:

+ 23 34
- 9 8
+ 100 1
* 8 7
^ 2 5
/ 45 8

阅读器将第一个操作数存储在 char 类型中,并根据它检索到的 char 调用一个函数来执行对这两个数字的操作,这里有一个示例函数可以执行此操作。

void doDivision(ifstream &inFile) {
    char ch;
    int num1, num2;

    inFile >> ch >> num1 >> num2;
    cout << "Division     " << num1 << "    " << num2 << "    " << "Quotient " << "    " << num1/num2 << " Remain " << num1%num2  << endl; 
}

有一件事是我不确定为什么参数是 &inFile 这个函数原型不是我制作的,但它来自一本书,也许这就是为什么我不能让它工作的原因。

这是我的主要功能:

int main()
{

ifstream inFile;
char ch;
int num1, num2;

inFile.open("math.txt");
if (inFile.fail())
{
cout << ch;
      cout << "The math.txt input file failed to open";
        return -1;
}


 while(inFile)
{
    switch (ch) {

    case '+':
        doAddition(inFile);
        break;
    case '-':
        doSubtraction(inFile);
        break;
    case '*':
        doMultiplication(inFile);
        cout << "debug " << ch;
        break;
    case '/':
        doDivision(inFile);
        break;
    case '!':
        doFactorial(inFile);
        break;
    default:
        cout << "Invalid Operation" << endl;

    }

    inFile >> ch;
}

inFile.close();
return 0;
}

所有这些一起产生了以下意想不到的结果

Invalid Operation 
Addition 3 34 sum 37 (wrong data in text file is 23 and 34)
subtraction 0 8 difference 8 (data in textfile is 9 and 8 respectively)

我将如何实现这一点,我不知所措,因为我以前从未使用过文件。

4

7 回答 7

4

一个简单的错误是在您的 while() 循环中,inFile >> ch直到第一次通过循环之后才调用。尝试修复它,看看它是否有帮助。

此外,Aniket 在他们的回答中所说的是您需要注意的另一个问题。

简而言之,您的循环应该大致如下所示:

inFile >> ch;
while(inFile) {
    switch(ch) {
    case '+':
        ...
    }
    inFile >> ch;
}

您的功能应该与此类似:

void doDivision(ifstream &inFile) {
    int num1, num2;

    inFile >> num1 >> num2;

    ...
}
于 2013-03-08T22:57:07.440 回答
2

由于您已经在这样做inFile >> chmain()因此(逻辑上)再次阅读它doAddition()和其他方法将是错误的。

既然你已经发布doDivision()了你在角色中阅读的方法ch,我假设你也在做同样的事情doAddition()

还有你的输出:

加法 3 34 和 37(文本文件中的错误数据是 23 和 34)

告诉我们一切——你已经读了 1 个字符(找到+)然后在方法中读了另一个字符doAddition(),——读2chdoAddition()然后读334..

这实际上是错误所在。

解决方案:将您doAddition()和所有其他功能更改为如下所示。

void doAddition(ifstream &inFile) {
    char ch;
    int num1, num2;

    inFile >> num1 >> num2;
    cout << "Addition of " << num1 << " and " << num2 << " = "<< (num1+num2) << '\n';
}

此外,在main()函数中:

while 循环应如下所示:

while(inFile)
{
    inFile >> ch;
    switch (ch) {

    case '+':
        doAddition(inFile);
        break;
    case '-':
        doSubtraction(inFile);
        break;
    case '*':
        doMultiplication(inFile);
        cout << "debug " << ch;
        break;
    case '/':
        doDivision(inFile);
        break;
    case '!':
        doFactorial(inFile);
        break;
    default:
        cout << "Invalid Operation" << endl;

    }
}
于 2013-03-08T22:57:23.337 回答
2

您没有阅读ch第一次迭代。事实上,当您检查您的文件是否打开时没有问题,cout << ch;尽管事实上ch未初始化,您还是会这样做。您可以简单地将 移动到循环inFile >> ch;的顶部。while

下一个问题是,在您的每个doSomething函数内部,您都在inFile >> ch再次执行操作,这将尝试再次读取操作字符。不过,您的doSomething函数不需要知道ch,因为函数本身是根据 的值选择的ch

这是我将如何写这个:

ifstream inFile("math.txt"); // You can specify the file name here
char op;
int left_operand, right_operand;

// Use extraction has while condition
while (inFile >> op >> left_operand >> right_operand) {
  switch (op) {
    // Pass operands to the relevant function
    case '+': doAddition(left_operand, right_operand); break;
    // ...
  }
}

// You do not need to close inFile, it will be closed when it goes out of scope
return 0;
于 2013-03-08T22:57:46.893 回答
1

理想情况下,有更好的方法来执行您的建议,但是如果您必须使您的代码看起来和执行起来像这样,那么适当的解决方案应该是这样的:

#include <vector>
#include <fstream>
#include <iostream>
#include <string>
#include <cstdlib>

using namespace std;

void doAddition(ifstream &inFile) {
    int num1, num2;

    inFile >> num1 >> num2;
    cout << "Addition of " << num1 << " and " << num2 << " = "<< (num1+num2) << '\n';   
}

void doSubtraction(ifstream &inFile) {
    int num1, num2;

    inFile >> num1 >> num2;
    cout << "Subtraction of " << num1 << " and " << num2 << " = "<< (num1-num2) << '\n';
}

void doMultiplication(ifstream &inFile) {
    int num1, num2;

    inFile >> num1 >> num2;
    cout << "Multiplication of " << num1 << " and " << num2 << " = "<< (num1*num2) << '\n';
}

void doDivision(ifstream &inFile) {
    float num1, num2;

    inFile >> num1 >> num2;
    cout << "Division of " << num1 << " and " << num2 << " = "<< (num1/num2) << '\n';
}

void doFactorial(ifstream &inFile) {
    int t1, t2;

    inFile >> t1 >> t2;

    //perform factorial here
}

void readToNextLine(ifstream& inFile) {
    string t1, t2;

    inFile >> t1 >> t2;
}

int main()
{
    ifstream inFile;
    char ch;
    int num1, num2;

    inFile.open("math.txt");

    if (inFile.is_open()){

        inFile >> ch;
        while (!inFile.eof())
        {
            switch (ch) 
            {

                case '+':
                    doAddition(inFile);
                    break;
                case '-':
                    doSubtraction(inFile);
                    break;
                case '*':
                    doMultiplication(inFile);
                    break;
                case '/':
                    doDivision(inFile);
                    break;
                case '!':
                    doFactorial(inFile);
                    break;
                default:
                    readToNextLine(inFile);
                    cout << "Invalid Operation" << endl;
            }
            inFile >> ch;
        }
            inFile.close();
    }
    else
    {
        cout << "The math.txt input file failed to open";
        return -1;
    }

    inFile.close();
    return 0;
}

这里有几点需要注意:

其他人建议的一些解决方案不考虑默认情况- 它只是放弃读取该行的其余部分,导致逻辑错误- 这是没有人想要的。

现在,至于“更好”、更通用的解决方案,最好先将所有内容存储为字符串,然后进行标记化,并尝试将适当的标记转换为所需的类型输出。

但是,正如我之前提到的,如果您希望符合以前的代码,那么这是合适的。

于 2013-03-08T23:34:26.460 回答
0

除非您感到自虐,否则几乎可以肯定的是同时读取运算符和两个操作数,然后执行操作:

char operation;
int operand1, operand2;

while (infile >> op >> operand1 >> operand2) 
   switch(operation) {
       case '+': add(operand1, operand2); break;
       case '-': sub(operand1, operand2); break;
       case '*': mul(operand1, operand2); break;
       case '/': div(operand1, operand2); break;
   }

对于只有四个操作员,这按原样工作得很好。如果您要拥有更多,则最好使用指向函数的指针表来代替:

typedef int (*op)(int, int);

op operators[UCHAR_MAX];

for (int i=0; i<UCHAR_MAX; i++)
    operators[i] = report_bad_operator;

operators['+'] = add;
operators['-'] = sub;
operators['/'] = div;
operators['*'] = mul;
// more operators here

while (infile >> operation >> operand1 >> operand2)
    operators[operation](operand1, operand2);

这样做的明显原因/时间是处理非二元运算符(即,不一定采用两个操作数的运算符)。

于 2013-03-08T23:03:18.427 回答
0

首先,在为它赋值之前,您正在阅读 chr。

像这样改变你的while循环:

while(inFile)
{
    inFile >> ch; // assign before reading
    switch (ch) {

    case '+':
        doAddition(inFile);
        break;
    case '-':
        doSubtraction(inFile);
        break;
    case '*':
        doMultiplication(inFile);
        cout << "debug " << ch;
        break;
    case '/':
        doDivision(inFile);
        break;
    case '!':
        doFactorial(inFile);
        break;
    default:
        cout << "Invalid Operation" << endl;
    }
}

并像这样更改您的 doDivision 函数:

void doDivision(ifstream &inFile)
{ 
    int num1, num2;

    inFile >> num1 >> num2; // your already read the arithmetic operator
    cout << "Division     " << num1 << "    " << num2 << "    " << "Quotient " << " 
}
于 2013-03-08T23:06:44.443 回答
0

首先,初始传递,您的ch变量未初始化。它在循环的底部 被初始化。

尝试添加:

 inFile >> ch;

在while循环之前。

于 2013-03-09T01:09:01.477 回答