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

 更新时间:2022年07月22日 08:38:46   作者:飞鸟真人  
这篇文章主要介绍了关于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微秒左右;

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

相关文章

  • C++实现趣味扫雷游戏

    C++实现趣味扫雷游戏

    这篇文章主要为大家详细介绍了C++实现趣味扫雷游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-06-06
  • C++中的Reactor原理与实现

    C++中的Reactor原理与实现

    reactor设计模式是event-driven architecture的一种实现方式,处理多个客户端并发的向服务端请求服务的场景,每种服务在服务端可能由多个方法组成,这篇文章主要介绍了Reactor原理与实现,需要的朋友可以参考下
    2022-07-07
  • 详谈C语言指针

    详谈C语言指针

    这篇文章主要介绍了C语言的指针,介绍了其相关概念,然后分享了几种用法,具有一定参考价值。需要的朋友可以了解下
    2021-10-10
  • C语言中获取和改变目录的相关函数总结

    C语言中获取和改变目录的相关函数总结

    这篇文章主要介绍了C语言中获取和改变目录的相关函数总结,包括getcwd()函数和chdir()函数以及chroot()函数的使用方法,需要的朋友可以参考下
    2015-09-09
  • C++迷宫的实现代码

    C++迷宫的实现代码

    这篇文章主要为大家详细介绍了C++实现迷宫游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-03-03
  • Qt实现验证码相关功能的代码示例

    Qt实现验证码相关功能的代码示例

    验证码的原理基于人类视觉和计算机视觉的差异性,通过给用户显示一些难以被机器识别的图形或文字,让用户进行人机交互,确认自己的身份,这样可以有效保护网站安全,所以本给大家介绍了Qt实现验证码相关功能的代码示例,感兴趣的朋友可以参考下
    2024-01-01
  • 深入解析C++中的指针数组与指向指针的指针

    深入解析C++中的指针数组与指向指针的指针

    以下是对C++中的指针数组与指向指针的指针进行了详细的介绍,需要的朋友可以过来参考下
    2013-09-09
  • C++标准模板库STL深入讲解

    C++标准模板库STL深入讲解

    STL提供了一组表示容器、迭代器、函数对象和算法的模板。容器是一个与数组类似的单元,可以存储若干个值。STL容器是同质的,即存储的值的类型相同:算法是完成特定任务(如对数组进行排序或在链表中查找特定值)的处方
    2022-12-12
  • C++ 中的INT_MAX,INT_MIN数值大小操作

    C++ 中的INT_MAX,INT_MIN数值大小操作

    这篇文章主要介绍了C++ 中的INT_MAX,INT_MIN数值大小操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-03-03
  • C++获取本地时间常见方法汇总

    C++获取本地时间常见方法汇总

    这篇文章主要介绍了C++获取本地时间的常见方法,帮助大家更好的理解和学习C++,感兴趣的朋友可以了解下
    2020-08-08

最新评论