1

とについて混乱しchar *ていconst char *ます。私の例では、それらを組み合わせる方法がわかりません。const char *最終的な文字列に連結したい文字列がいくつかありconst char *ます。

struct MyException : public std::exception
{
  const char *source;
  int number;
  const char *cause;

  MyException(const char *s, int n)
      : source(s), number(n) {}
  MyException(const char *s, const char *c)
      : source(s), number(0), cause(c) {}

  const char *what() const throw()
  {
    if (number != 0) {
      char buffer[1024];
      // why does this not work?
      cause = strerror_r(number, buffer, 1024);
    }

    // how to concatenate the strings?
    return source + ": " + cause;
  }
};
4

6 に答える 6

5

を格納しても、what関数からをstd::string返すことができます。const char *

struct MyException : public std::exception
{
private:
  std::string message;  

public:    
  MyException(const char *s, int n) {
    char buffer[1024];
    strerror_r(n, buffer, 1024);
    message.reserve(strlen(s) + 2 + strlen(buffer));
    message = s;
    message += ": ";
    message += buffer;
  }

  MyException(const char *s, const char *c) {
    message.reserve(strlen(s) + 2 + strlen(c));
    message = s;
    message += ": ";
    message += c;
  }

  const char *what() const throw()
  {
    return message.c_str();
  }
};
于 2012-07-26T20:07:06.150 に答える
2

string.hから使用strcat()してstrcpy()機能するだけです。

http://www.cplusplus.com/reference/clibrary/cstring/strcat/ http://www.cplusplus.com/reference/clibrary/cstring/strcpy/

また、元の文字列を変更する必要がないため、との違いは重要ではconst char*ありchar*ません。

malloc()また、宛先文字列の必要なサイズを忘れないでください(スペースを予約してください)。

于 2012-07-26T20:03:52.283 に答える
2

これは私がこれを実装する方法です:

struct MyException : public std::exception
{
public:
  const char *source;
  int number;
  const char *cause;
private:
  char buffer[1024]; // #1
  std::string message; // #2

  std::string build_message() {
    if (number != 0) {
      cause = strerror_r(number, buffer, 1024); // use the member buffer
    }
    std::string s; // #3
    s.reserve(strlen(source) + 2 + strlen(cause));
    return s + source + ": " + cause;
  }

public:
  MyException(const char *s, int n)
      : source(s), number(n), cause(), message(build_message()) {}
  MyException(const char *s, const char *c)
      : source(s), number(0), cause(c), message(build_message()) {}

  const char *what() const throw()
  {
    return message.c_str(); // #4
  }
};

注意事項:

  1. 元のコードは、バッファーにローカル変数を使用していました。スコープが終了した瞬間にに格納されているポインタが無効にcauseなるため、これは悪い考えです。

  2. 連結されたメッセージの場合、動的な割り当てが必要になります。また、そのストレージのクリーンアップが必要になることも意味します。それを実行し、文字列のような操作を提供する既存のツールを入手しましたstd::string

  3. 連結を使用すると、演算子std::stringを使用して実行できます。+予想されるサイズのメモリを予約するように要求したことに注意してください。これはメモリの最適化であり、必須ではありません。文字列はどちらの方法でも十分なメモリを割り当てます。

  4. what例外をスローすることはできません。そうしないと、呼び出しstd::unexpectedが発生します。したがって、ここで文字列を割り当てることはできません。

于 2012-07-26T20:09:48.197 に答える
1

char*ポインタを操作する必要がある場合は、を使用することをお勧めしますstrcatstrcat2つの引数achar*とaconst char*を取り、が指す文字列をに追加しconst char*ますchar*。これは、最初に最初の文字列をコピーする必要があることを意味します。

あなたはこのようなことをしたいと思うでしょう:

char* Concatenate(const char* first, const char* second)
{
  char* mixed = new char[strlen(first) + strlen(second) + 2 /* for the ': ' */ + 1 /* for the NULL */];
  strcpy(mixed, first);
  strcat(mixed, ": ");
  strcat(mixed, second);

  return mixed;
}

それはただ醜いではありませんか?また、その関数によって返されるchar *を動的に割り当てたため、呼び出し元はそれを覚えておく必要がありますdelete[]。この醜さと、呼び出し元が正しい方法でクリーンアップすることを保証する必要があるため、などの文字列実装を使用する方がよいでしょうstd::string

于 2012-07-26T20:08:48.493 に答える
0

本当にc文字列を使用する必要がある場合は、strcat()それらを連結することを検討する必要があります。ただし、カスタム例外を作成しているstd::stringため、C ++での使用がより使いやすいため、代わりに使用することを検討するのが妥当です。

于 2012-07-26T20:08:29.923 に答える
0

サイズのバッファを割り当て、メッセージの作成にstrlen(source) + strlen(cause) + 3使用sprintfします。実際には、このコードをコンストラクターに移動して、what単純なゲッターにすることができます。

于 2012-07-26T20:06:21.680 に答える