質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.77%

VC++ ofstreamでテキスト出力されない

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,703

robomoco

score 29

以下のプログラムをエラーなく,コンパイルすることができました。が,ofstreamのオブジェクトofsに<<を用いて文字列を出力しても,開いたファイルには何も書きこまれませんでした。全く原因が分かりません。

何故か、Main.cppの下部にあるwhile(1)以降のところをコメントアウトしたら、Code Writerクラスのコンストラクタで定義した、デバッグ用の ofs<<"Open Wow”が実行されて、出力ファイルに上手くか囲まれました。

Main.cpp

#include <iostream>
#include "Parser.h"
#include "CodeWriter.h"
using namespace std;
int main()
{
    Parser parser;
    CodeWriter codewriter(parser);
    parser.advance();
    while (1) {
        if (parser.commandType() == C_ARITHMATIC) {
            codewriter.writeArithmatic(parser.arg1());
        }
        else if (parser.commandType() == C_POP) {
            codewriter.writePushPop(C_POP, parser.arg1(), parser.arg2());
        }
        else if (parser.commandType() == C_PUSH) {
            codewriter.writePushPop(C_PUSH, parser.arg1(), parser.arg2());
        }
            parser.advance();
    }
}

Parser.h

#pragma once
#include <fstream>
#include <sstream>
#include <string>
#include <iostream>
enum comType{
    C_ERROR,
    C_ARITHMATIC,
    C_PUSH,
    C_POP,
    C_LABEL,
    C_GOTO,
    C_IF,
    C_FUNCTION,
    C_RETURN,
    C_CALL
};

class Parser {
public:
    std::string infilename;
    Parser();            //読みこみファイルを開く
    void advance();        //次のコマンドを読みこむ
    comType commandType();    //コマンドのタイプを返す
    std::string arg1();            //現コマンドの1番目の引数を返す
    int arg2();                //現コマンドの2番目の引数を返す
    std::ifstream ifs;
    std::string curcmd;        //現在コマンド
};

Parser.cpp

#include "Parser.h"
using namespace std;
//クラスParserの実装
Parser::Parser()
{
    cin >> infilename;
    ifs.open(infilename);
    while(ifs.fail()) {
        cin >> infilename;
        ifs.open(infilename);
    }
}

void Parser::advance()
{
    getline(ifs, curcmd);

    while (curcmd[0] == ' ') {
        curcmd.erase(curcmd.begin()+0);
    }
    while (curcmd[0] == '/') {
        advance();
    }
    while (curcmd[0] == '\0') {
        advance();
    }
}

comType Parser::commandType()
{
string curcmdope = curcmd;
    curcmdope = curcmdope.substr(0, curcmd.find(" "));
    if (curcmdope == "add" || curcmdope == "sub" || curcmdope == "neg" ||
        curcmdope == "eq"  || curcmdope == "qt"  || curcmdope == "lt"  ||
        curcmdope == "and" || curcmdope == "or"  || curcmdope == "not") {

        return C_ARITHMATIC;
    }
    else if (curcmdope == "push") {
        return C_PUSH;
    }
    else if (curcmdope == "pop") {
        return C_POP;
    }
    else {
        return C_ERROR;
    }
}

string Parser::arg1()
{
    string curcmdarg1 = curcmd;

    if (commandType() == C_RETURN) {
        cout << "C_RETURNは呼ぶな" << endl;
        return curcmd;
    }
    else if (commandType() == C_ARITHMATIC) {
        return curcmd;
    }
    else if (commandType() == C_PUSH || commandType() == C_POP) {

        while (curcmdarg1[0] != ' ') {
            curcmdarg1.erase(curcmdarg1.begin() + 0);
        }
        while (curcmdarg1[0] == ' ') {
            curcmdarg1.erase(curcmdarg1.begin() + 0);
        }

        curcmdarg1 = curcmdarg1.substr(0, curcmdarg1.find(" "));

        return curcmdarg1;
    }
}

int Parser::arg2() 
{
    string curcmdarg2 = curcmd;

    if (commandType() == C_PUSH || commandType() == C_POP || 
        commandType() == C_FUNCTION || commandType() == C_CALL) {

        while (curcmdarg2[0] != ' ') {
            curcmdarg2.erase(curcmdarg2.begin() + 0);
        }
        while (curcmdarg2[0] == ' ') {
            curcmdarg2.erase(curcmdarg2.begin() + 0);
        }
        while (curcmdarg2[0] != ' ') {
            curcmdarg2.erase(curcmdarg2.begin() + 0);
        }
        while (curcmdarg2[0] == ' ') {
            curcmdarg2.erase(curcmdarg2.begin() + 0);
        }
        curcmdarg2 = curcmdarg2.substr(0, curcmdarg2.find(" "));
        //cout << "curcmdarg2 " << curcmdarg2 << endl;
        return stoi(curcmdarg2);
    }
}

