如何加快解析大字符串?

Ric*_*ick 2 c++ c++11

所以我制作了一个读取各种配置文件的程序.其中一些配置文件可能很小,有些可能是半大的(最大的一个是3,844 KB).

读入文件存储在一个字符串中(在它下面的程序中称为sample).

然后,我根据各种格式规则从字符串中提取程序信息.这很好用,唯一的问题是,当读取较大的文件时,它非常慢....

我想知道是否有任何我可以做的事情来加速解析,或者是否有一个现有的库可以完成我需要的工作(提取字符串,直到在同一级别的2个分隔符之间的分隔符和提取字符串字符串).任何援助都会很棒.

这是我的代码和它应该如何工作的样本......

#include "stdafx.h"

#include <string>
#include <vector>

std::string ExtractStringUntilDelimiter(
   std::string& original_string,
   const std::string& delimiter,
   const int delimiters_to_skip = 1)
{
   std::string needle = "";

   if (original_string.find(delimiter) != std::string::npos)
   {
      int total_found = 0;

      auto occurance_index = static_cast<size_t>(-1);

      while (total_found != delimiters_to_skip)
      {
         occurance_index = original_string.find(delimiter);
         if (occurance_index != std::string::npos)
         {
            needle = original_string.substr(0, occurance_index);
            total_found++;
         }
         else
         {
            break;
         }
      }

      // Remove the found string from the original string...
      original_string.erase(0, occurance_index + 1);
   }
   else
   {
      needle = original_string;
      original_string.clear();
   }

   if (!needle.empty() && needle[0] == '\"')
   {
      needle = needle.substr(1);
   }
   if (!needle.empty() && needle[needle.length() - 1] == '\"')
   {
      needle.pop_back();
   }

   return needle;
}

void ExtractInitialDelimiter(
   std::string& original_string,
   const char delimiter)
{
   // Remove extra new line characters
   while (!original_string.empty() && original_string[0] == delimiter)
   {
      original_string.erase(0, 1);
   }
}

void ExtractInitialAndFinalDelimiters(
   std::string& original_string,
   const char delimiter)
{
   ExtractInitialDelimiter(original_string, delimiter);

   while (!original_string.empty() && original_string[original_string.size() - 1] == delimiter)
   {
      original_string.erase(original_string.size() - 1, 1);
   }
}

std::string ExtractStringBetweenDelimiters(
   std::string& original_string,
   const std::string& opening_delimiter,
   const std::string& closing_delimiter)
{
   const size_t first_delimiter = original_string.find(opening_delimiter);
   if (first_delimiter != std::string::npos)
   {
      int total_open = 1;
      const size_t opening_index = first_delimiter + opening_delimiter.size();

      for (size_t i = opening_index; i < original_string.size(); i++)
      {
         // Check if we have room for opening_delimiter...
         if (i + opening_delimiter.size() <= original_string.size())
         {
            for (size_t j = 0; j < opening_delimiter.size(); j++)
            {
               if (original_string[i + j] != opening_delimiter[j])
               {
                  break;
               }
               else if (j == opening_delimiter.size() - 1)
               {
                  total_open++;
               }
            }
         }


         // Check if we have room for closing_delimiter...
         if (i + closing_delimiter.size() <= original_string.size())
         {
            for (size_t j = 0; j < closing_delimiter.size(); j++)
            {
               if (original_string[i + j] != closing_delimiter[j])
               {
                  break;
               }
               else if (j == closing_delimiter.size() - 1)
               {
                  total_open--;
               }
            }
         }


         if (total_open == 0)
         {
            // Extract result, and return it...
            std::string needle = original_string.substr(opening_index, i - opening_index);
            original_string.erase(first_delimiter, i + closing_delimiter.size());

            // Remove new line symbols
            ExtractInitialAndFinalDelimiters(needle, '\n');
            ExtractInitialAndFinalDelimiters(original_string, '\n');

            return needle;
         }
      }
   }

   return "";
}

int main()
{
   std::string sample = "{\n"
      "Line1\n"
      "Line2\n"
      "{\n"
         "SubLine1\n"
         "SubLine2\n"
      "}\n"
   "}";

   std::string result = ExtractStringBetweenDelimiters(sample, "{", "}");
   std::string LineOne = ExtractStringUntilDelimiter(result, "\n");
   std::string LineTwo = ExtractStringUntilDelimiter(result, "\n");

   std::string SerializedVector = ExtractStringBetweenDelimiters(result, "{", "}");
   std::string SubLineOne = ExtractStringUntilDelimiter(SerializedVector, "\n");
   std::string SubLineTwo = ExtractStringUntilDelimiter(SerializedVector, "\n");

   // Just for testing...
   printf("LineOne: %s\n", LineOne.c_str());
   printf("LineTwo: %s\n", LineTwo.c_str());
   printf("\tSubLineOne: %s\n", SubLineOne.c_str());
   printf("\tSubLineTwo: %s\n", SubLineTwo.c_str());
   system("pause");
}
Run Code Online (Sandbox Code Playgroud)

Yak*_*ont 5

使用string_view或手动滚动.

不要修改加载的字符串.

  original_string.erase(0, occurance_index + 1);
Run Code Online (Sandbox Code Playgroud)

代码味道很大,原始字符串很大.

如果您要修改某些内容,请一次性完成.不要反复删除它的前面 - 即O(n ^ 2).相反,沿着它继续并将"已完成"的东西推入输出累加器.

这将涉及更改代码的工作方式.