工作中C++ map容器正确处理方式?

map是STL的一个关联容器,map的特性就是它提供一对一的数据处理能力,其中第一个可以称为关键字(key),每个关键字只能在map中出现一次,第二个可能称为该关键字的值(value),由于这个特性,它完成有可能在我们处理一对一数据的时候,在编程上提供快速通道。

今天主要讲的是如何使用map来获取一个文件的实值(value)和键值(key)。

map使用

map以红黑树为底层机制,map把值与键关联在一起,可以使用键来查找词。使用map得包含map类所在的头文件 #include 中。我们创建一个文件

domain.rc

key=google.com;value=GOOGLE_VIDEO
key=facebook.com;value=FACEBOOK_VIDEO
key=youtube.com;value=YOUTUBE_LIVE
key=bilibili.com;value=VIDEO
key=www.google.com,video;value=VIDEO

上面的文件非常直观,我们在程序中可以定义为:map<string,string> mRst;

key为关键字,每个关键字只能在map中出现一次,value为该关键字的值。键可以是基本类型,string经常被用来作为键。value的基本类型也是string。

实例

对于上面的文件(domain.rc),如果我们想要获取到key和value应该怎么弄呢? 这个时候就需要写一个切割函数,主要对符号,;=进行切割,然后放到容器中。

//对str按delimiter进行切割,并保存到svec中,返回一共切割的个数
int UtlSpilit(const string& Line, vector<string>& Svec, const string& Delimit, int Count)
{
    Svec.clear();
    if(Delimit.empty() || Count < 0 || Line.empty())
        return 0;
    if(Count == 0)
        Count = numeric_limits<int>::max();
    string::size_type bPos=0;
    string::size_type ePos=0;
    int NowCount=1;
    //string中find()返回值是字母在母串中的位置(下标记录),如果没有找到,那么会返回一个特别的标记npos
    while((ePos = Line.find(Delimit, bPos)) != string::npos && NowCount<Count)
    {   
    	/*获得字符串Line中从第bPos位开始的长度为ePos-bPos的字符串*/
        string tmpLine=Line.substr(bPos, ePos-bPos);

        Svec.push_back(tmpLine);/*顺序容器,存放string类型的对象。*/

        bPos=ePos+Delimit.size();
        ++NowCount;
    }   
    string tmpLine = Line.substr(bPos);
    Svec.push_back(tmpLine);
    return Svec.size();/*返回切割个数*/
}

切割文件中符号;=

int UtlParseOpts(const string &strVal, map<string, string> &mapOpts, 
        const string &strMainToken, const string &strSlaveToken)
{

    vector<string> vOpts;
    utl_spilit(strVal.c_str(), vOpts, strMainToken, 0);
    for(unsigned i = 0; i < vOpts.size(); i++)
    {
        vector<string> vKv;
        utl_spilit(vOpts[i].c_str(), vKv, strSlaveToken, 0);
        if  ( vKv.size() != 2)
            continue;
        mapOpts[vKv[0]] = vKv[1];    
    }
    return 0;
};

解析文件(domain.rc)

void  ParserRcFile(char* szCfgPath,list<Cfg> &lstRcConfs)
{
    FILE *pFp = fopen(szCfgPath, "r");
    if (pFp == 0)
    {
        return ;
    }

    char szLine[1024];
    for(;;)
    {
        char *pLine = fgets(szLine, sizeof(szLine)-1, pFp);
         if (pLine == 0)
            break;
         
        if (!pLine || pLine[0] == '#') 
            continue;
        char *pTmp = strrchr(pLine, '\n');
        if (pTmp != 0)
            *pTmp = 0;
        pTmp = strrchr(pLine, '\r');
        if (pTmp != 0)
            *pTmp = 0;   
        
        map<string,string> mRst;//以string为键值,以string为值
        /*format:key=google.com;value=FACEBOOKVIDEO*/
        utl_parse_opts(pLine, mRst, ";", "=");
        string strKeys = mRst["key"];
        string strValue = mRst["value"];
        printf("strKeys = %s\n", strKeys.c_str());
        printf("strValue = %s\n", strValue.c_str());
        vector<string> vKeys;
        utl_spilit(strKeys, vKeys, ",", 0);
        Cfg cfg;
        for (string & s : vKeys)
        {
            cfg.m_iValue.push_back(s);
        }

        cfg.m_iProt = strValue;

        lstRcConfs.push_back(cfg);
    }
    fclose(pFp);
}

