我正在为学校的一个班级做一个项目。它是堆栈和队列的简单实现。但是作为项目的一部分,我们需要从文件中读取操作码。操作码的格式如下:
append 10
serve
append 20
append 30
serve
push 10
push 50
push 20
push 20
pop
我的问题是,当我通过标准的fstream读取文件时,它似乎会拾取某种奇怪的格式或其他内容,并且不会与比较检查相匹配。
我很想知道我做错了什么,如何解决它,以及是否有更好的方法来操作opcode。实际上,if-else语句总是转到if。迫切需要这种工作。
#include "StackAndQueue.h"
#include <string>
#include <iostream>
#include <fstream>
using namespace std;
int main(){
Stack leStack;
Queue leQueue;
//Read in the datafile.
cout << "Reading default file: p2datafile.txt";
fstream data("p2datafile.txt");
while (data.fail()){
cout << " failed." << endl;
data.close();
cout << "Please enter path to datafile: ";
string filename;
cin >> filename;
data.open(filename.c_str());
}
cout << endl << "Sucess!" << endl;
//Loop through all the commands in the file
while(!data.eof()){
// Determine what kind of command is running
// and if parsing will be needed.
string opcode;
getline(data,opcode,' ');
if (opcode == "pop"){
cout << "popping!" << endl;
leStack.pop();
}
else if (opcode == "serve"){
cout << "serving" << endl;
leQueue.serve();
}
else if (opcode == "push"){
cout << "pushing";
}
else{
cout << "else!" << endl;
}
}
data.close();
system("pause");
return 0;
}
如果代码难以阅读,我很抱歉,以及它的一般半成品性质。我对此仍然很陌生。
答案 0 :(得分:1)
您最有可能的问题源于您阅读输入的方式。 std::getline(..., ' ')
提取以空格结尾的字符串。使用给定的输入,获得的第一个字符串将是append
,但第二个字符串将是
10
serve
append
因为没有空格。
如何做到这一点,而不是试图准确读取操作码,读取一行,看看是否可以通过操作码判断是否开始。
答案 1 :(得分:1)
不是一次读一个单词,而是阅读整行(使用std::getline
),然后使用std::stringstream
处理该行,如下所示:
std::string line;
while(std::getline(file,line))
{
std::stringstream linestream(std::stringstream::in|std::stringstream::out);
linestream << line;
std::string command;
if(std::getline(linestream,command,' '))
{
//process line - chain 'if(std::getline(linestream,command,' '))' to advance the token steam
}
else
//error blank line
}
答案 2 :(得分:0)
getline
仅将' '
视为分隔符,因此它不会在换行符处停止;而且,你没有提取参数(当操作码有任何参数时),因此它将在下一次迭代时被读作操作码(粘在真实操作码前面)。
在我看来,你可以简单地使用正常的operator>>
。它在任何空格(这是你想要做的)正确停止并正确支持C ++字符串。重要的是要记住在需要时提取参数(同样,使用operator>>
),在数字格式错误的情况下观察istream::fail()
错误。您甚至可能希望在出现这些错误时让流上升异常(因此不会忽视它们)。
try
{
string opcode;
data.exceptions(ios::failbit);
//Loop through all the commands in the file
while(data>>opcode){
// Determine what kind of command is running
// and if parsing will be needed.
int argument;
if (opcode == "pop"){
cout << "popping!" << endl;
leStack.pop();
}
else if (opcode == "serve"){
cout << "serving" << endl;
leQueue.serve();
}
else if (opcode == "push"){
cout << "pushing";
data >> argument;
}
else if (opcode == "append"){
cout << "appending";
data >> argument;
}
else{
cout << "else!" << endl;
}
}
data.close();
}
catch(const ios::failure & ex)
{
if(!data.eof())
cout<<"IO error"<<endl;
}