CodeWriter.h

#pragma once
#include <fstream>
#include <sstream>
#include <string>
#include <iostream>

class CodeWriter {
public:
    std::string outfilename;
    CodeWriter(Parser& parser);        //出力先ファイルを開く
    void setFileName(std::string fileName);
    int label_num;
    std::string get_new_label();
    void writeArithmatic(std::string command);
    void writePushPop(comType command, std::string segment, int index);
    void close();
    std::ofstream ofs;
    //std::string* curcmd;        //現在コマンド
};

CodeWriter.cpp

#include "Parser.h"
#include "CodeWriter.h"

using namespace std;

CodeWriter::CodeWriter(Parser& parser)
{
    label_num = 0;
    //curcmd = &(parser.curcmd);
    outfilename = parser.infilename;
    outfilename.erase(outfilename.find(".") + 1, outfilename.find(".") + 3);
    outfilename += "hack";
    ofs.open(outfilename);
    ofs << "open WOW";
}

void CodeWriter::setFileName(string fileName) 
{

}



void CodeWriter::writePushPop(comType command, string segment, int index)
{
    string idx = to_string(index);
    string outfilename_ex_hack = outfilename;
    outfilename_ex_hack=outfilename_ex_hack.erase(outfilename.find("."), outfilename.find(".") + 5);
    cout << "outfilename(-hack): " << outfilename_ex_hack << endl;

    if (command == C_PUSH) {
        if (segment == "static") {
            ofs << "@" << outfilename_ex_hack << "." << idx << "\n";
            ofs << "D=M\n";
            //write push from D-register
            ofs << "@SP\n";
            ofs << "A=M\n";
            ofs << "M=D\n";
            ofs << "@SP\n";
            ofs << "M=M+1\n";
        }
        else if (segment == "constant") {
            ofs << "@" << idx << "\n";
            ofs << "D=A\n";
            //write push from D-register
            ofs << "@SP\n";
            ofs << "A=M\n";
            ofs << "M=D\n";
            ofs << "@SP\n";
            ofs << "M=M+1\n";
        }
        else if (segment == "local" || segment == "argument" ||
            segment == "this" || segment == "that") {
            string reg_name;
            //write push from virtual segment
            if (segment == "local")    reg_name = "LCL";
            else if (segment == "argument")reg_name = "ARG";
            else if (segment == "this")reg_name = "THIS";
            else if (segment == "that")reg_name = "THAT";
            ofs << "@" << reg_name << "\n";
            ofs << "A=M\n";
            for (int i(0); i < index; i++) {
                ofs << "A=A+1\n";
            }
            ofs << "D=M\n";
            //write push from D-register
            ofs << "@SP\n";
            ofs << "A=M\n";
            ofs << "M=D\n";
            ofs << "@SP\n";
            ofs << "M=M+1\n";
        }
        else if (segment == "pointer" || segment == "temp") {
            ofs << "@0\n";
            if (segment == "pointer") {
                for (int i(0); i < 3 + index; i++) {
                    ofs << "A = A + 1\n";
                }
                ofs << "D=M\n";
                //write push from D-register
                ofs << "@SP\n";
                ofs << "A=M\n";
                ofs << "M=D\n";
                ofs << "@SP\n";
                ofs << "M=M+1\n";
            }
            else if (segment == "temp") {
                for (int i(0); i < 5 + index; i++) {
                    ofs << "A = A + 1\n";
                }
                ofs << "D=M\n";
                //write push from D-register
                ofs << "@SP\n";
                ofs << "A=M\n";
                ofs << "M=D\n";
                ofs << "@SP\n";
                ofs << "M=M+1\n";
            }
        }

    }
    else if (command == C_POP) {
        if (segment == "static") {
            //write pop to m_register
            ofs << "@SP\n";
            ofs << "M=M-1\n";
            ofs << "A=M\n";
            ofs << "D=M\n";
            ofs << "@" << outfilename_ex_hack << "." << idx << "\n";
            ofs << "M=D\n";
        }
        else if (segment == "local" || segment == "argument" ||
            segment == "this" || segment == "that") {
            string reg_name;
            //write pop to virtual segment
            if (segment == "local")    reg_name = "LCL";
            else if (segment == "argument")reg_name = "ARG";
            else if (segment == "this")reg_name = "THIS";
            else if (segment == "that")reg_name = "THAT";
            //write pop to m_register
            ofs << "@SP\n";
            ofs << "M=M-1\n";
            ofs << "A=M\n";
            ofs << "D=M\n";
            ofs << "@" << reg_name << "\n";
            ofs << "M=D\n";
        }
        else if (segment == "temp" || segment == "pointer") {
            //write pop to static segment
            if (segment == "temp") {

                //write pop to m_register
                ofs << "@SP\n";
                ofs << "M=M-1\n";
                ofs << "A=M\n";
                ofs << "D=M\n";
                ofs << "@0\n";
                for (int i(0); i < 3 + index; i++) {
                    ofs << "A=A+1\n";
                }
                ofs << "M=D";

            }
            else if (segment == "pointer") {
                //write pop to m_register
                ofs << "@SP\n";
                ofs << "M=M-1\n";
                ofs << "A=M\n";
                ofs << "D=M\n";
                ofs << "@0\n";
                for (int i(0); i < 5 + index; i++) {
                    ofs << "A=A+1\n";
                }
                ofs << "M=D";
            }
        }
    }
}

