-1

Lets say I have a prepend function:

//for example xMessage = "apple";
//for example yMessage = "juice";
//answer should be newMessage = "applejuice"

char* concat(char *xMessage, int xSize, char* yMessage, int ySize){
     char newMessage[xSize+ySize];
     for(....){
        //copyxMessage
     }
     for(....){
        //copyYMessage
     }
    return (char *) newMessage;
}

I know I can use strings, but would preferably keep them as an array of bytes. What could be the best solution for this to avoid the error of returning a local pointer.

SOLUTION: Create a vector or deque of uint8_t depending on the needs of the type of manipulation/algorithms of RAW data. I ended up using a std::vector<uint8_t>. Ex.

std::vector<uint8_t> data(buffer + bytesIn);

Due to in my case receiving data from a socket.

Edit: After reading the replies, the most convenient solution was to create a vector of chars or a string. Since I had a bunch of bytes being sent I decided to go with a std::vector<uint8_t> due to more manipulation I had to do later in the program. Thank you everyone for making me realize that and helping me with this. The reason I was messing with raw char pointers is because the data I was dealing with was RAW data, but converting it into a vector it was easier to manipulate the data, than dealing with char pointers.

Recursive
  • 211
  • 3
  • 10
  • 2
    This is C++. Why mess around with raw `char*` when `std::string` is right there. Combined with `std::tuple` you have a solution here. This function isn't even needed if you did the stuff with `std::string`, as you can just do `x + y`. – tadman Jun 08 '23 at 21:41
  • 1
    Use `std::string`. Don’t mess with C-style stfings. – Pete Becker Jun 08 '23 at 21:42
  • 7
    `char newMessage[xSize+ySize];` -- This is not valid C++ code anyway. Arrays in C++ must have their size denoted by compile-time values, not runtime values. – PaulMcKenzie Jun 08 '23 at 21:42
  • 4
    Sorry, but you need [a good C++ book](https://www.youtube.com/watch?v=2vbYlqgWZk8) to learn from. You can't learn C++ by asking questions on SO the whole day. – Yksisarvinen Jun 08 '23 at 21:42
  • Does this answer your question? [const char\* concatenation](https://stackoverflow.com/questions/1995053/const-char-concatenation) – Jan Schultke Jun 08 '23 at 21:43
  • *I know I can use strings, but I can't do it for this issue.* -- I am going to make a friendly wager of a cup of coffee that what you are saying isn't really true. I bet you don't know *how* to use `std::string` properly enough to not have to use char arrays like this. – PaulMcKenzie Jun 08 '23 at 21:44
  • 4
    It's great that you're asking questions, but please, **SLOW DOWN AND [READ THE ANSWERS](https://stackoverflow.com/questions/76432638/how-can-i-concat-two-char-pointers-into-one)** to your previous questions. It's extremely disrespectful to just blunder along and make the same mistakes. It's also a huge waste of your time as well as everyone else's. – tadman Jun 08 '23 at 21:45
  • 1
    Also, you are returning the address of a local variable, even if that local variable is a fake C++ array. That is undefined behavior. – PaulMcKenzie Jun 08 '23 at 21:46
  • @PaulMcKenzie Could be a "C++" professor who has no idea what C++ actually is, and is irrationally terrified of anything in `std`. – tadman Jun 08 '23 at 21:46
  • How is this different from your previous question? [How can I concat two char pointers into one?](https://stackoverflow.com/questions/76432638/how-can-i-concat-two-char-pointers-into-one) – Daniel H Jun 08 '23 at 21:47
  • @tadman this is due to an error, not because I did not read previous answers. I had to work around and now I did it, but get an error as stated in my question. Kinda different issue. – Recursive Jun 08 '23 at 21:48
  • 2
    @tadman Something that has been part of standard C++ for 25 years now, you would think that the idiotic "you can't use std::string" was done away with in this day and age. – PaulMcKenzie Jun 08 '23 at 21:48
  • 1
    @PaulMcKenzie You'd think, and yet here we are. I mean it's hard to teach C++ even from 25 years ago when you're inflicting a 30 year old compiler like Turbo C++ on your unfortunate students. – tadman Jun 08 '23 at 21:49
  • 2
    A) You can't (reliably) use VLAs (Variable Length Arrays, like `char x[n]`) in C++. B) You will need to `new[n]` instead. C) Because of that, now you've inherited a whole world of hurt to do with *memory management*. D) You really should use `std::string`, and even if you can't because *reasons*, keep that in mind. E) **DO NOT** forget the **NUL terminator** part of the allocation, it's always "length + 1". F) **DO NOT** forget to **NUL terminate**, the last byte of that must be 0. – tadman Jun 08 '23 at 21:50
  • 1
    So in summary: C++ `return a + b`. C shaped C++: `new[]`, `strcpy`, `strcat`, and a whole other mess of responsibilities. – tadman Jun 08 '23 at 21:54
  • `char* concat(char *xMessage, int xSize, char* yMessage, int ySize)` -- That declaration in C++ code raises more questions than you realize. 1) Where does the returned `char *` come from? Is it dynamically allocated? If so, was it created with `new[]`? or `malloc`? What if `xSize` and/or `ySize` are the incorrect values and now you have a buffer overrun, one of the errors where code can be exploited. See what teaching `C` in a C++ course gives you? – PaulMcKenzie Jun 08 '23 at 21:55
  • @TedLyngmo thank you I just noticed. Looks like I was making sure to edit my questions to make sure why I needed to use char pointers. I accepted the answer since that was my mistake. I kept getting hate for trying to learn more about pointers. Also, looks like they made me realize of a better way to do this since I was getting confused with probable issues of having null values inside my data I was receiving. Thank you for making me notice that. Sorry about that – Recursive Jun 26 '23 at 04:24
  • @Recursive You're welcome and hang in there! – Ted Lyngmo Jun 26 '23 at 05:00

