模擬打印文件樹,難點在文件夾的開閉,如果僅僅將子文件縮進,則問題很簡單,遞歸即可,題目要求顯示文件夾的開閉(用'|'),所以直接遞歸打印不能解決(因爲可能需要在前面打印'|'),這裏我選擇將需要打印的所有符號保存在一個緩衝區char型數組裏,修改緩衝區再打印緩衝區
#include <cstdio>
#include <cstring>
#include <iostream>
#include <string>
#include <vector>
#include <queue>
using namespace std;
#define MAX_NODE 200
#define MAX_ROW 12
#define MAX_COL 200
/*
|_#/usr[24]
|_*mark[17]
| |_hw.c[3]
| |_*course[13]
| |_aa.txt[12]
|_*alex[6]
|_hw.c[5]
*/
struct Node
{
string name;
size_t size;
bool isDir;
int printRow;
Node* parent;
vector<Node*> children;
} nodes[MAX_NODE], *root;
int nex;
Node* newNode(const string& s, size_t u, Node* f)
{
Node* p = nodes + nex++;
p->name = s;
p->size = u;
p->isDir = s[0] == '*';
p->parent = f;
p->children.clear();
return p;
}
size_t walk(Node* p)
{
if(p->isDir){
vector<Node*>& v = p->children;
for(int i = 0, n = v.size(); i < n; ++i){
p->size += walk(v[i]);
}
}
return p->size;
}
char graph[MAX_ROW][MAX_COL];
void gls(Node* p, int level, int& row)
{
// step 1: print this node
//figure out how many indent spaces are there
int offset = level << 3;
//leave indent spaces in front
if(p->parent){
for(int i = p->parent->printRow+1; i <= row; ++i){
graph[i][offset] = '|';
}
}
else graph[row][offset] = '|';
//print leading char
graph[row][offset+1] = '_';
//print "name[size]"
int n = sprintf(&graph[row][offset+2], "%s[%u]", p->name.c_str(), p->size);
//recover last space rewritten by sprintf
graph[row][offset+2+n] = ' ';
//mark the printing row
p->printRow = row++;
// step 2: print all children
if(p->isDir){
vector<Node*>& v = p->children;
for(int i = 0, n = v.size(); i < n; ++i){
gls(v[i], level + 1, row);
}
}
}
void rtrim(int n)
{
int i, j;
for(i = 0; i < n; ++i){
for(j = MAX_COL - 1; graph[i][j] == ' '; --j) ;
graph[i][j+1] = '\0';
}
}
void ls()
{
// step 0: init graph array
memset(graph, ' ', sizeof(graph));
// step 1: set print graph array
walk(root);
int row = 0;
gls(root, 0, row);
//step 2: trim graph array
rtrim(row);
//step 3: print the graph
for(int i = 0; i < row; ++i) puts(graph[i]);
}
void inputChildren(Node* fa)
{
string name;
size_t size;
while(cin.get() != '(');
while(cin >> name, name != ")"){
cin >> size;
fa->children.push_back(newNode(name, size, fa));
}
}
bool input()
{
string name;
size_t size;
if(cin >> name >> size, !cin) return false;
nex = 0;
root = newNode(name, size, NULL);
queue<Node*> q;
q.push(root);
while(!q.empty()){
for(int n = q.size(); n--; ){
Node* p = q.front(); q.pop();
if(p->isDir){
inputChildren(p);
vector<Node*>& v = p->children;
for(int i = 0, n = v.size(); i < n; ++i){
q.push(v[i]);
}
}
}
}
return true;
}
int main()
{
while(input()) ls();
return 0;
}