指定的流中读取数据,每次读取一行。对文件中第一个字符#跳过,这样方便注释。查找字符在指定字符串中从右面开始的第一次出现\n,\r的位置 ,定义一个map存放切割实值(value)和键值(key)。

完整代码:

#include <list>
#include <vector>
#include <map>
#include <iostream>
#include <string>
#include <stdio.h>
#include <string.h>
#include <limits>
using std::numeric_limits;
using std::list;
using std::vector;
using std::map;
using std::string;

struct Cfg
{
    vector<string> m_vIdxs;
    string  m_iValue;
};


//对str按delimiter进行切割,并保存到svec中,返回一共切割的个数
int UtlSpilit(const string& Line, vector<string>& Svec, const string& Delimit, int Count)
{
    Svec.clear();
    if(Delimit.empty() || Count < 0 || Line.empty())
        return 0;
    if(Count == 0)
        Count = numeric_limits<int>::max();
    string::size_type bPos=0;
    string::size_type ePos=0;
    int NowCount=1;
    while((ePos = Line.find(Delimit, bPos)) != string::npos && NowCount<Count)
    {   
        string tmpLine=Line.substr(bPos, ePos-bPos);

        Svec.push_back(tmpLine);

        bPos=ePos+Delimit.size();
        ++NowCount;
    }   
    string tmpLine = Line.substr(bPos);
    Svec.push_back(tmpLine);
    return Svec.size();
}

int UtlParseOpts(const string &strVal, map<string, string> &mapOpts, 
        const string &strMainToken, const string &strSlaveToken)
{

    vector<string> vOpts;
    UtlSpilit(strVal.c_str(), vOpts, strMainToken, 0);
    for(unsigned i = 0; i < vOpts.size(); i++)
    {
        vector<string> vKv;
        UtlSpilit(vOpts[i].c_str(), vKv, strSlaveToken, 0);
        if  ( vKv.size() != 2)
            continue;
        mapOpts[vKv[0]] = vKv[1];    
    }
    return 0;
};


void  ParserRcFile(char* szCfgPath,list<Cfg> &lstRcConfs)
{

    FILE *pFp = fopen(szCfgPath, "r");
    if (pFp == 0)
    {
        return ;
    }
    char szLine[1024];
    for(;;)
    {
        char *pLine = fgets(szLine, sizeof(szLine)-1, pFp);
         if (pLine == 0)
            break;
         
        if (!pLine || pLine[0] == '#') 
            continue;
        char *pTmp = strrchr(pLine, '\n');
        if (pTmp != 0)
            *pTmp = 0;
        pTmp = strrchr(pLine, '\r');
        if (pTmp != 0)
            *pTmp = 0;   
                   
        map<string,string> mRst;
        /*format:key=google.com;value=FACEBOOKVIDEO*/
        UtlParseOpts(pLine, mRst, ";", "=");
        string strKeys = mRst["key"];
        string strValue = mRst["value"];
        printf("strKeys = %s\n", strKeys.c_str());
        printf("strValue = %s\n", strValue.c_str());
        vector<string> vKeys;
        utl_spilit(strKeys, vKeys, ",", 0);
        printf("vKeys =%s\n", vKeys);
        Cfg cfg;
        for (string & s : vKeys)
        {
            cfg.m_vIdxs.push_back(s);
        }
        cfg.m_iValue= strValue;
        lstRcConfs.push_back(cfg);
    }
    fclose(pFp);
}

int main(int argc, char const *argv[])
{
	char szListFilef[256] = {0};
    snprintf( szListFilef, sizeof(szListFilef),"./domain.rc");
	list<Cfg> lstRcConfs;
    ParserRcFile(szListFilef,lstRcConfs);

	return 0;
}

编译输出:
在这里插入图片描述

总结

map是STL的一个关联容器,它提供一对一的hash。第一个可以称为关键字(key),每个关键字只能在map中出现一次;第二个可能称为该关键字的值(value),key 和 value可以是任意你需要的类型。

本篇文章只是简单介绍map工作中的常见用法,没有对内部源码的研究和所有map基本操作函数的使用。

在这里插入图片描述

欢迎关注微信公众号【程序猿编码】,添加本人微信号(17865354792),回复:领取学习资料。或者回复:进入技术交流群。网盘资料有如下:

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值