[英]C++ fstream, reading data from text and preforming math operations?
我的智慧到此為止。 我正在用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)
我將不知道如何處理這個問題,因為我以前從未使用過文件。
一個簡單的錯誤是,在while()循環內部,直到第一次通過循環后才調用inFile >> ch
。 嘗試修復該問題,看看是否有幫助。
另外, 阿尼凱特(Aniket)在回答中所說的是您需要注意的另一個問題。
簡而言之,您的循環應大致如下所示:
inFile >> ch;
while(inFile) {
switch(ch) {
case '+':
...
}
inFile >> ch;
}
並且您的功能應與此類似:
void doDivision(ifstream &inFile) {
int num1, num2;
inFile >> num1 >> num2;
...
}
由於您已經在main()
執行inFile >> ch
,因此從邏輯上在doAddition()
和其他方法中再次讀取它是錯誤的。
由於您已經發布了doDivision()
方法並在其中讀取了ch
字符,因此我假設您在doAddition()
中也是如此。
還有你的輸出:
加法3 34的總和37(文本文件中的錯誤數據是23和34)
告訴我們所有內容-您已讀取1個字符(找到+
),然后在doAddition()
方法中讀取了另一個字符,-將2
讀入了doAddition()
ch
,然后讀取了3
和34
.。
這實際上是錯誤所在。
解決方案:將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;
}
}
您不會在第一次迭代中讀入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;
理想情況下,有更好的方法可以執行建議的操作,但是如果您必須使代碼看起來像這樣並執行,那么適當的解決方案應該是這樣的:
#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;
}
這里需要注意幾件事:
其他人建議的某些解決方案則不考慮默認情況 ,因為這種情況只是簡單地讀了其余的行, 從而導致邏輯錯誤 ,這是沒人希望的。
現在,對於“更好”的通用解決方案,將所有內容都首先存儲為字符串,然后進行標記化,然后嘗試將適當的標記轉換為所需的類型輸出,將是更理想的選擇。
但是,正如我之前指出的,如果您希望遵循以前的代碼,那么這是合適的。
除非您感到受虐狂,否則幾乎可以肯定,一次讀取所有運算符和兩個操作數,然后執行該操作最簡單:
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);
否則的明顯原因/時間將是處理非二進制運算符(即,不一定要使用兩個操作數的運算符)。
首先,您正在閱讀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 " << "
}
首先,初始階段,您的ch
變量未初始化。 它在循環的底部被初始化。
嘗試添加:
inFile >> ch;
在while循環之前。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.