I am trying to make a c++ program that emulates parts of a linux filesystem.
I have a vector<Node*>. In order to add to it I have to first create a Node* that I then .push_back() to the vector, right? Is it possible to .push_back() without having to first create another Node* to push_back()?
Another problem is that I cannot invoke any methods on the nodes inside of the vector<Node*>. In order to do anything with them like, say, use a GetName() method on it, I have to first create a Node* with the index of the vector that has the data I want to use. I am fairly certain that this way of going about it is what's causing me so much grief.
What's killing me right now is that when I test all the associated methods in a separate main.cpp file, they all cooperate and do what I want. When I run them through a TEST_CASE however, they misbehave and cause a crash. I can't think of anything that could be causing these problems mostly because they behave in a main method.
For Reference, here's all my code: node.hpp:
#ifndef NODE_HPP
#define NODE_HPP
using namespace std;
#include <string>
#include <vector>
class Node {
private:
char type;
string name;
vector<Node*> children;
Node* parent;
void RemoveHelper(Node* subtree);
public:
Node(string name, char type);
Node();
~Node();
void AddChild(Node* child);
void AddChild(string name, char type);
bool RemoveChild(string name);
void SetParent(Node* parent);
void SetType(char type);
Node* GetChild(string name);
vector<Node*> GetChildren();
Node* GetParent();
char GetType();
string GetName();
};
#endif
node.cpp:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
#include "node.hpp"
void Node::RemoveHelper(Node* subtree){
for (int j = 0; j < subtree->GetChildren().size(); j++){
//cout << j << " ";
Node* n = subtree->GetChildren()[j];
if (!n->GetChildren().empty()){
for (int i = 0; i < n->GetChildren().size(); i++){
//cout << i << endl;
RemoveHelper(subtree->GetChildren()[i]);
subtree->RemoveChild(n->GetName());
}
}
}
}
Node::Node(){
name = "";
type = ' ';
parent = nullptr;
}
Node::Node(string name, char type){
this->name = name;
this->type = type;
parent = nullptr;
}
Node::~Node(){
children.clear();
}
void Node::AddChild(string name, char type){
Node* n = new Node(name, type);
AddChild(n);
delete n;
}
void Node::AddChild(Node* child){
children.push_back(child);
}
bool Node::RemoveChild(string name){
Node* n = GetChild(name);
for (int i = 0; i < children.size(); i++){
if (n == children[i]){
RemoveHelper(children[i]);
children.erase(children.begin()+i);
//delete n;
return true;
}
}
return false;
}
void Node::SetParent(Node * parent){
this->parent = parent;
}
void Node::SetType(char type){
this->type = type;
}
Node* Node::GetChild(string name){
for (int i = 0; i < children.size(); i++){
Node* n = children[i];
if (n->GetName() == name){
//delete n;
return children[i];
}
//delete n;
}
return nullptr;
}
vector<Node*> Node::GetChildren(){
return children;
}
Node* Node::GetParent(){
return parent;
}
char Node::GetType(){
return type;
}
string Node::GetName(){
return name;
}
filesystem.hpp:
#ifndef FILESYSTEM_HPP
#define FILESYSTEM_HPP
using namespace std;
#include <string>
#include "node.hpp"
class FileSystem {
private:
Node* root;
Node* currentDirectory;
void AddNode(Node* newNode);
Node* FindNode(string name);
public:
FileSystem();
~FileSystem();
string mkdir(string name);
string touch(string name);
string pwd();
string ls();
string rm(string name);
string mv(string from, string to);
string cd(string dirname);
};
#endif
filesystem.cpp
#include <iostream>
#include <string>
using namespace std;
#include "filesystem.hpp"
#include "node.hpp"
void FileSystem::AddNode(Node* newNode){
currentDirectory->AddChild(newNode);
currentDirectory->GetChild(newNode->GetName())->SetParent(currentDirectory);
}
Node* FileSystem::FindNode(string name){
return currentDirectory->GetChild(name);
}
FileSystem::FileSystem(){
root = new Node("root", 'd');
currentDirectory = root;
}
FileSystem::~FileSystem(){
for (int i = root->GetChildren().size(); i > i; i--){
Node* n = root->GetChildren()[i];
root->RemoveChild(n->GetName());
//delete n;
}
delete root;
for (int i = currentDirectory->GetChildren().size(); i > 0; i--){
Node* n = currentDirectory->GetChildren()[i];
currentDirectory->RemoveChild(n->GetName());
delete n;
}
delete currentDirectory;
}
string FileSystem::mkdir(string name){
if (currentDirectory->GetChild(name) == nullptr){
Node* n = new Node(name, 'd');
AddNode(n);
return "directory " + name + " created successfully";
}
return "Error: " + name + " exists";
}
string FileSystem::touch(string name){
if (currentDirectory->GetChild(name) == nullptr){
currentDirectory->AddChild(name, 'f');
return "file " + name + " created successfully";
}
return "Error: " + name + " exists";
}
// I know that this only works for up to 3 directories. That's fine for this project.
string FileSystem::pwd(){
string ret = "/" + root->GetName();
if (root != currentDirectory){
if (currentDirectory->GetParent() != root){
ret += "/" + currentDirectory->GetParent()->GetName();
}
ret += "/" + currentDirectory->GetName();
}
return ret;
}
string FileSystem::ls(){
string ret = "";
for (int i = 0; i < currentDirectory->GetChildren().size(); i++){
Node* n = currentDirectory->GetChildren()[i];
ret += n->GetType();
ret += " " + n->GetName() + "\n";
//delete n;
}
return ret;
}
string FileSystem::rm(string name){
if (currentDirectory->RemoveChild(name)){
return name + " removed successfully";
}
return "No such file or directory";
}
string FileSystem::mv(string from, string to){
currentDirectory->AddChild(to, currentDirectory->GetChild(from)->GetType());
currentDirectory->RemoveChild(from);
return "file/dir renamed successfully";
}
string FileSystem::cd(string dirname){
cout << currentDirectory->GetChild("dir");
if ((dirname == ".." && currentDirectory == root) || dirname == currentDirectory->GetName()){
return "can't change to directory " + dirname;
}
else if (dirname == ".."){
currentDirectory = root;
}
else if (currentDirectory->GetChild(dirname) == nullptr){
return "can't change to directory " + dirname;
}
else{
currentDirectory = currentDirectory->GetChild(dirname);
}
return pwd();
}
One of the test files:
#include "catch/catch.hpp"
#include "../filesystem.hpp"
TEST_CASE("Test creating a file system")
{
FileSystem fs;
CHECK ("/root" == fs.pwd());
CHECK ("" == fs.ls());
}
TEST_CASE ("Test touch and mkdir")
{
FileSystem fs;
CHECK ("file file1 created successfully" == fs.touch("file1"));
CHECK ("Error: file1 exists" == fs.touch("file1"));
CHECK ("file file2 created successfully" == fs.touch("file2"));
CHECK ("directory dir1 created successfully" == fs.mkdir("dir1"));
CHECK ("Error: dir1 exists" == fs.mkdir("dir1"));
CHECK ("Error: dir1 exists" == fs.touch("dir1"));
CHECK ("f file1\nf file2\nd dir1\n" == fs.ls());
CHECK ("/root" == fs.pwd());
}
If there is anything else anyone catches that could help avoid other issues I haven't caught yet, that would also be greatly appreciated.
Aucun commentaire:
Enregistrer un commentaire