我正在尝试创建一个程序,我有一个.txt文件并使用我的程序读取该文件。我的程序应该能够添加或减去数字并显示总和。我目前已经到了可以成功添加或减去文件中的数字的地步。当我尝试取一个数字的平方时,我出现了问题。例如,这就是文本文件的外观。
8 ^;
6 ^ + 3;
900 + 5 ^ - 4 ^ + 2 - 9;
期望的输出应该如下所示
64
39
902
到目前为止,我只能在没有涉及平方的情况下处理答案。但当我把平方包括在内时,一切都变得令人困惑。如果有人可以帮助我走上解决方案的正确道路,我将非常感激。
int main() {
//Initialize variables
int sum = 0;
char operation;
int number;
int holdingnumber;
int holdingoperation;
int operationChecker;
ifstream fileChecker;
//Open file
fileChecker.open("data.txt");
//If file didn't open exit program
if (!fileChecker) {
cout << "The file could not be found/opened!";
exit(1);
}
//Read information from file and add to variable sum
fileChecker >> number;
sum = number;
while (fileChecker >> operation >> number)
{
if (operation == ';')
{
cout << sum << endl;
sum = number;
}
else if (operation == '^')
{
holdingnumber = holdingnumber * holdingnumber;
if (holdingoperation == '+')
{
sum = sum + holdingnumber;
}
else if (holdingoperation == '-')
{
sum = sum - holdingoperation;
}
}
else if (operation == '+')
{
holdingoperation = operation;
holdingnumber = number;
}
else if (operation == '-')
{
holdingoperation = operation;
holdingnumber = number;
}
}
//Close file and display sum
fileChecker.close();
cout << sum;
return 0;
}
答案 0 :(得分:0)
您(或将要)遇到最大问题的原因是您创建了一个非常脆弱的输入例程,该例程依赖于输入文件的>> number >> operator
格式。为什么你在实现平方部分代码时遇到问题,关于广场的输入格式有额外的计算并不仅仅遵循>> number >> operator
,还包括>> operator >> number
例如:
900 + 5^ - 4^ + 2 - 9;
是>> number >> operator >> number >> operator >> operator >> number operator >> operator >> number >> operator >> number >> delimiter
。
虽然无论如何操作都会有嵌套条件,但除了根据它们处理各种计算之外,当你开始在read语句中添加其他条件时,所需的数字很快就会失控。
在上面的代码中,如果您将>>
更改为scanf
次调用,将<<
更改为printf
,则您的代码不会使用C ++提供的任何内容。 C ++提供了一组很好的工具,可以帮助您处理这些事物的值,字符串,字符和集合。利用语言提供的功能。
此处,使用string
和vector
类,无需管理holding...
变量。它可以这样做,同时完全消除您在行末有分隔符(例如';'
)的依赖性。 (事实上唯一的挑战是,如果你找到一个由';'
分隔的行,你只需将其删除)
更好的阅读文件的方法是一次读一行string
getline
。这使得循环遍历文件很简单,只需将每行读入字符串,直到没有更多的行可读。
C ++提供自动范围迭代器(以及其他几个),然后让你迭代字符串(行)中的每个字符。 <cctype>
标头提供isdigit()
函数,允许您确定当前char是否为允许您获取数值的数字。通过调用vector
成员函数将该值添加到向量中,push_back()
类可以轻松存储该值(以及根据需要添加更多值)。
(注意:您可以轻松地在存储的字符串上使用 stringstream ,并根据stoi
等转换例程解析这些值,但对于简单数字(假定为非负数 - 意味着'-'
是一个运算符,并且不包含代码来处理'- -value'
,但可以很容易地添加代码。
当遇到运算符时,向量类提供了一个简单的.size()
成员函数,允许您告知向量中有多少值正在等待。然后,它只是一个逻辑游戏,知道+, -, *, /
将对向量中的最后相邻值进行操作,而'^'
仅对最后一个进行操作。
如果您将向量中的最后一个值保留为当前sum
,那么在处理给定的所有计算时,您不必跟踪任何其他变量(临时使用除外)线。
当您处理完一行后,您的计算文本已存储在您的字符串中,因此在处理完一行后,您只需输出您的计算字符串然后输出结果(存储的最后一个值)你的矢量):
cout << string << " = " << vector.back() << "\n";
将所有部分组合在一起,您可以执行与以下类似的操作。稍微考虑一下,你可能会找到一个更好的方法来做到这一点。关键是,总会有很多方法来解决问题:
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <cctype>
using std::ifstream;
using std::cout;
using std::cerr;
using std::string;
using std::vector;
/* execute current calculation between adjacent values */
void execute (vector<long>& values, char op);
int main (int argc, char **argv) {
long tmp = 0; /* temp number to build values as chars processed */
string calc; /* string to hold the line (complete calculation) */
ifstream f (argc > 1 ? argv[1] : "data.txt"); /* file to read */
if (!f.is_open()) { /* validate file open for reading */
cerr << "error: file open failed.\n";
return 1;
}
while (getline (f, calc)) { /* loop over each line in the file */
char op = 0; /* char to hold operator (+,-,*,/) */
vector<long> values; /* vector to hold adjacent values */
if (calc.back() == ';') /* if line delimited by ';', then */
calc.pop_back(); /* remove ';' from string */
for (auto& c : calc) { /* for each char in line */
if (isdigit(c)) { /* am I a digit?, if so build value */
tmp *= 10;
tmp += c - '0';
}
else { /* if I'm not a digit, I'm either whitespace or op */
if (tmp) { /* if there is a value in temp */
values.push_back (tmp); /* add the value to vector */
tmp = 0; /* zero tmp */
}
if (values.size() && c == '^') { /* handle squared */
values.back() *= values.back(); /* square in place */
}
else if (values.size() > 1 && op) { /* adjacent vals & op */
execute (values, op); /* computer intermediate calc */
op = 0; /* op consumed, reset to zero */
}
else { /* not digit, not squaring, no adjacent vales */
switch (c) { /* save op if one of following */
case '+': op = c; break;
case '-': op = c; break;
case '*': op = c; break;
case '/': op = c; break;
}
}
}
} /* all characters processed */
if (tmp) { /* does tmp value remain? */
values.push_back (tmp); /* add to vector */
tmp = 0; /* reset tmp */
}
if (values.size() > 1 && op) /* handle final calculation */
execute (values, op);
cout << calc << " = " << values.back() << "\n";
}
f.close();
}
/* simple function takes vector reference and operator
* and performs indicated calculation on adjacent values.
*/
void execute (vector<long>& values, char op)
{
long sum;
auto it = values.end();
it -= 2;
switch (op) {
case '+': sum = *it + values.back();
values.pop_back();
values.back() = sum;
break;
case '-': sum = *it - values.back();
values.pop_back();
values.back() = sum;
break;
case '*': sum = *it * values.back();
values.pop_back();
values.back() = sum;
break;
case '/': sum = *it / values.back();
values.pop_back();
values.back() = sum;
break;
}
}
(注意:)使用上面的pop_back()
来修剪向量中的最后一个元素,允许您将运行总计作为向量中的最终(且唯一)值基本上,计算完成后,如果它涉及两个值,在计算完成后,矢量中的最后一个值将被删除,当前总数将被存储到该计算的第一个值的位置。
另请注意,这是一个简单的示例,除了解决输入数据文件的方法之外,其他任何内容都不适用。
示例输入文件
没有行尾分隔符:
$ cat ../dat/calc.txt
127 + 231
8^
6^ + 3
900 + 5^ - 4^ + 2 - 9
使用分隔符:
$ cat ../dat/calcdelim.txt
127 + 231;
8^;
6^ + 3;
900 + 5^ - 4^ + 2 - 9;
示例使用/输出
无论使用哪个输入文件,输出都是相同的。
$ ./bin/calctest ../dat/calc.txt
127 + 231 = 358
8^ = 64
6^ + 3 = 39
900 + 5^ - 4^ + 2 - 9 = 902
仔细看看。消化语言的不同部分需要时间。这是一些很好的参考引用帮助,如cppreference.com。如果您有任何其他问题,请与我们联系。