-1

My C++ project purpose is to output a file with a picture made from simple characters.

The first part of my project requires that I "include a function that read a command from the input file and returns an integer value representing the command that was read". That's my takeCommand function. Seems horribly inefficient, but I guess necessary if, I understood it correctly.

The current problem is that my the while loop in my main function runs an infinite loop. When outputting the text "Works", it constantly repeats. My intention was to make an End-of-File controlled loop. Inside the takeCommand function, when it reads the last line, the takeCommand function ceases to run, thus the while loop ends.

I need ideas as to how to get the while loop to work without repeating constantly.

What I currently have is:

    int takeCommand(int& num, int& cmd);

    ifstream infile;
    ofstream outfile;

    int main()
    {
         const int MAX_FOR = 3;
         string str;
         int num, cmd;
         infile.open("DrawingInput_01.txt");
         outfile.open("DrawingOutput_01.txt");

         for (int i = 0; i < MAX_FOR; i++)
         {
             getline(infile,str);
         }

         takeCommand(num,cmd);
         while(infile)
         {
           cout << "Works";
           /*switch(cmd)
           {
               case '1': printSpace(infile, outfile); break;
               case '2': printChar(infile, outfile); break;
               case '3': printNewline(infile, outfile); break;
               case '0': break;
           }*/
           takeCommand(num, cmd);
         }

         infile.close();
         outfile.close();
         return 0;
     }

     int takeCommand(int& num, int& cmd)
     {
         string str;
         char firstChar;
         infile.open("DrawingInput_01.txt");
         for (int i = 0; i < 3; i++)
         {
             getline(infile.str);
         }
         infile >> firstChar >> str >> num;
         switch(firstChar)
         {
             case 's': cmd = 1; break;
             case 'p': cmd = 2; break;
             case 'n': cmd = 3; break;
             case 'q': cmd = 0; break;
         }
         return cmd;
     }

One of the input files looks like:

; CS 1044 Fall 2010
; Project 4
; Basic Cat
space 1
print 1 /
print 1 \
print 1 _
print 1 /
print 1 \
newline
print 1 (
space 1
print 1 o
print 1 .
print 1 o
space 1
print 1 )
newline
space 1
print 1 >
space 1
print 1 ^
space 1
print 1 <
newline
quit

The output file is supposed to make a bunny.

The void functions are in my code, it's just not the problem right now.

4

2 回答 2

0

您的问题是它infile在整个 while 循环的执行过程中都处于活动状态,因此您的 while 循环始终为真,因为即使在文件关闭后该对象仍然存在。

此外,您应该在使用 switch 语句测试之前获取输入的字符串,并且当 I/O 操作表明文件已被完全读取(即使用 eof() 函数)时,您需要在 while 循环内关闭文件,必须在读取数据后调用)。你在第二个函数中再次打开文件。这段代码需要认真修改。

于 2013-11-06T01:11:44.613 回答
0

好吧,让我们首先从您的takeCommand函数开始:您使用了循环机制并getline忽略了文件中的前三行(因为它是一个简单的标题)。似乎合乎逻辑,但有一个警告。当您在循环内多次调用此函数时while,每次调用都会忽略 3 行。“极其低效”是怎么回事?!:)

你不需要这样做。此外,您最初忽略了函数内部的前三行main(在 while 循环之外),那么为什么在内部又需要它takeCommand呢?解决方案是删除 for 循环,以便之后的函数如下所示:

int takeCommand(int& num, int& cmd)
{
    char firstChar;
    infile.open("DrawingInput_01.txt");

    infile >> firstChar >> str >> num;

    switch (firstChar)
    {
        case 's': cmd = 1; break;
        case 'p': cmd = 2; break;
        case 'n': cmd = 3; break;
        case 'q': cmd = 0; break;
    }
    return cmd;
}

我的另一个烦恼是一个不必要的open电话。如果您在构建文件流时已经知道文件名,则只需在创建文件流时提供它。这意味着从函数中删除该调用,而是执行以下操作:

ifstream infile("DrawingInput_01.txt");

还有一件事,文件流不需要静态存储持续时间,也不需要作为全局变量,所以你应该把输入和输出文件流放在main中。

while 循环条件都是错误的。应在检查流之前执行 I/O。因此,您可以将功能更改为:

std::basic_ios<char>& takeCommand(int& cmd)
{
    char firstChar;
    if (!inFile.get(firstChar))
    {
        return inFile;
    }

    inFile.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

    // ...

    return inFile;
//  ^^^^^^^^^^^^^^
}

这允许流返回到下面的 while 循环条件,以便它检查输入是否成功:

while (takeCommand(cmd))

请注意,我还检查了输入操作是否成功(如果有,我们忽略该行的其余部分),并且我已经取出了不需要的参数。

在您进行这些更改(以及其他更改)之后,您的程序应该是这样的:

#include <iostream>
#include <fstream>
#include <limits>

std::ios& takeCommand(std::istream&, int&);

int main()
{
    std::ifstream inFile("DrawingInput_01.txt");
    std::ofstream outFile("DrawingInput_01.txt");
    std::string str;

    for (int i = 0; i < 3; ++i) std::getline(inFile, str);

    int cmd;

    while (takeCommand(inFile, cmd))
    {
        std::cout << "Command was " << cmd;
        outFile << cmd;
   }
}

std::ios& takeCommand(std::istream& is, int& cmd)
{
    char firstChar;
    if (!is.get(firstChar))
    {
        return is;
    }

    is.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

    switch (firstChar)
    {
        case 's': cmd = 1; break;
        case 'p': cmd = 2; break;
        case 'n': cmd = 3; break;
        case 'q': cmd = 0; break;
    }

    return is;
}
于 2013-11-06T02:03:55.190 回答