string CodeWriter::get_new_label() {
    label_num += 1;
    return "LABEL"+to_string(label_num);
}
void CodeWriter::writeArithmatic(string command)
{
    if (command == "add") {
        //write pop to m_register
        ofs << "@SP\n";
        ofs << "M=M-1\n";
        ofs << "A=M\n";
        ofs << "D=M\n";
        //write pop to m_register
        ofs << "@SP\n";
        ofs << "M=M-1\n";
        ofs << "A=M\n";

        ofs << "D=D+M\n";

        //write push from D_register
        ofs << "@SP\n";
        ofs << "A=M\n";
        ofs << "M=D\n";
        ofs << "@SP\n";
        ofs << "M=M+1\n";
    }
    else if (command == "sub") {
        //write pop to m_register
        ofs << "@SP\n";
        ofs << "M=M-1\n";
        ofs << "A=M\n";
        ofs << "D=M\n";
        //write pop to m_register
        ofs << "@SP\n";
        ofs << "M=M-1\n";
        ofs << "A=M\n";
ofs << "D=M-D\n";

        //write push from D_register
        ofs << "@SP\n";
        ofs << "A=M\n";
        ofs << "M=D\n";
        ofs << "@SP\n";
        ofs << "M=M+1\n";
    }
    else if (command == "and") {
        //write pop to m_register
        ofs << "@SP\n";
        ofs << "M=M-1\n";
        ofs << "A=M\n";
        ofs << "D=M\n";
        //write pop to m_register
        ofs << "@SP\n";
        ofs << "M=M-1\n";
        ofs << "A=M\n";

        ofs << "D=D&M\n";

        //write push from D_register
        ofs << "@SP\n";
        ofs << "A=M\n";
        ofs << "M=D\n";
        ofs << "@SP\n";
        ofs << "M=M+1\n";
    }

}

void CodeWriter::close()
{
    ofs.close();
}
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • Chironian

    2019/05/08 23:15

    CodeWriter.cppを貼り付けそこなっているようですよ。

    キャンセル

回答 2

+1

こんにちは。

可能性としては、「while(1)以降のところ」で何か異常が発生してプログラムが落ちていることが考えられます。この場合、CodeWriterのコンストラクタで書き込まれたものはまだキャッシュに残っていてファイルへ出力されていないため、書き込まれないです。
しかし、その部分をコメントアウトして異常終了しなければ、ofsがきちんとデストラクトされるのでその時点でキャッシュの内容はファイルへ書き込まれます。

本当にそうなっているのかどうか確認するには、デバッガを使ってステップ実行するなどしてデバッグした方が良いと思います。

他に、要所要所で、std:cout << "デバッグ文字列" << std::endl;するのも手です。
std::endlは改行だけでなくキャッシュに溜まっているデータをファイルへ追い出すので、落ちたところを見つけやすいです。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

check解決した方法

0

自己解決しました。
おそらく,while(1)としたのがまずかったのでしょう。無限ループで終わらないので,そこでエラーが発生して,一切のファイル出力をしてくれなかったのものと思われます。多分。
そこで,getline関数を含むadvance()の実装を以下のように,エラー判定できるように変えました。

bool Parser::advance()
{
if(!getline(ifs, curcmd)) return false;  <======変更点

while (curcmd[0] == ' ') {
curcmd.erase(curcmd.begin()+0);
}
while (curcmd[0] == '/') {
advance();
}
while (curcmd[0] == '\0') {
advance();
}
}

そしてmain.cppのほうでは,while(1)ではなく,while(parser.advance())とすることで,無限ループを食い止めます。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.77%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る