一、设计并实现几个类,用于打开并读取不同类型的文件内容。要求如下:
- 一种类型对应一个类。
- 根据文件名后缀区分文件类型。需要支持 .ini, .xml, .json。
- 这些类需要支持以下几个方法:
bool open() - 打开文件
std::string file() const - 返回打开的文件路径
std::string get(const std::string& key) - 根据key获取内容(只需简单实现,返回文件类型+首行内容) - 可扩展,能方便添加其他文件类型。
#include <iostream>
#include <fstream>
#include <string>
#include <map>
class FileReader {
public:
virtual ~FileReader() {}
virtual bool open(const std::string& filename) = 0;
virtual std::string file() const = 0;
virtual std::string get(const std::string& key) = 0;
};
class IniFileReader : public FileReader {
public:
virtual bool open(const std::string& filename) override {
file_.open(filename);
return file_.is_open();
}
virtual std::string file() const override {
return filename_;
}
virtual std::string get(const std::string& key) override {
std::string line;
while (std::getline(file_, line)) {
if (line[0] == ';') continue; // ignore comments
size_t pos = line.find('=');
if (pos != std::string::npos) {
std::string k = line.substr(0, pos);
if (k == key) {
return "ini: " + line.substr(pos + 1);
}
}
}
return "";
}
private:
std::ifstream file_;
std::string filename_;
};
class XmlFileReader : public FileReader {
public:
virtual bool open(const std::string& filename) override {
file_.open(filename);
return file_.is_open();
}
virtual std::string file() const override {
return filename_;
}
virtual std::string get(const std::string& key) override {
std::string line;
while (std::getline(file_, line)) {
if (line.find("<" + key + ">") != std::string::npos) {
std::getline(file_, line);
return "xml: " + line;
}
}
return "";
}
private:
std::ifstream file_;
std::string filename_;
};
class JsonFileReader : public FileReader {
public:
virtual bool open(const std::string& filename) override {
file_.open(filename);
if (file_.is_open()) {
std::string line;
std::getline(file_, line);
if (line[0] == '{') {
buffer_ = line;
}
else {
file_.close();
return false;
}
}
filename_ = filename;
return true;
}
virtual std::string file() const override {
return filename_;
}
virtual std::string get(const std::string& key) override {
if (buffer_.empty()) {
return "";
}
size_t pos = buffer_.find("\"" + key + "\":");
if (pos == std::string::npos) {
return "";
}
size_t start = buffer_.find(':', pos) + 1;
size_t end = buffer_.find(',', start);
if (end == std::string::npos)
{
end = buffer_.find('}', start);
}
return "json: " + buffer_.substr(start, end - start);
}
private:
std::ifstream file_;
std::string filename_;
std::string buffer_;
};
二、实现一个String类,要求:
1、不能使用系统默认构造、析构、拷贝构造、赋值操作符等;
2、实现常用操作接口,如拼接、分隔、字符查找、替换等。
#include<iostream>
using namespace std;
#define MSTRING_NUM_SIZE sizeof(int)//引用计数大小
#define DEFEALT_LEN (10+MSTRING_NUM_SIZE)
class Mstring
{
public:
Mstring(const char* str)
{
if (NULL == str)
{
_len = DEFEALT_LEN;
_val_len = 0;
_str = new char[_len];
memset(_str, 0, _len);
return;
}
_val_len = strlen(str);
_len = _val_len + 1;
_str = new char[_len];
memset(_str, 0, _len);
for (int i = 0; i < _val_len; i++)
{
_str[i] = str[i];
}
}
Mstring(const Mstring& src)
{
_val_len = strlen(src._str);
_len = _val_len + 1;
_str = new char[_len];
memset(_str, 0, _len);
for (int i = 0; i < _val_len; i++)
{
_str[i] = src._str[i];
}
}
Mstring& operator=(const Mstring& src)
{
if (&src == this)
{
return *this;
}
delete[]_str;
_val_len = strlen(src._str);
_len = _val_len + 1;
_str = new char[_len];
memset(_str, 0, _len);
for (int i = 0; i < _val_len; i++)
{
_str[i] = src._str[i];
}
return *this;
}
~Mstring()
{
delete[]_str;
}
void push_back(char c)//尾插
{
if (full())//判满
{
revert();//如果满了则扩容
}
_str[_val_len] = c;
_val_len++;
}
void pop_back()//尾删
{
if (empty())
{
return;
}
_val_len--;
}
char back()const//获取最后一个元素
{
if (empty())
{
return 0;
}
return _str[_val_len - 1];
}
char front()const//获取第一个元素
{
if (empty())
{
return 0;
}
return _str[0];
}
bool empty()const
{
return _val_len;
}
Mstring operator+(const Mstring& str)const//拼接
{
char* p;
int len = _val_len + str._val_len + 1;
p = new char[len];
memset(p, 0, len);
int i = 0;
for (; i < _val_len; i++)
{
p[i] = _str[i];
}
for (int j = 0; j < str._val_len; j++, i++)
{
p[i] = str._str[j];
}
return p;//返回指针会直接构造成一个对象
}
Mstring operator+(const char c)const//拼接
{
char* p;
int len = _val_len + 1;
p = new char[len];
memset(p, 0, len);
int i = 0;
for (; i < _val_len; i++)
{
p[i] = _str[i];
}
p[len] = c;
return p;//返回指针会直接构造成一个对象
}
//分隔
Mstring Str_P(char c)
{
Mstring tmp = "";
if (My_char_find(c) != -1) // 这里是处理按空格分割的数据,如果是其他的分隔符,这里和下一行更改为指定的分割符即可。
{
int pos = My_char_find(c);
for (int i = 0; i < _val_len; i++)
{
tmp=tmp+_str[i];
}
}
return tmp;
}
//字符查找
int My_char_find(char c)const
{
int pos = -1;
for (int i = 0; i < _val_len; i++)
{
if (_str[i] == c)
{
pos = i;
return pos;
}
}
return pos;
}
//字符替换
bool My_char_replace(char c,char re)const//拼接
{
for (int i = 0; i < _val_len; i++)
{
if (_str[i] == c)
{
_str[i] = re;
return true;
}
}
return false;
}
char& operator[](int pos)//返回值为引用的目的就是保证外界可以进行修改
{
return _str[pos];
}
char operator[](int pos)const
{
return _str[pos];
}
bool full()const
{
return _val_len == _len - 1;
}
void revert()
{
_len = _len << 1;//左移一位,相当于乘以2
char* p;
p = new char[_len];
memset(p, 0, _len);
int i = 0;
for (; i < _val_len; i++)
{
p[i] = _str[i];
}
delete[]_str;
_str = p;
}
int size()const
{
return _val_len;
}
friend ostream& operator<<(ostream& out, const Mstring& str)
{
int i = 0;
for (; i < str._val_len; i++)
{
out << str._str[i];
}
out << endl;
return out;
}
friend istream& operator>>(istream& in, Mstring& str)
{
char tmp[1024];
cin >> tmp;
str = tmp;
return in;
}
private:
bool full()const;
void revert();
char* _str;//堆上申请的空间用来存放数据;能否直接使用浅拷贝-----怎么增加引用计数
int _len;//空间总大小
int _val_len;//实际占用空间,实际数据数量
};