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

2022-07-22 09:13:39

目录这里用c++11的stingstream实现一个用c重新实现一遍c++11的std库中没有提供路径拼接的功能比如我需要将d:temprobin和..config.ini路径拼...

目录
这里用c++11的stingstream实现一个
用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向后滑动,直到末尾
 {
  // 滑动后当python前位置
  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;
  }

  // 当前找到的长度
  lhttp://www.cppcns.comen2 = 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 python- 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 &lt;< 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微秒左右;

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