0

から取得した文字列がありますostringstream。現在、この文字列 ( ) の一部の文字を置き換えようとしていますcontent.replace(content.begin(), content.end(), "\n", "");が、例外が発生することがあります。

malloc: *** mach_vm_map(size=4294955008) failed (error code=3)
*** error: can't allocate region
*** set a breakpoint in malloc_error_break to debug
std::bad_alloc

文字列が大きすぎるためにこれが発生すると思われます。これらの状況のベストプラクティスは何ですか? ヒープ上で文字列を宣言しますか?

アップデート

私の完全な方法:

xml_node HTMLDocument::content() const {
  xml_node html = this->doc.first_child();
  xml_node body = html.child("body");
  xml_node section = body.child("section");
  std::ostringstream oss;
  if (section.type() != xml_node_type::node_null) {
    section.print(oss);
  } else {
    body.print(oss);
  }
  string content;
  content = oss.str();
  content.replace(content.begin(), content.end(), "<section />", "<section></section>");
  content.replace(content.begin(), content.end(), "\t", "");
  xml_node node;
  return node;
}
4

4 に答える 4

1

std::string::replaceイテレータのペアを受け入れるメンバー関数のオーバーロードはありません。これは、const char*検索const char*され、置換として使用されます。これが問題の原因です。

content.replace(content.begin(), content.end(), "\n", "");

次のオーバーロードに一致します。

template <class InputIterator>
string& replace(iterator i1, iterator i2,
                InputIterator first, InputIterator last);

つまり"\n"""range として扱われ、<first; last)どのアドレスを持っているかによって、プログラムがクラッシュするかどうかが決まります。

遭遇したパターンを反復して置換文字列に置き換えるstd::regex独自のロジックを使用または実装する必要があります。std::string

于 2014-09-29T14:52:50.790 に答える
0

これは、コピーを作成してオリジナルをそのまま残したい場合に、文字列から文字を削除する正しい (そしてかなり効率的な) 方法の 1 つです。

#include <algorithm>
#include <string>

std::string delete_char(std::string src, char to_remove)
{
    // note: src is a copy so we can mutate it

    // move all offending characters to the end and get the iterator to last good char + 1
    auto begin_junk = std::remove_if(src.begin(),
                                     src.end(),
                                     [&to_remove](const char c) { return c == to_remove; });
    // chop off all the characters we wanted to remove
    src.erase(begin_junk,
              src.end());

    // move the string back to the caller's result
    return std::move(src);
}

次のように呼び出されます:

std::string src("a\nb\bc");
auto dest = delete_char(src, '\n');
assert(dest == "abc");

文字列をその場で変更したい場合は、次のようにします。

src.erase(std::remove_if(src.begin(), src.end(), [](char c) { return c == '\n'; }), src.end());
于 2014-09-29T15:51:31.730 に答える
0

AFAIK stl 文字列は、Visual Studio の 32 文字など、特定の (小さい) サイズを超えた場合、常にヒープに割り当てられます。

割り当ての例外が発生した場合にできること:

  • カスタム アロケータを使用する
  • ロープ」クラスを使用します。

不正な割り当ては、メモリが不足していることを意味するのではなく、連続したメモリが不足している可能性が高い. 内部で文字列を分割して割り当てるロープ クラスの方が適している場合があります。

于 2014-09-29T14:52:48.750 に答える