3 Answers3

3

Just use std::string

std::string concat(char *xMessage, int xSize, char* yMessage, int ySize){
  std::string s(xMessage);
  s += yMessage;
  return s;
}

If you really want a pointer to the appended string buffer you can use a wrapper around concat.

A. K.
  • 34,395
  • 15
  • 52
  • 89
  • Better would be to take in `std::string` objects as input, eg: `std::string concat(const std::string &xMessage, const std::string &yMessage){ return xMessage + yMessage; }`. You can still pass in `char*` strings to them, if needed. But really, you can just eliminate this function altogether if you just use `std::string` as-is, eg: `std::string xMessage = "apple"; std::string yMessage = "juice"; std::string newMessage = xMessage + yMessage;` – Remy Lebeau Jun 08 '23 at 21:55
  • Alternatively take `std::string_view`s which could be cheaper to construct, if there are already char arrays containing the data. Even if `std::string`s are used, they can be converted to `std::string_view`s. Btw: you may want to construct an empty string first, then reserve followed by 2 calls to `append` to avoid the possibility of a reallocation of the string memory. `std::string s; s.reserve(xSize + ySize); s.append(xMessage, xSize); s.append(yMessage, ySize); return s;` – fabian Jun 08 '23 at 21:59
  • 1
    While I agree that using std::string for parameter is better, taking a std::string may not be a choice for OP. – A. K. Jun 08 '23 at 22:29
2

Note: I absolutely do not agree with doing this, but since you know you can use a std::string but would like to do it with raw pointers, here's one way:

  • Allocate a buffer large enough to hold xSize + ySize characters + 1 extra for the terminating \0. You do this with new[].
  • std::memcpy the input strings into the allocated buffer.
  • Don't forget to delete[] the buffer after use.
#include <cstring>

char* concat(const char *xMessage, int xSize, const char* yMessage, int ySize) {
    char* newMessage = new char[xSize + ySize + 1];

    std::memcpy(newMessage, xMessage, xSize);
    std::memcpy(newMessage + xSize, yMessage, ySize);
    newMessage[xSize + ySize] = '\0';

    return newMessage;
}

Demo

Ted Lyngmo
  • 93,841
  • 5
  • 60
  • 108
0

The function declaration

char* concat(char *xMessage, int xSize, char* yMessage, int ySize){

does not make sense.

Firstly, if the arrays pointed to by the pointers xMessage and yMessage are not changed within the function then the corresponding parameters should be declared with qualifier const.

Or if characters from the array pointed to by the parameter yMessage are appended to the array pointed to by the pointer xMessage then in any case the parameter yMessage should be declared with qualifier const.

Secondly, if the parameters xMessage and yMessage point to strings and you need to build a new string that will contain concatenated strings then parameters xSize and ySize are senseless.

If you indeed need to build a string that will contain concatenated passed strings then the function can look the following way

char * concat( const char *xMessage, const char *yMessage )
{
    size_t xLen = strlen( xMessage );

    char *result = new char[ xLen + strlen( yMessage ) + 1 ];

    memcpy( result, xMessage, xLen );
    strcpy( result + xLen, yMessage );

    return result;
}

And the function can be called for example like

char *result = concat( "apple", "juice" );

The caller of the function is responsible for deleting the concatenated string when it will not be required any more like

delete [] result;
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335