・main.c
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include "directorytree.h"
DirNode* createSample() {
DirNode* aDir = createDirNode("a");
DirNode* bDir = createDirNode("b");
DirNode* cDir = createDirNode("c");
DirNode* dDir = createDirNode("d");
FileNode* xFile = createFileNode("x.txt");
FileNode* yFile = createFileNode("y.txt");
FileNode* zFile = createFileNode("z.txt");
FileNode* wFile = createFileNode("w.txt");
addChildDir(aDir, bDir);
addChildDir(aDir, cDir);
addChildDir(cDir, dDir);
addChildFile(aDir, xFile);
addChildFile(bDir, yFile);
addChildFile(bDir, zFile);
addChildFile(bDir, wFile);
return aDir;
}
/**
* @desc ファイルの表示
* @param (fileNode) Fileへのポインタ
* @param (indent) 表示インデント
*/
void printFileNode(FileNode* fileNode, size_t indent){
assert(fileNode);
for (int i = 0; i < indent; ++i) {
// インデントを設定
printf(" ");
}
printf("File: %s\n", fileNode->name);
}
/**
* @desc ディレクトリ構造の表示
* @param (dirNode) ディレクトリへのポインタ
* @param (indent) 表示インデント
*/
void printDirNode(DirNode* dirNode, size_t indent){
assert(dirNode);
for (int i = 0; i < indent; ++i) {
// インデントを設定
printf(" ");
}
printf("Dir: %s\n", dirNode->name);
for (int i = 0; i < dirNode->childFileNum; ++i) {
printFileNode(dirNode->fileChildren[i], indent+1);
}
for (int i = 0; i < dirNode->childDirNum; ++i) {
printDirNode(dirNode->dirChildren[i], indent+1);
}
}
/**
* @desc ディレクトリ配下で指定した名前のファイルを検索する
* @param (dirNode) ディレクトリ
* @param (fileName) ファイル名
* @return 見つかったらファイルノードのポインタを返す
* 見つからなかったらNULLを返す
*/
FileNode* findFileByNameUnderDir(DirNode* dirNode, const char* fileName) {
/*ここ*/
}
/**
* @desc ディレクトリ以下にあるファイルの総数を数える
* @param (dirNode) ディレクトリ
* @return ディレクトリ以下にあるファイルの総数
*/
size_t countFilesUnderDir(DirNode* dirNode) {
size_t count=0;
count+=dirNode->childFileNum;
for(int i=0; i<dirNode->childDirNum; i++) {
count+=countFilesUnderDir(dirNode->dirChildren[i]);
}
return count;
}
/**
* 確認プログラム
* assertに引っかからなければOK
* 簡略のためエラー処理は省略しています
*/
int main(int argc, const char* argv[])
{
DirNode* aDir = createSample();
printDirNode(aDir, 0);
DirNode* bDir = getChildDir(aDir, 0);
DirNode* cDir = getChildDir(aDir, 1);
FileNode* xFile = findFileByNameUnderDir(aDir, "x.txt");
assert(xFile);
assert(0 == strcmp(xFile->name, "x.txt"));
FileNode* wFile = findFileByNameUnderDir(aDir, "w.txt");
assert(wFile);
assert(0 == strcmp(wFile->name, "w.txt"));
FileNode* uFile = findFileByNameUnderDir(aDir, "u.txt");
assert(!uFile);
size_t a = countFilesUnderDir(aDir);
assert(a == 4);
size_t b = countFilesUnderDir(bDir);
assert(b == 3);
size_t c = countFilesUnderDir(cDir);
assert(c == 0);
deleteDirNode(aDir);
return 0;
}
#define _CRT_SECURE_NO_WARNINGS
#include <assert.h>
#include <string.h>
#include <stdlib.h>
#include "directorytree.h"
/**
* @desc FileNodeの作成
* @param (name) 名前 (NAME_MAX-1文字以内)
* @return FileNodeへのポインタ.メモリ確保失敗時はNULLを返す.
* @detail 動的にメモリ確保しているため,
* 不要になったらdeleteFileNodeを呼んで削除すること.
*/
FileNode* createFileNode(const char* name) {
assert(name);
FileNode* fileNode = (FileNode*)calloc(1, sizeof(FileNode));
if (fileNode) {
strncpy(fileNode->name, name, NAME_MAX);
fileNode->name[NAME_MAX-1] = '\0';
}
return fileNode;
}
/**
* @desc FileNodeの削除
* @param (fileNode) FileNodeへのポインタ
* @detail 不要になったFileNodeをfreeで削除する.
*/
void deleteFileNode(FileNode* fileNode){
assert(fileNode);
free(fileNode);
}
/**
* @desc File名の取得
* @param (fileNode) FileNodeへのポインタ
* @return FileNode名
*/
const char* getFileName(FileNode* fileNode){
assert(fileNode);
return fileNode->name;
}
/**
* @desc 親ディレクトリの取得
* @param (fileNode) FileNodeへのポインタ
* @return 親DirNode
*/
DirNode* getParentDirOfFile(FileNode* fileNode){
assert(fileNode);
return fileNode->parent;
}
/**
* @desc DirNodeの作成
* @param (name) 名前 (NAME_MAX-1文字以内)
* @return DirNodeへのポインタ.メモリ確保失敗時はNULLを返す.
* @detail 動的にメモリ確保しているため,
* 不要になったらdeleteDirNodeを呼んで削除すること.
*/
DirNode* createDirNode(const char* name){
assert(name);
DirNode* dirNode = (DirNode*)calloc(1, sizeof(DirNode));
if (dirNode) {
strncpy(dirNode->name, name, NAME_MAX);
dirNode->name[NAME_MAX-1] = '\0';
}
return dirNode;
}
/**
* @desc DirNodeの削除
* @param (dirNode) 削除するDirNode
* @detail 不要になったDirNodeをfreeで削除する.
* 登録されている子要素も削除する.
*/
void deleteDirNode(DirNode* dirNode){
assert(dirNode);
for (int i = 0; i < dirNode->childDirNum; ++i) {
deleteDirNode(dirNode->dirChildren[i]);
}
free(dirNode->dirChildren);
for (int i = 0; i < dirNode->childFileNum; ++i) {
deleteFileNode(dirNode->fileChildren[i]);
}
free(dirNode->fileChildren);
free(dirNode);
}
/**
* @desc ディレクトリ名の取得
* @param (dirNode) DirNodeへのポインタ
* @return DirNode名
*/
const char* getDirName(DirNode* dirNode) {
assert(dirNode);
return dirNode->name;
}
/**
* @desc 親ディレクトリの取得
* @param (dirNode) DirNodeへのポインタ
* @return 親DirNode
*/
DirNode* getParentDirOfDir(DirNode* dirNode){
assert(dirNode);
return dirNode->parent;
}
/**
* @desc 子ディレクトリの個数の取得
* @param (dirNode) DirNodeへのポインタ
* @return 子ディレクトリの個数
*/
size_t getChildDirNum(DirNode* dirNode){
assert(dirNode);
return dirNode->childDirNum;
}
/**
* @desc 子ディレクトリの取得
* @param (dirNode) 親ディレクトリのポインタ
* @param (i) 子ディレクトリのインデックス
* @return 子ディレクトリのポインタ
* インデックス外であればNULLを返す
*/
DirNode* getChildDir(DirNode* dirNode, size_t i){
assert(dirNode);
if (dirNode->childDirNum <= i) {
/* インデックス外 */
return NULL;
}
return dirNode->dirChildren[i];
}
/**
* @desc 子ディレクトリの追加
* @param (parentDir) 親ディレクトリのポインタ
* @param (childDir) 追加する子ディレクトリ
* @return 成功したらNORMALLY_FINISHED,
* 失敗したらそれ以外を返す.
*/
int addChildDir(DirNode* parentDir, DirNode* childDir){
assert(parentDir);
assert(childDir);
if (parentDir->childDirNum >= parentDir->reservedDirNum) {
size_t new_size = parentDir->reservedDirNum * 2;
if (new_size == 0) {
new_size = 1;
}
DirNode** p = (DirNode**)realloc(parentDir->dirChildren, sizeof(DirNode*) * new_size);
if (!p) {
return ALLOCATION_ERROR;
}
parentDir->dirChildren = p;
parentDir->reservedDirNum = new_size;
}
parentDir->dirChildren[parentDir->childDirNum] = childDir;
parentDir->childDirNum += 1;
childDir->parent = parentDir;
return NORMALLY_FINISHED;
}
/**
* @desc 子ディレクトリの削除
* @param (parentDir) 親ディレクトリのポインタ
* @param (i) 削除する子ディレクトリのインデックス
* @return 成功したらNORMALLY_FINISHED,
* 失敗したらそれ以外を返す.
*/
int removeChildDir(DirNode* parentDir, size_t i){
if (parentDir->childDirNum <= i) {
return OUT_OF_RANGE_ERROR;
}
if (i < parentDir->childDirNum - 1) {
deleteDirNode(parentDir->dirChildren[i]);
memmove(parentDir->dirChildren + i,
parentDir->dirChildren + i+1,
(parentDir->childDirNum-i-1) * sizeof(DirNode*));
}
parentDir->childDirNum -= 1;
return NORMALLY_FINISHED;
}
/**
* @desc 子ファイルの個数の取得
* @param (dirNode) DirNodeへのポインタ
* @return 子ファイルの個数
*/
size_t getChildFileNum(DirNode* dirNode){
assert(dirNode);
return dirNode->childFileNum;
}
/**
* @desc 子ファイルの取得
* @param (dirNode) 親ディレクトリのポインタ
* @param (i)) 子ファイルのインデックス
* @return 子ファイルのポインタ
* インデックス外であればNULLを返す
*/
FileNode* getChildFile(DirNode* dirNode, size_t i){
assert(dirNode);
if (dirNode->childFileNum <= i) {
/* インデックス外 */
return NULL;
}
return dirNode->fileChildren[i];
}
/**
* @desc 子ファイルの追加
* @param (parentDir) 親ディレクトリのポインタ
* @param (childFile) 追加する子ファイル
* @return 成功したらNORMALLY_FINISHED,
* 失敗したらそれ以外を返す.
*/
int addChildFile(DirNode* parentDir, FileNode* childFile){
assert(parentDir);
assert(childFile);
if (parentDir->childFileNum >= parentDir->reservedFileNum) {
size_t new_size = parentDir->reservedFileNum * 2;
if (new_size == 0) {
new_size = 1;
}
FileNode** p = (FileNode**)realloc(parentDir->fileChildren, sizeof(FileNode*) * new_size);
if (!p) {
return ALLOCATION_ERROR;
}
parentDir->fileChildren = p;
parentDir->reservedFileNum = new_size;
}
parentDir->fileChildren[parentDir->childFileNum] = childFile;
parentDir->childFileNum += 1;
childFile->parent = parentDir;
return NORMALLY_FINISHED;
}
/**
* @desc 子ファイルの削除
* @param (parentDir) 親ディレクトリのポインタ
* @param (i) 削除する子ファイルのインデックス
* @return 成功したらNORMALLY_FINISHED,
* 失敗したらそれ以外を返す.
*/
int removeChildFile(DirNode* parentDir, size_t i){
if (parentDir->childFileNum <= i) {
return OUT_OF_RANGE_ERROR;
}
if (i < parentDir->childDirNum - 1) {
deleteFileNode(parentDir->fileChildren[i]);
memmove(parentDir->fileChildren + i,
parentDir->fileChildren + i+1,
(parentDir->childFileNum-i-1) * sizeof(FileNode*));
}
parentDir->childFileNum -= 1;
return NORMALLY_FINISHED;
}
#pragma once
#define NAME_MAX 100
#define NORMALLY_FINISHED 0
#define ALLOCATION_ERROR 1001
#define OUT_OF_RANGE_ERROR 1002
struct _dir_node;
typedef struct _file_node {
char name[NAME_MAX]; // ファイル名
struct _dir_node* parent; // 親ディレクトリ
} FileNode;
typedef struct _dir_node {
char name[NAME_MAX]; /* ディレクトリ名 */
struct _dir_node* parent; /* 親ディレクトリ */
struct _dir_node** dirChildren; /* 子ディレクトリ(複数かも) */
struct _file_node** fileChildren; /* 子ファイル(複数かも) */
int childDirNum; /* 子ディレクトリの数 */
int reservedDirNum; /* 子ディレクトリの配列の長さ */
int childFileNum; /* 子ファイルの数 */
int reservedFileNum; /* 子ファイルの配列の長さ */
} DirNode;
FileNode* createFileNode(const char* name);
void deleteFileNode(FileNode* fileNode);
const char* getFileName(FileNode* fileNode);
DirNode* getParentDirOfFile(FileNode* fileNode);
DirNode* createDirNode(const char* name);
void deleteDirNode(DirNode* dirNode);
const char* getDirName(DirNode* dirNode);
DirNode* getParentDirOfDir(DirNode* dirNode);
size_t getChildDirNum(DirNode* dirNode);
DirNode* getChildDir(DirNode* dirNode, size_t i);
int addChildDir(DirNode* parentDir, DirNode* childDir);
int removeChildDir(DirNode* parentDir, size_t i);
size_t getChildFileNum(DirNode* dirNode);
FileNode* getChildFile(DirNode* dirNode, size_t i);
int addChildFile(DirNode* parentDir, FileNode* childFile);
int removeChildFile(DirNode* parentDir, size_t i);