在C ++中读取文件输入作为操作码

时间:2010-09-21 09:30:37

标签: c++

我正在为学校的一个班级做一个项目。它是堆栈和队列的简单实现。但是作为项目的一部分,我们需要从文件中读取操作码。操作码的格式如下:

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;
}

如果代码难以阅读,我很抱歉,以及它的一般半成品性质。我对此仍然很陌生。

3 个答案:

答案 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;
}