我的编程空间,编程开发者的网络收藏夹
学习永远不晚

关于c++11与c风格路径拼接的速度对比

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

关于c++11与c风格路径拼接的速度对比

c++11的std库中没有提供路径拼接的功能

比如我需要将  "d:\\temp\\robin"  和   "..\\config.ini" 路径拼接,

这里用c++11的stingstream实现一个

string& replace_str(string& str, const string& to_replaced, const string& newchars)
{
    for (string::size_type pos(0); pos != string::npos; pos += newchars.length())
    {
        pos = str.find(to_replaced, pos);
        if (pos != string::npos)
            str.replace(pos, to_replaced.length(), newchars);
        else
            break;
    }
    return   str;
}
 
// windows
std::string combinePath(const char *dir, const char* name)
{    
    //printf("%s  +  %s\n", dir, name);
    if (dir == nullptr || name == nullptr)
        return "";
    string temp = dir;
    replace_str(temp, "/", "\\");
    std::stringstream oss(temp);
    std::deque<std::string> vecDir;
    std::deque<std::string> vecName;
 
    string part;
    while (std::getline(oss, part, '\\'))
    {
        if (part.length() == 0)
            continue;
        vecDir.emplace_back(part);
    } 
 
    temp = name;
    replace_str(temp, "/", "\\");
    oss.clear();
    oss.str(temp);
    while (std::getline(oss, part, '\\'))
    {
        if (part.length() == 0)
            continue;
        vecName.emplace_back(part);
    }
 
    int index = 0;
    while (index < vecName.size())
    {
        if (vecName[0] == ".")
        {
            vecName.pop_front();
        }
        //else if (vecName[0].find("..") != vecName[0].npos)
        else if (vecName[0] == "..")
        {
            vecName.pop_front();
            if (vecDir.size() > 1)
                vecDir.pop_back();
        }
        else
        {
            vecDir.emplace_back(vecName[0]);
            vecName.pop_front();
        }
    }
 
    oss.clear();
    oss.str("");
    for (int i=0; i<vecDir.size(); i++)
    {
        oss << vecDir[i];
        if (vecDir.size() == 1 || i < (vecDir.size() - 1))
        {
            oss << "\\";
        }
    } 
    return oss.str();
}

测试方法:

void test1()
{
    cout << combinePath("d:\\temp\\robin\\", "..\\demo\\config.ini") << endl;
    cout << endl;
 
    cout << combinePath("d:", "..\\demo\\config.ini") << endl;
    cout << endl;
 
    cout << combinePath("d:\\temp\\robin", "../demo/config.ini") << endl;
    cout << endl;
 
    cout << combinePath("d:\\temp\\robin", "./config.ini") << endl;
    cout << endl;
 
    cout << combinePath("d:\\temp\\robin", "config.ini") << endl;
    cout << endl;
 
    cout << combinePath("d:\\temp\\robin\\", "\\config.ini") << endl;
    cout << endl;
}

测试发现,release使用O2优化,能平均在2~4微秒左右,还是不够快啊,

用c重新实现一遍

// 字符串范围内,逆向查找
const char *  strrfind(const char *begin, const char *end, const char c)
{
    const char * buf = end;
    while (buf >= begin)
    {
        if (*buf == c)
            return buf;
        buf--;
    }
    return nullptr;
}
size_t  combinePathC(char ** buffer, const char * dir, const char *name)
{
    int n1 = strlen(dir);
    int n2 = strlen(name);
    size_t len =  n1 + n2 + 2;
    char *buf = new char[len];
    *buffer = buf;
 
    memcpy(buf, dir, n1);
    size_t len1 = n1;
 
    // 末尾保证有一个"\"
    if (buf[n1-1] == '\\')
    {
        len1 = n1;
    }
    else
    {
        buf[n1] = '\\';
        len1 = n1+1;        
    }
    buf[len1] = '\0';
 
    // len1++示当前拼接的长度
    size_t index = 0;
    char * rPart = (char *)name;
    size_t len2 = n2;
    while (index < n2)   // 使用index向后滑动,直到末尾
    {
        // 滑动后当前位置
        rPart = (char *)name + index;
        char * tmp = (char *)strchr(rPart, '\\');
        if (tmp == nullptr)   // end here
        {
            // 拼接剩下的
            len2 = n2 - index;
            memcpy(buf + len1, rPart, len2);
            len1 += len2;
            buf[len1] = '\0';
            len1++;
 
            break;
        }
 
        // 当前找到的长度
        len2 = tmp - rPart;
        if (len2 == 0)     // 遇到 "\config.ini",去掉1个字符
        {
            index += 1;
        }
        else if (len2 == 1 && rPart[0] == '.')   // 遇到 ".\config.ini",去掉2个字符
        {
            index += 2;
        }
        else if (len2 >= 2 && rPart[0] == '.')  // 遇到 "..\config.ini", "..x\config.ini"去掉3个字符,末尾去掉一个目录
        {
            index += len2 + 1;
            const char * back = strrfind(buf, buf + len1 - 2 , '\\');   // 从末尾的"\"前一个字符开始找
            if (back == nullptr)
            {
                // dir 当前是这样的情况,"d:\”
            }
            else if ((back - dir) == 2)  // dir 当前是这样的情况,"d:\temp\”
            {
                len1 = 3;
                buf[3] = '\0';
            }
            else                        // dir 当前是这样的情况,"d:\temp\test1\”
            {
                len1 = back - buf + 1;
                buf[len1] = '\0';
            }
        }
        else    //  遇到首字符不为点 "x\config.ini",  
        {
            index += len2 + 1;
            memcpy(buf + len1, name + index, len2 + 1);
            len1 += len2 + 1;
        }
    } 
    return len1;
}

测试一下:

    char * buf = nullptr;
    size_t len; 
    
    len = combinePathC(&buf, "d:\\temp\\robin\\", "config.ini");
    cout << buf << endl;
 
    len = combinePathC(&buf, "d:\\temp\\robin", "config.ini");
    cout << buf << endl;*/
 
    len = combinePathC(&buf, "d:\\temp\\robin", ".\\config.ini");
    cout << buf << endl;
 
    len = combinePathC(&buf, "d:\\temp\\robin", "..\\config.ini");
    cout << buf << endl;
 
    len = combinePathC(&buf, "d:\\temp\\robin", "...\\config.ini");
    cout << buf << endl;

测试发现,平均在0.2微秒左右;

打完收功! 以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程网。

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

关于c++11与c风格路径拼接的速度对比

下载Word文档到电脑,方便收藏和打印~

下载Word文档

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录