Chinaunix首页 | 论坛 | 博客
  • 博客访问: 988561
  • 博文数量: 158
  • 博客积分: 4380
  • 博客等级: 上校
  • 技术积分: 2367
  • 用 户 组: 普通用户
  • 注册时间: 2006-09-21 10:45
文章分类

全部博文(158)

文章存档

2012年(158)

我的朋友

分类: C/C++

2012-11-20 11:13:09

Tree包含名称,和子Tree列表,在流中形式形如:
a
        b
        c
                d
                e
        f
注1:  html中无法显示Tab符号,所以我以8个空格代替
注2:  不同的编译器应当使用不同的文本格式,比如VC++使用windows文本格式(\r\n作为行间隔),dev-cpp使用Unix文本格式(\n作为行间隔)。

// 测试通过 by g++3.4.2 和 vc++2005

1. Tree.h文件:
#ifndef __TREE_H__
#define __TREE_H__

#include
#include
#include

struct Tree
{
    friend std::istream& operator>>( std::istream& is, Tree& tree );
    friend std::ostream& operator<<( std::ostream& os, const Tree& tree );

    typedef std::vector sctype;
    static const char Split;

    Tree();
    explicit Tree( const std::string nodename );
    void swap( Tree& tree );

    std::string name;
    sctype subs;
};

inline void swap( Tree& lhs, Tree& rhs )
{
    lhs.swap( rhs );
}

#endif // __TREE_H__

2. Tree.cpp文件:
#include "Tree.h"
#include
using namespace std;

const char Tree::Split = '\t';

Tree::Tree()
{
}
Tree::Tree( const string nodename ) : name(nodename)
{
}
void Tree::swap( Tree& tree )
{
    name.swap( tree.name );
    subs.swap( tree.subs );
}

istream& operator>>( istream& is, Tree& tree )
{
    struct parse
    {
        void operator()( const string& line, size_t& level, string& name )
        {
            const char* whitespace = " \t\n";
            level = line.find_first_not_of( Tree::Split );
            if( level == string::npos ) level = line.size();
            size_t n1 = line.find_first_not_of( whitespace, level );
            if( n1 == string::npos )
            {
                name.erase();
            }
            else
            {
                size_t n2 = line.find_last_not_of( whitespace );
                name = line.substr( n1, n2-n1+1 );
            }
        }
    } parse;

    if( is.fail() ) return is;
    tree = Tree();

    typedef vector COLS;
    COLS cols;
    streampos prepos;
    for( string line; prepos=is.tellg(), getline(is,line); )
    {
        size_t level;
        string name;
        parse( line, level, name );
        if( name.empty() && tree.name.empty() && (is.flags() & is.skipws) )
        {
            continue;
        }
        if(  name.empty() || level>cols.size() || ( level==0 && !tree.name.empty() ) )
        {
            is.seekg( prepos );
            if( tree.name.empty() )
                is.setstate( ios::failbit );
            return is;
        }
        cols.resize( level+1 );
        if( level == 0 )
        {
            tree.name = name;
            cols.back() = &tree;
        }
        else
        {
            COLS::reverse_iterator b = cols.rbegin();
            COLS::reverse_iterator a = b; ++a;
            (*a)->subs.push_back( Tree(name) );
            (*b) = &(*a)->subs.back();
        }
    }
    if( !is.bad() && is.eof() && !tree.name.empty() )
        is.clear();
    return is;
}

ostream& operator<<( ostream& os, const Tree& tree )
{
    os << tree.name << '\n';
    size_t level = 1;
    typedef pair COL;
    vector cols( 1, COL(tree.subs.begin(),tree.subs.end()) );

    for( ; ; )
    {
        if( cols.back().first == cols.back().second )
        {
            --level;
            cols.pop_back();
            if( level == 0 ) break;
            ++cols.back().first;
        }
        else
        {
            os << setw((streamsize)level) << setfill(Tree::Split) << "" << cols.back().first->name << '\n';
            ++level;
            cols.push_back( COL(cols.back().first->subs.begin(),cols.back().first->subs.end()) );
        }
    }
    return os;
}

3. 测试文件:
#include "Tree.h"
#include
#include
using namespace std;

int main( int argc, char *argv[] )
{
    ifstream file( "test.txt" );
    for( Tree tree; file>>tree; cout<    cout << "-------------" << endl;
    file.clear();
    for( string line; getline(file,line); cout<
    return EXIT_SUCCESS;
}
test.txt文件内容:
a
        b
        c
                dm
                e
        f
a2
        b
        c
                   "test"   

                e
        f
输出:
a
        b
        c
                dm
                e
        f
a2
        b
        c
                "test"
-------------
                e
        f

阅读(858) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~