文件目录管理与显示
给出目录和文件信息,编程实现将其排列成一棵有一定缩进的树。
要求:
(1)设计文件和目录信息树的存储结构。
(2)从文件或键盘输入目录和文件信息,输入格式采用绝对路径法,即:
\A
\A\AA1
\A\AA1\aa1.doc
…
创建时要检查同一路径下不能有同名的目录或文件名。
(3)设计文件和目录信息树的输出格式(以凹入表的形式显示)。
(4)查找指定目录和文件。
(5)添加新目录或新文件。
(6)删除指定目录或文件,子目录能够被删除的前提是其为空,既不包含任何子目录和文件;根目录不能删除。
(7)扩充目录或文件信息,如创建时间、读写权限、文件长度或子目录包含的子目录和文件数等。
(8)对同一层次下的子目录或文件按创建时间有序输出。
(9)通配符的使用。如用“?”代表任意一个字符,用“*”表示任意多个任意字符。
扩展内容:
实现相对路径表示法。
#include <stdio.h>
#include <malloc.h>
#include <string>
#include <iostream>
#include <sstream>
using namespace std;
#include "Sibtree.h"
void add(SibTree *t1)
{
printf("输入目录文件信息以输入0结束:\n");
SibTreeNode *r, *r1, *r2;
char ifm[1000] = { '\0' }, name1[50], name2[50];
char *str;
int i, j, n;
while (1)
{
cin >> ifm;
str = ifm;
if (*str == '0')break;
r = t1->root;
if (r == NULL)
{
for (i = 0, str += 1; *str != '\\'&&*str != '\0'; str++, i++)
{
name1[i] = *str;
}
name1[i] = '\0';
if (*str == '\0')insertRoot(t1, name1);
else
printf("%s的路径不存在,不能添加\n", name1);
}
else
{
for (i = 0, str += 1; *str != '\\'&&*str != '\0'; str++, i++)
{
name1[i] = *str;
}
name1[i] = '\0';
if (search(t1, name1) == 0 && *str == '\0')
{
insertnextSibing(t1, r, name1);
}
if (search(t1, name1) == 0 && *str != '\0')printf("%s的路径不存在,不能添加\n", name1);
r1 = LevelOrderTraverse(t1->root, name1);
while (r1 != NULL)
{
if (*str == '\0')break;
for (i = 0, str += 1; *str != '\\'&&*str != '\0'; str++, i++)
{
name2[i] = *str;
}
name2[i] = '\0';
if (*str == '\0')
{
if (insertChild(t1, r1, name2)){ break; }
}
else
{
n = children(r1);
for (j = 1; j <= n; j++)
{
if (strcmp(child(r1, j)->data, name2) == 0)break;
}
if (j <= n)r2 = child(r1, j);
else r2 = NULL;
if (r2 == NULL)printf("%s的路径不存在,不能添加\n", name2);
}
n = children(r1);
for (j = 1; j <= n; j++)
{
if (strcmp(child(r1, j)->data, name2) == 0)break;
}
if (j <= n)r1 = child(r1, j);
else r1 = NULL;
}
}
}
}
void check(SibTree *t)
{
SibTreeNode *r;
printf("输入要查找的文件名:");
char name[50];
cin >> name;
r = *1LevelOrderTraverse(t->root, name);
if (r == NULL)
//printf("没有此文件\n");
printf("\n");
else
{
printf("此文件找到,创建时间为:");
printf("%d/%d/%d %d:%d:%d", r->year, r->month, r->day, r->hour, r->minute, r->second);
printf("\t子目录个数为:");
printf("%d\n", children(r));
}
}
void Delete(SibTree *t)
{
SibTreeNode *r, *p, *kid;
printf("输入要删除的文件名:");
char name[50];
cin >> name;
r = LevelOrderTraverse(t->root, name);
if (r == NULL)printf("没有此文件!\n");
else
{
if (r->firstChild != NULL)printf("有子文件不能删除!\n");
else
{
p = r->parent;
kid = p->firstChild;
if (strcmp(kid->data, r->data) == 0)p->firstChild = kid->nextSibling;
else
{
while (strcmp(kid->nextSibling->data, r->data))kid = kid->nextSibling;
kid->nextSibling = kid->nextSibling->nextSibling;
}
printf("已删除!\n");
}
}
}
void out(SibTree *t)
{
printf("输出文件目录的信息:\n");
printf("root:\n");
printf("%s", toString(t).c_str());
}
void repair(SibTree *t)//修改扩充
{
SibTreeNode *r, *p, *kid;
printf("输入想要扩充或修改的文件或目录的名称\n");
char name[100];
cin >> name;
r = LevelOrderTraverse(t->root, name);
if (r == NULL)
printf("没有此文件!\n");
else
{
printf(" 查找成功\n\n 1 修改or 2扩充?\n\n\n");
int k;
cin >> k;
if (k == 1)
{
printf("输入目录或文件的新名称 \n");
char Name[100];
cin >> Name;
strcpy(r->data, Name);
printf(" 修改成功!\n\n");
printf(" 修改时间为:");
printf("%d年/%d月/%d日 %d时:%d分:%d秒\n\n\n", sys.wYear, sys.wMonth, sys.wDay, sys.wHour, sys.wMinute, sys.wSecond);
r->year = sys.wYear;
r->month = sys.wMonth;
r->day = sys.wDay;
r->hour = sys.wHour;
r->minute = sys.wMinute;
r->second = sys.wSecond;
}
else
{
printf("当前目录的信息为:\n 限制子目录的个数 %d 个 限制子文件的个数 %d 个\n", r->sonmulu, r->sonfile);
printf("请输入修改后的限制子目录的个数和限制子文件的个数:\n");
int a, b;
cin >> a >> b;
r->sonmulu = a;
r->sonfile = b;
printf("修改成功!\n\n\n");
}
}
}
void *check(SibTree *t)
{
SibTreeNode *r;
printf("输入要查找的文件或目录名:");
char name[50];
cin >> name;
r = *LevelOrderTraverse(t->root, name);
if (r == NULL) //printf("没有此文件\n");
printf("\n");
else
{
printf("此文件或目录找到,创建时间为:");
printf("%d/%d/%d %d:%d:%d", r->year, r->month, r->day, r->hour, r->minute, r->second);
printf("\t子目录个数为:");
printf("%d\n", children(r));
}
}
void main()
{
SibTree t1;
int k;
TreeInitiate(&t1);
while (1)
{
printf("\n");
printf("\t 文件管理 \t\n");
printf("\t********************************************************\t\n");
printf("\t *************对照号码输入你要进行的操作*************\n");
printf("\t 1 ——>添加目录或文件 \n");
printf("\t 2 ——>查找目录或文件 \n");
printf("\t 3 ——>删除目录或文件 \n");
printf("\t 4 ——>输出文件信息 \n");
printf("\t 5 ——>扩充目录或文件信息 \n");
printf("\t 6 ——>模糊查找 \n");
printf("\t 7 ——>退出 \n");
printf("输入你想进行的操作号码:");
scanf("%d", &k);
if (k == 7)break;
switch (k)
{
case 1: add(&t1); break;
case 2: check(&t1); break;
case 3: Delete(&t1); break;
case 4: out(&t1); break;
case 5: repair(&t1); break;
case 6: *check(&t1); break;
default:
printf("输入号码错误!\n");
}
}
}
#include <windows.h>
#include <queue>
SYSTEMTIME sys;
int ok;
typedef struct SibTreeNode
{
char data[50];
int valid;
int year;
int month;
int day;
int hour;
int minute;
int second;
int sonmulu;
int sonfile;
struct SibTreeNode * parent;
struct SibTreeNode *firstChild;
struct SibTreeNode *nextSibling;
}SibTreeNode;
typedef struct
{
SibTreeNode *root;
int size;
}SibTree;
typedef SibTreeNode *QueueDataType;
#include "SeqCQueue.h"
int IsTreeEmpty(SibTree *t)
{
return t->size == 0;
}
int isValidNode(SibTreeNode *p)
{
if (p)
return p->valid;
else return 0;
}
//创建一个空树
void TreeInitiate(SibTree *t)
{
t->root = NULL;
t->size = 0;
}
//创建结点
SibTreeNode * newSibTreeNode(char x[50])
{
GetLocalTime(&sys);
SibTreeNode *p = (SibTreeNode *)malloc(sizeof(SibTreeNode));
strcpy(p->data, x);
p->valid = true;
p->year = sys.wYear;
p->month = sys.wMonth;
p->day = sys.wDay;
p->hour = sys.wHour;
p->minute = sys.wMinute;
p->second = sys.wSecond;
p->sonmulu = 5; //扩充的信息,限制子目录的个数
p->sonfile = 2; //限制子文件的个数
p->parent = NULL;
p->firstChild = NULL;
p->nextSibling = NULL;
return p;
}
//创建包含一个结点的树
void onenodeSibTree(SibTree *t, char x[50])
{
t->root = newSibTreeNode(x);
strcpy(t->root->data, x);
t->size = 1;
}
//输出当前结点的父亲节点
SibTreeNode *root(SibTreeNode *p)
{
if (p == NULL)
{
p = (SibTreeNode*)malloc(sizeof(SibTreeNode));
return p;
}
else
{
return p;
}
}
//插入根节点
void insertRoot(SibTree *t, char x[50])
{
SibTreeNode * newRoot = newSibTreeNode(x);
newRoot->firstChild = t->root;
if (t->root != NULL)
{
t->root->parent = newRoot;
}
t->root = newRoot;
t->size++;
}
// 输出树的大小
int size(SibTree *t)
{
return t->size;
}
// 构造一个不合法的结点
SibTreeNode * invalidSibTreeNode()
{
SibTreeNode *p = (SibTreeNode *)malloc(sizeof(SibTreeNode));
p->valid = false;
return p;
}
//当前结点的孩子的个数
int children(SibTreeNode *p)
{
int count = 0;
SibTreeNode *countNode;
if (isValidNode(p))
{
countNode = p->firstChild;
while (countNode != NULL)
{
count++;
countNode = countNode->nextSibling;
}
return count;
}
else
{
return 0;
}
}
//返回当前结点的cth孩子结点
SibTreeNode *child(SibTreeNode *p, int c)
{
if (isValidNode(p))
{
if (c < 1)
{
return invalidSibTreeNode();
}
SibTreeNode *kid = p->firstChild;
while ((kid != NULL) && (c > 1))
{
kid = kid->nextSibling;
c--;
}
if (kid == NULL)
{
return invalidSibTreeNode();
}
else
{
return kid;
}
}
else
throw "the node is not a valid node!";
}
//返回当前结点的兄弟结点
SibTreeNode *nextSibling(SibTreeNode *p)
{
if (isValidNode(p))
{
if (p->nextSibling == NULL)
{
return invalidSibTreeNode();
}
else
{
return p->nextSibling;
}
}
else
{
throw "the node is not a valid node!";
return invalidSibTreeNode();
}
}
//插入孩子结点
int insertChild(SibTree *t, SibTreeNode *p, char x[50])
{
SibTreeNode *n;
int i, flog = 0;
for (i = 0; x[i] != '\0'; i++)
{
if (x[i] == '.'){ flog = 1; break; }
}
if (isValidNode(p))
{
n = p->firstChild;
if (n == NULL)
{
p->firstChild = newSibTreeNode(x);
p->firstChild->parent = p;
}
else
{
while (n != NULL)
{
if (strcmp(n->data, x) == 0){ printf("输入的文件有重名,请更改名字!"); break; }
if (n->nextSibling == NULL)break;
n = n->nextSibling;
}
if (strcmp(n->data, x) != 0)
{
if (flog == 1 && children(n->parent)<n->parent->sonfile)
{
n->nextSibling = newSibTreeNode(x); n->nextSibling->parent = p;
}
else
if (flog == 1)printf("文件数超出,不能继续存储\n");
else
if (flog == 0 && children(n->parent)<n->parent->sonmulu) { n->nextSibling = newSibTreeNode(x); n->nextSibling->parent = p; }
else if (flog == 0)printf("子目录超出,不能继续存储\n");
}
}
t->size++;
return 1;
}
else return 0;
}
//为当前结点插入兄弟结点
int insertnextSibing(SibTree *t, SibTreeNode *p, char x[50])
{
SibTreeNode *n;
if (isValidNode(p))
{
n = p->nextSibling;
if (n == NULL)p->nextSibling = newSibTreeNode(x);
else
{
while (n->nextSibling != NULL)n = n->nextSibling;
n->nextSibling = newSibTreeNode(x);
n->nextSibling->parent = p->parent;
}
t->size++;
return 1;
}
else return 0;
}
int *check(char a[], char b[])
{
int len = strlen(b);
int len1 = strlen(a);
for (int i = 0; i < len; i++)
{
if (b[i] == '*')
{
int j = len - 1;
int k = len1 - 1;
while (j != i)
{
if (b[j] != a[k])
return 0;
--j;
--k;
}
return 1;
}
else if (b[i] != '?')
{
if (a[i] != b[i])
return 0;
}
}
return 1;
}
//模糊查找
SibTreeNode **LevelOrderTraverse(SibTreeNode *t, char a[50])
{
int ok = 0;
SeqCQueue Q;
SibTreeNode *x;
if (t == NULL)return NULL;
QueueInitiate(&Q);
QueueAppend(&Q, t);
x = t->nextSibling;
while (x != NULL)
{
QueueAppend(&Q, x);
x = x->nextSibling;
}
while (QueueNotEmpty(Q))
{
QueueDelete(&Q, &x);
if (*check(x->data, a) == 1)
{
ok = 1;
printf("查找到符合条件的有");//%s\n",x->data);
////////
SibTreeNode *xx;
xx = x;
char sss[100][100];
char gan = '\\';
int len = 0;
while (xx!=root(t) )//&& xx->parent != NULL)
{
strcpy(sss[len++],xx->data);
//printf("\%s ",xx->data);
xx=xx->parent;
}
if (strcmp(sss[len-1],"\\")!=0)
printf("%ca",gan);
for(int i=len-1;i>=0;i--)
{
printf("%c",gan);
printf("%s",sss[i]);
}
printf("\n");
///////////
}
x = x->firstChild;
while (x != NULL)
{
QueueAppend(&Q, x);
x = x->nextSibling;
}
}
if (!ok) printf("不存在此文件或目录\n");
return x;
}
SibTreeNode **1LevelOrderTraverse(SibTreeNode *t, char a[50])
{
int ok = 0;
SeqCQueue Q;
SibTreeNode *x;
if (t == NULL)return NULL;
QueueInitiate(&Q);
QueueAppend(&Q, t);
x = t->nextSibling;
while (x != NULL)
{
QueueAppend(&Q, x);
x = x->nextSibling;
}
while (QueueNotEmpty(Q))
{
QueueDelete(&Q, &x);
if (strcmp(x->data, a) == 0)
{
ok = 1;
printf("查找到符合条件的有");//%s\n",x->data);
////////
SibTreeNode *xx;
xx = x;
char sss[100][100];
char gan = '\\';
int len = 0;
while (xx!=root(t) )//&& xx->parent != NULL)
{
strcpy(sss[len++],xx->data);
//printf("\%s ",xx->data);
xx=xx->parent;
}
if (strcmp(sss[len-1],"\\")!=0)
printf("%ca",gan);
for(int i=len-1;i>=0;i--)
{
printf("%c",gan);
printf("%s",sss[i]);
}
printf("\n");
///////////
}
x = x->firstChild;
while (x != NULL)
{
QueueAppend(&Q, x);
x = x->nextSibling;
}
}
if (!ok) printf("不存在此文件或目录\n");
return x;
}
//层序遍历
SibTreeNode *LevelOrderTraverse(SibTreeNode *t, char a[50])
{
SeqCQueue Q;
SibTreeNode *x;
if (t == NULL)return NULL;
QueueInitiate(&Q);
QueueAppend(&Q, t);
x = t->nextSibling;
while (x != NULL)
{
QueueAppend(&Q, x);
x = x->nextSibling;
}
while (QueueNotEmpty(Q))
{
QueueDelete(&Q, &x);
if (strcmp(x->data, a) == 0)break;
x = x->firstChild;
while (x != NULL)
{
QueueAppend(&Q, x);
x = x->nextSibling;
}
}
return x;
}
//查找是否存在
int search(SibTree *t, char x[50])
{
if (LevelOrderTraverse(t->root, x) == NULL)return 0;
else return 1;
}
string preorderString(SibTreeNode *currentNode, int depth)
{
string s = " ";
stringstream out;
if (currentNode == NULL)
{
return "";
}
for (int i = 0; i < depth; i++)
{
s = s + " ";
}
out << currentNode->data;
s += out.str();
s += "\n";
s += preorderString(currentNode->firstChild, depth + 1);
s += preorderString(currentNode->nextSibling, depth);
return s;
}
string toString(SibTree *t)
{
return preorderString(t->root, 0);
}
typedef struct
{
QueueDataType queue[50];
int front;
int rear;
int count; /* 队列的当前表长 */
} SeqCQueue;
//初始化
void QueueInitiate(SeqCQueue *Q)
{
Q->front = 0;
Q->rear = 0;
Q->count = 0;
}
//判断队列非空
int QueueNotEmpty(SeqCQueue Q)
{
if (Q.count != 0) return 1;
else return 0;
}
//入队列
int QueueAppend(SeqCQueue *Q, QueueDataType x)
{
if (Q->count>0 && Q->rear == Q->front)
{
printf("队列已满无法插入!\n");
return 0;
}
else
{
Q->queue[Q->rear] = x;
Q->rear = (Q->rear + 1) % 50;
Q->count++;
return 1;
}
}
//出队列
int QueueDelete(SeqCQueue *Q, QueueDataType *x)
{
if (Q->count == 0)
{
printf("队列已空无数据元素出队列!\n");
return 0;
}
else
{
*x = Q->queue[Q->front];
Q->front = (Q->front + 1) % 50;
Q->count--;
return 1;
}
}
//取对头数据元素
int QueueGet(SeqCQueue *Q, QueueDataType *x)
{
if (Q->count == 0)
{
printf("队列已空无数据元素出队列!\n");
return 0;
}
else
{
*x = Q->queue[Q->front];
return 1;
}
}
测试数据:
1
\a
\a\aad
\a\abcde
\a\abcde\fghij
\a\abcde\fghij\aaaaabbbbb.doc
\a\aad\aa
\a\aad\aa\aaa
\a\aad\aa\aaa\aaaaaa.doc
0
4
2
aa
3
aaaaaa.doc
4
5
aaa
1
asd
4
5
asd
2
12 3
6
a?d
4
1
\a\aad\aa\asd\aaaaabbbbb.doc
0
4
6
aa*bb.doc
6
aa*cc.doc
4
6
a*