CLion实现ini 解析器设计与实现

INI格式:

cpp 复制代码
[server]
ip = 127.0.0.1
port = 80

[profile]
name = jack
gender = male
age = 30

IniFile.h

cpp 复制代码
#pragma once
#include <string>
#include <map>
class Value {
public:
    Value();
    explicit Value(bool value);
    explicit Value(int value);
    explicit Value(double value);
    explicit Value(const char * value);
    explicit Value(const std::string & value);

    Value& operator = (bool value);
    Value& operator = (int value);
    Value& operator = (double value);
    Value& operator = (const char * value);
    Value& operator = (const std::string & value);

    explicit operator bool();
    explicit  operator int();
    explicit operator double();
    explicit operator std::string();
private:
    std::string m_value;
};

typedef std::map<std::string, Value> Section;
class IniFile {
public:
    IniFile();
    bool load(const std::string & filename);
    Value & get(const std::string & section, const std::string & key);
    void set(const std::string & section, const std::string & key,const Value & value);
    bool has(const std::string & section,const std::string & key);
    bool has(const std::string & secton);
    void remove(const std::string & section,const std::string & key);
    void remove(const std::string & section);
    void clear();
    bool save(const std::string& filename);
    Section & operator [] (const std::string & section) {
        return m_sections[section];
    }
private:
    std::string trim(std::string & str);
private:
    std::string m_filename;
    std::map<std::string,Section> m_sections;
};

IniFile.cpp

cpp 复制代码
#include "IniFile.h"
#include <fstream>
#include <iostream>
Value::Value() {
    m_value = "";
}
Value::Value(bool value) {
    *this = value;
}
Value::Value(int value) {
    *this = value;
}
Value::Value(double value) {
    *this = value;
}
Value::Value(const char * value) {
    *this = value;
}
Value::Value(const std::string & value) {
    *this = value;
}

Value& Value::operator=(bool value) {
    m_value = value ? "true" : "false";
    return *this;
}

Value& Value::operator=(int value) {
    m_value = std::to_string(value);
    return *this;
}

Value& Value::operator=(double value) {
    m_value = std::to_string(value);
    return *this;
}

Value& Value::operator=(const char* value) {
    m_value = value;
    return *this;
}

Value& Value::operator=(const std::string& value) {
    m_value = value;
    return *this;
}

Value::operator bool() {
    return m_value == "true";
}
Value::operator int() {
    return std::stoi(m_value);
}
Value::operator double() {
    return std::stod(m_value);
}
Value::operator std::string() {
    return m_value;
}

IniFile::IniFile() = default;

bool IniFile::load(const std::string & filename) {
    m_filename = filename;
    std::ifstream fin( filename);
    if(fin.fail()) {
        std::cout << "Failed to open file: " <<std::endl;
        return false;
    }
    std::string line;
    std::string section;
    while(std::getline(fin, line)) {
        line = trim(line);
        if(line.empty()) {
            continue;
        }
        int pos = line.find_first_of(']');
        if(pos != std::string::npos) {
            section = line.substr(1, pos - 1);
            section = trim(section);
            m_sections[section] = Section();
        }else {
            int pos = line.find_first_of('=');
            if(pos != std::string::npos) {
                std::string key = line.substr(0, pos);
                key = trim(key);
                std::string value = line.substr(pos + 1);
                value = trim(value);
                m_sections[section][key] = value;
            }
        }
    }
    fin.close();
    return true;
}

std::string IniFile::trim(std::string &str) {
    if(str.empty()) {
        return str;
    }
    str.erase(0, str.find_first_not_of(" \n\r"));
    str.erase(str.find_last_not_of(" \n\r") + 1);
    return str;
}

Value & IniFile::get(const std::string & section, const std::string & key) {
    return m_sections[section][key];
}

void IniFile::set(const std::string & section, const std::string & key,const Value & value) {
    m_sections[section][key] = value;
}

bool IniFile::has(const std::string & section,const std::string & key) {
    std::map<std::string,Section>::const_iterator it = m_sections.find(section);
    if(it != m_sections.end()) {
        return it->second.find(key) != it->second.end();
    }
    return false;
}

// 在 IniFile 类中添加保存方法
bool IniFile::save(const std::string& filename) {
    std::ofstream fout(filename );
    if (fout.fail()) {
        return false;
    }

    for ( auto& section_pair : m_sections) {
        fout << "[" << section_pair.first << "]\n";
        for ( auto& key_value : section_pair.second) {
            fout << key_value.first << "=" << static_cast<std::string>(key_value.second) << "\n";
        }
        fout << "\n";
    }

    fout.close();
    return true;
}

bool IniFile::has(const std::string & section) {
    return m_sections.find(section) != m_sections.end();
}

void IniFile::remove(const std::string & section,const std::string & key) {
    std::map<std::string,Section>::iterator it = m_sections.find(section);
    if(it != m_sections.end()) {
        it->second.erase(key);
    }
}
void IniFile::remove(const std::string & section) {
    m_sections.erase(section);
}
void IniFile::clear() {
    m_sections.clear();
}

main.cpp

cpp 复制代码
#include <iostream>
#include "IniFile.h"

int main() {
    IniFile ini;
    ini.load("test.ini");
    const std::string & ip = static_cast<std::string>(ini.get("server", "ip"));
    int port = static_cast< int>(ini.get("server", "port"));
    std::cout<<"ip:"<<ip<<" port:"<<port<<std::endl;

    const std::string ipp = static_cast<std::string>(ini["server"]["ip"]);
    std::cout<<"ipp:"<<ipp<<std::endl;

    //ini.set("server", "ip", "192.168.1.1");
    //std::cout<<"ip:"<<ip<<" port:"<<port<<std::endl;
    ini.set("server","timeout",Value(1000));

    std::cout<<"timeout:"<<static_cast<int>(ini.get("server","timeout"))<<std::endl;

    bool b = ini.has("server","timeout");
    std::cout<<"has timeout:"<<b<<std::endl;

    b = ini.has("server");
    std::cout<<"has server:"<<b<<std::endl;
    ini.remove("server","timeout");
    ini.save("test.ini");
    return 0;
}
相关推荐
Undoom10 小时前
智能开发环境下的 Diagram-as-Code 实践:MCP Mermaid 技术链路拆解
后端
农夫山泉2号11 小时前
【c++】——c++编译的so中函数有额外的字符
java·服务器·c++
计算机毕设VX:Fegn089511 小时前
计算机毕业设计|基于springboot + vue图书借阅管理系统(源码+数据库+文档)
数据库·vue.js·spring boot·后端·课程设计
疯狂的程序猴11 小时前
IPA 深度混淆是什么意思?分析其与普通混淆的区别
后端
仰泳的熊猫11 小时前
1077 Kuchiguse
数据结构·c++·算法·pat考试
cci11 小时前
Remote ssh无法连接?
后端
JohnYan11 小时前
Bun技术评估 - 22 Stream
javascript·后端·bun
okseekw11 小时前
Maven从入门到实战:核心概念+配置详解+避坑指南
java·后端
该用户已不存在11 小时前
Node.js后端开发必不可少的7个核心库
javascript·后端·node.js
踏浪无痕11 小时前
计算机算钱为什么会算错?怎么解决?
后端·算法·面试