我对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;
}
};
答案 0 :(得分:5)
您可以存储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();
}
};
答案 1 :(得分: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()
(保留空间)所需的目标字符串大小。
答案 2 :(得分: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
}
};
注意事项:
原始代码使用本地变量作为缓冲区。这是一个坏主意,因为存储在cause
中的指针将为invalid the moment the scope ends。
对于连接的消息,将需要动态分配。这也意味着需要清理该存储。我抓住了一个现有的工具,提供了类似字符串的操作:std::string
。
std::string
可以使用+
运算符进行连接。请注意我是如何要求它为预期大小保留内存的。这是内存优化,并不是必需的:字符串将以任何方式分配足够的内存。
what
无法抛出异常,否则会出现调用std::unexpected
。所以这里不能分配字符串。
答案 3 :(得分:1)
如果您必须使用char*
指针,则需要使用strcat
。 strcat
使用char*
和const 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
等字符串实现的原因。
答案 4 :(得分:0)
分配大小为strlen(source) + strlen(cause) + 3
的缓冲区,并使用sprintf
创建您的邮件。实际上,您可以将此代码移动到构造函数,以便what
变为简单的getter。
答案 5 :(得分:0)
如果你真的必须使用c-strings,你应该看strcat()
将它们连接在一起。但是,由于您要创建自定义异常,因此考虑使用std::string
是合理的,因为它在C ++中使用起来更友好。