2010-09-21 111 views
0

我正在为学校的班级开发一个项目。这是一个简单的堆栈和队列实现。然而,作为项目的一部分,我们需要从文件中读取操作码。将文件输入作为C++中的操作码读取

append 10 
serve 
append 20 
append 30 
serve 
push 10 
push 50 
push 20 
push 20 
pop 

我的问题是,当我在文件中通过标准fstream的阅读似乎挑选了一些很怪的格式或什么的,并不会匹配比较检查:操作码如下格式化。

我在想我在做什么错,如何解决它,以及是否有更好的方法来操纵未来的操作码。就像这样,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

能否请您附上了错误的输出你? (顺便说一句,摆脱那个丑陋的系统(“暂停”);) – 2010-09-21 09:41:38

+0

标准流操作符会自动在空白区域中断。但是你的getline()只在空间上(而不是选项卡)中断,所以要小心输入文件不包含制表符(或使用操作符>>)。 – 2010-09-21 10:48:00

+0

另外你对eof()的测试不正确。在读过文件结尾之前,eof标志没有设置为true。所以,如果你阅读整个文件(没有任何遗漏),它仍然是错误的,并进入循环。下一次调用getline()会失败,并使opcodde处于不确定状态(可能是“”,从而导致打印“else!”)。 – 2010-09-21 10:50:29

回答

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

这真的是答案!我不知道getline在干什么,这让它变得非常糟糕,但是这样做效果更好!非常感谢! – stygma 2010-09-23 11:54:02

+0

没问题; getline的问题在于,像你一样调用它,它只停止读取空格,所以,在第一行之后,它读取参数*和*下面的操作码在同一个字符串中。 *和*,正如我写的,你也没有读过这个论点。 – 2010-09-23 12:01:18

1

这个问题很可能源于您阅读输入的方式。 std::getline(..., ' ')提取以空格结尾的字符串。在给定的输入,得到的第一个字符串会append,但第二个将是

10 
serve 
append 

因为没有空间。

这个怎么样,而不是试图完全读取操作码,读一行,并看看你是否可以找出开始与操作码。

+0

我很清楚这一点,但即使在读取服务时使用简单的if(getline(data,opcode,''== == serve)){cout << server正在工作,我也没有得到任何类型的确认。 } – stygma 2010-09-23 11:52:04

1

而不是读文件一句话AA时间,读取(使用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 
    } 
+0

还固定测试错误的EOF'而(!data.eof())' – 2010-09-21 10:46:31

+0

容易,只需申报linestream在一个声明中初始化。 'std :: stringstream linestream(line);'使用操作符>>从行中提取命令(因为它将读取空格分隔的单词)。 – 2010-09-21 10:51:28

+0

是的,好点,这是从我的旧项目快速复制粘贴,所以我从来没有打扰其他任何东西,然后它是正确和compilable :) – Necrolis 2010-09-21 11:20:06