-1

私の C++ プロジェクトの目的は、単純な文字から作成された画像を含むファイルを出力することです。

私のプロジェクトの最初の部分では、「入力ファイルからコマンドを読み取り、読み取ったコマンドを表す整数値を返す関数を含める」必要があります。それが私の takeCommand 関数です。恐ろしく非効率に思えますが、正しく理解できれば必要だと思います。

現在の問題は、メイン関数の while ループが無限ループを実行することです。テキスト「Works」を出力すると、常に繰り返されます。私の意図は、ファイルの終わりで制御されたループを作成することでした。takeCommand 関数の内部では、最後の行を読み取ると、takeCommand 関数の実行が停止するため、while ループが終了します。

while ループを常に繰り返さずに機能させる方法についてのアイデアが必要です。

私が現在持っているものは次のとおりです。

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

入力ファイルの 1 つは次のようになります。

; 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

出力ファイルはバニーを作成することになっています。

void 関数は私のコードにありますが、それは今のところ問題ではありません。

4

2 に答える 2

0

あなたの問題はinfile、while ループの実行中ずっと生きていることです。そのため、ファイルが閉じられた後でもオブジェクトがまだ存在するため、while ループは常に true です。

さらに、switch ステートメントでテストする前に、入力された文字列を取得する必要があります。また、ファイルが完全に読み取られたことを I/O 操作が示した場合 (つまり、eof() 関数を使用)、while ループ内でファイルを閉じる必要があります。 、データが読み取られた後に呼び出す必要があります)。そして、2番目の関数でファイルを再度開いています。このコードは大幅な修正が必要です。

于 2013-11-06T01:11:44.613 に答える
0

takeCommandまず、関数から始めましょう。ループ メカニズムを使用getlineし、ファイルの最初の 3 行を無視しました (単純なヘッダーだったため)。論理的に思えますが、注意点があります。この関数をwhileループ内から複数回呼び出すと、呼び出しごとに 3 行が無視されます。「恐ろしく非効率」はどうですか?:)

これを行う必要はありません。その上、最初は関数内 (while ループの外側) の最初の 3 行を無視するのにmain、なぜ内部で再びそれが必要なの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;
}

私が持っているもう1つの不満は、不必要なopen電話です。ファイル ストリームの構築時にファイルの名前がす​​でにわかっている場合は、ファイル ストリームの作成時にそれを指定するだけです。つまり、関数からその呼び出しを削除し、代わりに次のことを行います。

ifstream infile("DrawingInput_01.txt");

もう 1 つのことは、ファイル ストリームは静的ストレージ期間を必要とせず、グローバル変数としても必要ないため、入力ファイル ストリームと出力ファイル ストリームを取り、それらを 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 に答える