简体   繁体   English

连接const char *字符串

[英]concatenate const char * strings

I'm confused about char * and const char * . 我对char *const char *感到困惑。 In my example I'm not sure how to put them together. 在我的示例中,我不确定如何将它们放在一起。 I have several const char * strings I would like to concatenate to a final const char * string. 我想将多个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;
  }
};

You can store a std::string and still return a const char * from your what function. 您可以存储std::string并仍然从what函数返回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();
  }
};

Just use strcat() and strcpy() function from string.h . 只需使用string.h中的 strcat()strcpy()函数即可。

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

Also, since you don't have to modify original strings, the difference between const char* and char* doesn't matter. 另外,由于不必修改原始字符串,因此const char*char*之间的区别无关紧要。

Also don't forget to malloc() (reserve the space for) the required size of destination string. 同样不要忘记malloc() (保留空间)目标字符串的所需大小。

This is how I'd implement this: 这就是我要实现的方式:

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
  }
};

Things to note: 注意事项:

  1. The original code was using a local variable for a buffer. 原始代码使用本地变量作为缓冲区。 That is a bad idea, as the pointer stored in cause would be invalid the moment the scope ends . 这是一个坏主意,因为在作用域结束时,存储在cause的指针将无效

  2. For the concatenated message, dynamic allocation would be required. 对于串联的消息,将需要动态分配。 And that also means that cleanup of that storage would be required. 这也意味着将需要清理该存储。 I grabbed an existing tool that does that and provides string-like operations: std::string . 我抓住了一个现成的工具,它提供了类似字符串的操作: std::string

  3. With std::string concatenation can be done with the + operator. 使用std::string串联可以使用+运算符完成。 Note how I asked it to reserve memory for the expected size. 请注意我是如何要求它为预期大小保留内存的。 This is memory an optimization, and is not required: the string would allocate enough memory either way. 这是内存的优化,不是必需的:字符串将以任何一种方式分配足够的内存。

  4. what cannot throw an exception, otherwise a call std::unexpected would arise. what不能抛出异常,否则调用std::unexpected会发生。 So the string cannot be allocated here. 因此无法在此处分配字符串。

If you must work with char* pointers, you will want to use strcat . 如果必须使用char*指针,则需要使用strcat strcat takes two arguments a char* and a const char* and appends the string pointed to by the const char* onto the char* . strcat有两个参数一个char*const char*和附加字符串被指出const char*char* This means you first need to copy your first string over. 这意味着您首先需要复制第一个字符串。

You'll want to do something like this: 您将需要执行以下操作:

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;
}

Isn't that just ugly? 那不是很丑吗? And, remember, because you've dynamically allocated the char* returned by that function the caller must remember to delete[] it. 并且,请记住,因为您已经动态分配了该函数返回的char *,所以调用者必须记住将delete[] This ugliness and the need to ensure the caller cleans up in the right way is why you're better off using a string implementation such as std::string . 这很丑陋,并且需要确保调用者以正确的方式清理,这就是为什么最好使用字符串实现(例如std::string

Allocate a buffer of size strlen(source) + strlen(cause) + 3 and use sprintf to create your message. 分配大小为strlen(source) + strlen(cause) + 3的缓冲区,并使用sprintf创建消息。 Actually you can move this code to constructor so that what becomes simple getter. 其实你可以让这个代码移到构造what变得简单吸气。

If you really must use c-strings, you should look at strcat() to concatenate them together. 如果确实必须使用c字符串,则应查看strcat()将它们串联在一起。 However, since you are creating a custom exception, it would be reasonable to consider using std::string instead because it is more friendly to use in C++. 但是,由于要创建自定义异常,因此可以考虑使用std::string代替,因为在C ++中使用它更友好。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM