This is notepad that works with list of files (pages w/e) that can be edited (list). You can access each file separately and edit/view it too (rewrite, append, read). Here's my implementation of it. I have 2 classes that resemble menus (list of files, and file itself) both are inherited from interface and 1 class that edits files. Now the questions are:
- How spaghetti is my code
- Am I using interface in a right way here (is it needed)?
- Is there better way to implement mode selection? (I don't like it at all)
- What causes getline get empty line(s) before I send it to append() (I have to check for them)
Any other criticism is appreciated.
Menu.h
#pragma once
class Menu
{
private:
virtual int input() = 0;
public:
Menu() {}
Menu(const char*) {};
virtual int output() = 0;
virtual ~Menu() {}
};
FileMenu.h
#pragma once
#include "Menu.h"
#include "File.h"
#include <memory>
class FileMenu :
public Menu
{
private:
std::unique_ptr<File>m_f;
int input();
public:
FileMenu();
FileMenu(const char*);
~FileMenu();
int output();
};
FileMenu.cpp
#include "FileMenu.h"
#include <iostream>
#include <string>
FileMenu::FileMenu(){}
FileMenu::FileMenu(const char* path) :m_f(std::make_unique<File>(path)) {}
FileMenu::~FileMenu()
{
//delete m_f;
}
int FileMenu::input()
{
std::string mode;
std::cin >> mode;
if (!mode.compare("a"))
{
std::string buff;
while (buff.compare("/0")) //end of edit
{
if (buff.compare("")) //idk how to fix (if i use getline before append it will still get empty line and will write /0 to file (have to do another if)
{
m_f->append(buff.c_str());
//m_f->append("\n");
}
std::getline(std::cin, buff);
}
return 0;
}
if (!mode.compare("w"))
{
std::string buff;
m_f->clear();
while (buff.compare("/0"))
{
if (buff.compare(""))
{
m_f->append(buff.c_str());
//m_f->append("\n");
}
std::getline(std::cin, buff);
}
return 0;
}
if (!mode.compare("r"))
{
m_f->output(m_f->read());
system("pause"); //bad
return 0;
}
if (!mode.compare("e"))
{
return 1;
}
return -1;
}
int FileMenu::output()
{
do
{
system("cls");
std::cout << "\t(w)rite (a)ppend (r)ead (e)xit" << std::endl;
} while (input() != 1);
return 0;
}
MainMenu.h
#pragma once
#include "Menu.h"
#include "File.h"
#include <memory>
class MainMenu :
public Menu
{
private:
std::unique_ptr<File>m_f;
int input();
public:
MainMenu();
MainMenu(const char*);
~MainMenu();
int output();
};
MainMenu.cpp
#include "MainMenu.h"
#include "FileMenu.h"
#include "File.h"
#include <iostream>
#include <string>
#include <algorithm>
#include <cctype>
MainMenu::MainMenu(){}
MainMenu::MainMenu(const char * path) :m_f(std::make_unique<File>(path)) {}
MainMenu::~MainMenu(){}
int MainMenu::input()
{
std::string mode;
std::cin >> mode;
if (std::find_if(mode.begin(),
mode.end(), [](char c) { return !std::isdigit(c); }) == mode.end()) //check if mode is number
{
std::string pathBuff;
std::ifstream f = m_f->read();
f.clear();
f.seekg(0, std::ios::beg);
for (int i = 1; i < std::strtol(mode.c_str(), nullptr, 0);i++) //iterate through list of files
{
std::string token;
getline(f, token);
}
getline(f, pathBuff);
std::unique_ptr<Menu> fm(std::make_unique<FileMenu>(pathBuff.c_str())); //go to file menu
fm->output();
}
if (!mode.compare("n"))
{
std::string path;
std::cin >> path;
m_f->append(path.c_str()); //add new file to list
std::unique_ptr<File> f (std::make_unique<File>(path.c_str()));
f->create(); //create new file
std::unique_ptr<Menu> fm (std::make_unique<FileMenu>(path.c_str())); //go to file menu
fm->output();
return 0;
}
if (!mode.compare("e"))
{
return 1;
}
return -1;
}
int MainMenu::output()
{
do
{
system("cls");
m_f->output(m_f->read());
std::cout << "\t(1..) open file (n)ew file (e)xit" << std::endl;
} while (input() != 1);
return 0;
}
File.h
#pragma once
#include <fstream>
class File
{
private:
const char* m_path;
public:
//File();
File(const char*);
int create();
int append(const char*);
int clear();
std::ifstream read();
void output(std::ifstream);
~File();
};
File.cpp
#include "stdafx.h"
#include "File.h"
#include <iostream>
#include <string>
File::File(const char* path):m_path(path){}
File::~File()
{
delete m_path;
}
int File::create()
{
std::ofstream out(m_path);
return 0;
}
int File::append(const char* str)
{
std::ofstream out(m_path, std::ios::app);
out << str <<'\n';
return 0;
}
int File::clear()
{
std::ofstream out(m_path, std::ios::trunc);
return 0;
}
std::ifstream File::read()
{
std::ifstream in (m_path);
return in;
}
void File::output(std::ifstream in)
{
std::string lineBuff;
while (getline(in, lineBuff))
{
//if (lineBuff.compare(""))//idk how to fix empty lines
{
std::cout << lineBuff << std::endl;
}
}
}
main()
int main()
{
{ std::unique_ptr<Menu> menu (new MainMenu("inf.f"));
menu->output();
}
/*if (_CrtDumpMemoryLeaks())
std::cout << "memory leak!" << std::endl;*/
return 0;
}