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

您可以存储 astd::string并仍然const char *从您的 what 函数返回 a。

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

这就是我实现它的方式:

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 回答
2

只需使用string.hstrcat()中的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 回答
1

如果您必须使用char*指针,您将需要使用strcat. strcat接受两个参数 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

分配一个大小的缓冲区strlen(source) + strlen(cause) + 3并用于sprintf创建您的消息。实际上,您可以将此代码移至构造函数,以便what成为简单的 getter。

于 2012-07-26T20:06:21.680 回答
0

如果你真的必须使用 c 字符串,你应该考虑strcat()将它们连接在一起。但是,由于您正在创建自定义异常,因此考虑使用它是合理的,std::string因为它在 C++ 中使用更友好。

于 2012-07-26T20:08:29.923 回答