从文件中读取字符串格式的信息

时间:2014-05-12 12:51:06

标签: c++ string

我正在尝试从文件中读取逻辑门名称及其输入。我收到了一个.bench文件,其中提供了有关门名称及其输入的信息。 我在下面编写了一个代码,如果信息以下列格式给出,我会得到完美的结果:

firstGate = NAND(inpA, inpB, inpC)
secGate = NAND(1, 2)
30 = NAND(A, B)

问题:但是如果"白色空间发生变化"在=签名之前,,之后或其他地方,我的代码无效。对于 例如,如果文件以下列格式给出,那么我无法正确阅读

first=NAND(inpA, inpB, inpC) //no space before and after "="
sec = NAND(1,2) //no space after ","

我的代码适用于第一种情况如下:

int main(int argc, char* argv[])
{
    //Reading the .bench file
    ifstream input_file;
    input_file.open("circuit.bench");
    if(input_file.fail())
    {
        cout << "Failed to open Bench file.\n";
        return 1;
    }
    ///////

    string line;        
    while (getline( input_file, line ))  
    {
        ///For NAND
        size_t  first_index_nand, second_index_nand;
        string gate_name;

        const string nand_str = "NAND(";
        if ((first_index_nand = line.find(nand_str)) != string::npos)
        {
            gate_name = line.substr(0, first_index_nand - 3);
            cout<<"\nGate name: "<<gate_name;

            first_index_nand += nand_str.length() - 1;
            cout<<"\nInput to this gate: ";
            for (; first_index_nand != string::npos; first_index_nand = second_index_nand)
            {
                if ((second_index_nand = line.find_first_of(",)", first_index_nand)) != string::npos)
                {
                    string input_name = line.substr(first_index_nand + 1, second_index_nand++ - first_index_nand - 1);  
                    cout<<" "<<input_name;
                }
            }
        }
        cout<<"\n";
    }

    return 0;

}

查询:我应该如何修改我的代码,使其能够读取门的名称及其输入,而不管它们的位置是什么?空白?

注意:我必须使用C ++代码及其库来处理此问题。

2 个答案:

答案 0 :(得分:1)

第一个答案:永远不要自己写一个手工解析器: - )

1)将代码生成器用于解析器,如lex,yacc,bison(更多......)

2)你可以从expect或regexp获得解析支持

3)寻找序列化,例如提高::序列化。如果您修改编写器/阅读器,则可以序列化为更复杂的格式,其中包含类似于配置文件的格式。

如果你真的想编写自己的解析器,那么大多数建议你编写一个或多或少复杂的状态机。但这可以通过工具更容易地手工完成。

Sorr,我不会深入研究你的代码,但我的个人经验是,它以大量代码行结束,以获得真正有效的解析器。而且大部分代码都不再可维护。所以我想建议你使用我提供的三个(或任何其他选项)中的一个: - )

答案 1 :(得分:0)

你应该像@Rook和@Klaus建议的那样,可能使用一个没有dtd的简单xml文件和一个像Xerces http://xerces.apache.org/xerces-c/这样的库。

如果您想使用文件格式,则应手动删除所有空格,例如,您可以在此处找到What's the best way to trim std::string?或此处:remove whitespace in std::string。 只有在那之后,您才能使用算法提取数据。

无论如何试试这应该有用。

#include <iostream>
#include <fstream>
#include <string>
#include <algorithm>

using namespace std;

string trimWhiteSpaces(const string& line)
{
    string l = line;

    l.erase(std::remove_if( l.begin(), l.end(), ::isspace ), l.end());

    return l;
}

int main(int argc, char* argv[])
{
    cout << "starting... \n";

    ifstream _ifile;
    string fname = "gates.bench";

    _ifile.open(fname.c_str());
    if(!_ifile.is_open())
    {
        cerr << "Failed to open Bench file" << endl;
        exit(1);
    }

    string line;

    while(getline(_ifile, line))
    {

        line =  trimWhiteSpaces(line);

        size_t  first_index_nand, second_index_nand;
                string gate_name;

                const string nand_str = "NAND(";
                if ((first_index_nand = line.find(nand_str)) != string::npos)
                {
                    gate_name = line.substr(0, first_index_nand - 3);
                    cout<<"\nGate name: "<<gate_name;

                    first_index_nand += nand_str.length() - 1;
                    cout<<"\nInput to this gate: ";
                    for (; first_index_nand != string::npos; first_index_nand = second_index_nand)
                    {
                        if ((second_index_nand = line.find_first_of(",)", first_index_nand)) != string::npos)
                        {
                            string input_name = line.substr(first_index_nand + 1, second_index_nand++ - first_index_nand - 1);
                            cout<<" "<<input_name;
                        }
                    }
                }
                cout<<"\n";

    }

}

有更多OO approch

  #include <iostream>
#include <fstream>
#include <string>
#include <algorithm>

using namespace std;

class FileParser
{
public:
    FileParser (const string fname)
    {
        ifile.open(fname.c_str());
        if(!ifile.is_open())
        {
            exit(1);
        }
    }
    ~FileParser()
    {
        ifile.close();
    }
    void Parse()
    {
        string line;

        while(getline(ifile, line)){


        line =  trimWhiteSpaces(line);

        size_t  first_index_nand, second_index_nand;
        string gate_name;

        const string nand_str = "NAND(";
        if ((first_index_nand = line.find(nand_str)) != string::npos)
        {
        gate_name = line.substr(0, first_index_nand - 3);
        cout<<"\nGate name: "<<gate_name;

        first_index_nand += nand_str.length() - 1;
        cout<<"\nInput to this gate: ";
        for (; first_index_nand != string::npos; first_index_nand = second_index_nand)
        {
            if ((second_index_nand = line.find_first_of(",)", first_index_nand)) != string::npos)
            {

                string input_name = line.substr(first_index_nand + 1, second_index_nand++ - first_index_nand - 1);
                            cout<<" "<<input_name;
            }
           }
         }
         cout<<"\n";
    }
}
private:
    string trimWhiteSpaces(const string& line)
    {
        string l = line;

        l.erase(std::remove_if( l.begin(), l.end(), ::isspace ), l.end());

        return l;
    }

    ifstream ifile;

};

int main(int argc, char* argv[])
{

    FileParser fP("gates.bench");

    fP.Parse();
}