# char + char = love!

## Recommended Posts

hey there. i am programming in c++ and i've come to a point that i want to send a packet from my server to the client. but not just a packet, it has to have an idea aswell as some data since i want the client to know what data i sent(like coordinates or any other variables). so for this i guess i have to join two char arrays(strings?) to be able to connect an id and the information(like 01555 where 01 is the id of the packet,and 555 is the data). but well, c++ doesnt love char + char. and so i went on my long journy to google to find the lost html page with the tutorial on how to join two chars! but well that didnt go well. so i just thought about going here and ask, how can i join two char arrays :)?

##### Share on other sites
It doesn't look like you want to join two chars. Rather, you want to join two char arrays. To do this in C++ you need to know the lengths of both char arrays. Say that your char arrays are ca1 and ca2 respectively. Let the length of ca1 be la1 and the length of ca2 be la2. Then you can simply use a memcpy.

char* ca = new char[la1+la2];memcpy( ca, ca1, la1 );memcpy( &ca[la1], ca2, la2 );// do whatever you need to send your packet heredelete [] ca;

Note that here you probably wouldn't want to dynamically allocate the array ca all the time. It would be better if, at compile time, you knew the size of the packet, or at least had an upper bound on the size of the packet. Then you could either allocate ca statically, or you could allocate it dynamically once at the beginning of the program and then just use it repeatedly every time you needed to send a packet. Anyway, those are all details. The real answer is that to join two char arrays, you'll likely want to use memcpy.

Cheers,
Rob

##### Share on other sites
You can use strcat to concat two strings. I'll let you look it up.

You might want to write a class that deals with all this sorta stuff for you, similar to Raknet's Bitstream, or, well, the iostream stuff [smile]

##### Share on other sites
strcat seems nice and simple, but what's memcpy? didnt fully understand what it does.

##### Share on other sites
@Richy2k : He might not want to use strcat. The two separate char*'s he wants to concatenate might not have null terminators. In fact, from the example he provided, that doesn't seem to be the case. Try the following code:

#include <cstdio>#include <cstring>#include <iostream>using std::cout;using std::endl;int main(){  char* ca1 = new char[5];  char* ca2 = new char[8];  ca1[0] = 01;  ca2[1] = 5;  ca2[2] = 5;  ca2[3] = 5;  char* ca = new char[5+8];  strcat( ca, ca1 );  strcat( ca, ca2 );  puts( ca );  cout << strlen( ca ) << endl;  return 0;}

That likely won't be what you want or what Bru expects.

@Bru The strcat function concatenates two null terminated strings. The memcpy function is more generic. Basically it looks like this:

memcpy( void* dest, void* src, size_t len );

It's really rather straight forward. It copies "len" bytes from "src" into "dest". The problem with strcat, as I mentioned to Richy2k, is that it expects the char arrays your concatenating to be null terminated. Since you'll be sending things over the network and you might want to use chars as bytes rather than parts of a string, this may not be true for you. Take a look at the example program I posted if you want to see what I mean. Let me know if you have any other questions about memcpy.

--Rob

##### Share on other sites
If you really want to use C++, consider using std::vector<char> as your buffer.

##### Share on other sites
Why not just use std::string?

Wouldn't that be the easiest approach with the least risk?

##### Share on other sites
There are multiple ways listed above, but one you should seriously consider is using std::stringstream. The STL is really very powerful.

Here's a quick snippet to show you how easy it is to combine two char arrays into one stringstream.

#include <iostream>#include <sstream>using namespace std;int main(){	// Create a couple of buffers.	char* buffer1 = new char[11];	buffer1 = "firstBuffer";	char* buffer2 = new char[12];	buffer2 = "secondBuffer";	// Create a stringstream and feed in our char buffers using the input operator (<<)	stringstream stream;	stream << buffer1 << buffer2;	// Print out the results using the .str() function of stringstream.	cout << stream.str() << '\n';	return 0;}

Hope you figure out a way that works!

##### Share on other sites
[quote]Original post by ArcPrime
	// Create a couple of buffers.	char* buffer1 = new char[11];	buffer1 = "firstBuffer";	char* buffer2 = new char[12];	buffer2 = "secondBuffer";

[/quote]

What's that?

You know you are leaking memory and for no reason at all?

Why not just write:
std::string buffer1 = "firstBuffer";std::string buffer2 = "secondBuffer";

Or for this particular case:
const char *buffer1 = "firstBuffer";const char *buffer2 = "secondBuffer";

##### Share on other sites
Quote:
 What's that?You know you are leaking memory and for no reason at all?Why not just write:std::string buffer1 = "firstBuffer";std::string buffer2 = "secondBuffer";Or for this particular case:const char *buffer1 = "firstBuffer";const char *buffer2 = "secondBuffer";

Yes, you are correct. I wasn't so concerned about the tiny memory leak; the intention was simply to display the use of stringstream.

No offense intended, and thanks for giving everyone else the heads-up. :)

FYI, I personally prefer the first suggestion you made (using std::string).

##### Share on other sites
Quote:
 Original post by ArcPrimeI wasn't so concerned about the tiny memory leak; the intention was simply to display the use of stringstream.

I think the point was that the following doesn't come close to what you seem to think it's doing:

char* pData = new char[10];pData = "Hello, world.";

The problem here isn't really that you're not calling delete - although that would clearly fix the problem - but that you've misunderstood how the assignment in the second line works.

After the first line, pData (assuming new didn't fail and throw an exception) is a pointer to some newly-allocated memory on the free store. After the second line, pData is a pointer to the string literal "Hello, world." - you've completely lost any reference to the allocated memory and can no longer recover it.

pData = "Hello, world." doesn't copy the string "Hello, world." into the memory at pData, instead it creates a string literal (which may be stored in read-only segments, and multiple occurrences of that literal in the source may well actually correspond to a single instance in memory) and points pData at it.

##### Share on other sites
Quote:
 Original post by MononofuWhy not just use std::string?Wouldn't that be the easiest approach with the least risk?
If you ever put a null byte in a std::string, you'll probably get some very strange behaviour.

##### Share on other sites
I really don't know why people keep telling other people (especially beginners) how to solve C++ problem with C. You don't use memcpy in C++, you use, std::copy. You don't use (const) char*, you use std::string, you don't add two arrays of chars, you add two std::vectors.

typedef std::vector<char> Buffer;

Buffer buf1, buf2;

// do stuff with them

buf1.insert(buf1.end(), buf2.begin(), buf2.end()) // insert buf2 at the end of buf1

this is the C++ solution (int its simplest form) for adding 2 char buffers. In fact buf2 can also be a simple char array for example:

char buf2[LEN];

buf1.insert(buf1.end(), buf2, buf2 + LEN);

You can also try just using adding std::string as suggested by others above. Do not use C.

Also, for building a network message buffer you need to google up for serialization / marshaling.

##### Share on other sites
Quote:
Original post by Evil Steve
Quote:
 Original post by MononofuWhy not just use std::string?Wouldn't that be the easiest approach with the least risk?
If you ever put a null byte in a std::string, you'll probably get some very strange behaviour.

If an anonymous poster had written this, I'd WTFed, but since it's from you, Evil Steve, care to enlighten us?

I haven't noticed any strange behavior and didn't come across any warning putting '\0' bytes in a std::string. I guess printing the string might result in it being cut off depending on the crt and system used, or are there any std::string implementations out there doing strnlen() internally?

To the original poster, my recommendation would be to go with the stringstream demonstrated by ArcPrime (but skip the flaws :P). Less headaches, automatic binary - ascii conversion (depending on your level of knowledge, you might after all have the value you want to write in a char, not the ascii character representing that value).

##### Share on other sites
Quote:
 Original post by CygonI haven't noticed any strange behavior and didn't come across any warning putting '\0' bytes in a std::string. I guess printing the string might result in it being cut off depending on the crt and system used, or are there any std::string implementations out there doing strnlen() internally?

Not if they want to confirm to the standard. You are explicitly allowed to have bytes containing zero in a std::string, and all implementations that I know of handle it correctly.

It's true that if you attempt to convert the contents of such a string int, say, a C-style string or a Unicode string, you may encounter some unexpected results, but it's entirely well defined.

It has also bee the source of quite a lot of acrimony amongst committee members.

##### Share on other sites
Quote:
 I think the point was that the following doesn't come close to what you seem to think it's doing:char* pData = new char[10];pData = "Hello, world.";The problem here isn't really that you're not calling delete - although that would clearly fix the problem - but that you've misunderstood how the assignment in the second line works.After the first line, pData (assuming new didn't fail and throw an exception) is a pointer to some newly-allocated memory on the free store. After the second line, pData is a pointer to the string literal "Hello, world." - you've completely lost any reference to the allocated memory and can no longer recover it.pData = "Hello, world." doesn't copy the string "Hello, world." into the memory at pData, instead it creates a string literal (which may be stored in read-only segments, and multiple occurrences of that literal in the source may well actually correspond to a single instance in memory) and points pData at it.

I realize what it was doing, I just wrote that post in a hurry yesterday. I originally had it using std::strings (the norm for me in C++), but after seeing the mention that the OP was using char*, I adjusted my code quickly without double-checking. Silly mistake; not a misunderstanding of how allocation of memory and assignment works with regard to char pointers. I really consider the important code to be the demonstration of std::stringstream.

Thanks again for pointing out, as it really was a dumb thing to do. I hope the OP has enough stuff to work with now. :)

##### Share on other sites
Quote:
Original post by ArcPrime
Quote:

Thanks again for pointing out, as it really was a dumb thing to do. I hope the OP has enough stuff to work with now. :)

Fair dues, sorry. :-) Oh well, it always bears repeating for the odd lurking newbie, I suppose!

[Edited by - TheUnbeliever on January 19, 2009 2:27:09 PM]

##### Share on other sites
Okay, everyone, back up a second. Let's make sure we understand the problem correctly.

Quote:
 Original post by Bruso for this i guess i have to join two char arrays(strings?) to be able to connect an id and the information

Tell me, OP, in your own words:

What is a char?

What is a char array?

What is a string?

What is a byte?

Have you ever heard of "ASCII"? What is it?

Quote:
 (like 01555 where 01 is the id of the packet,and 555 is the data).

How many bytes are there in the packet ID that you propose? What are their values? How many bytes are in the data that you propose? What are their values?

##### Share on other sites
Quote:
Original post by Zahlman
Okay, everyone, back up a second. Let's make sure we understand the problem correctly.

Quote:
 Original post by Bruso for this i guess i have to join two char arrays(strings?) to be able to connect an id and the information

Tell me, OP, in your own words:

What is a char?

What is a char array?

What is a string?

What is a byte?

Have you ever heard of "ASCII"? What is it?

Quote:
 (like 01555 where 01 is the id of the packet,and 555 is the data).

How many bytes are there in the packet ID that you propose? What are their values? How many bytes are in the data that you propose? What are their values?

char is one letter in ascii i belive.
char array is an array of chars(!?)
string is like a char array just that its not an array?
byte is a cell in the memory that is made of 8 bits, can hold any number between -127 to 127 or 0-255
ascii stands for american code something, i know all letters in the computer are saved in their ascii code.
in 01555 i belive there are 5 bytes(or now that i think about it, if its in ascii then its probably 10?).
value of each digit in 01555 in ascii? dont know.

P.S sorry for bump.

##### Share on other sites
I think his point was for you to think about your protocol. Is is text based or does it use some other encoding for the data?

When I first replied I assumed it was not text based, so I suggested std::vector<char> as a buffer type.

##### Share on other sites
Quote:
 Original post by rip-offI think his point was for you to think about your protocol. Is is text based or does it use some other encoding for the data?When I first replied I assumed it was not text based, so I suggested std::vector as a buffer type.

well at the moment i dont use any enconding. i simply send raw data between the client and server. the reason for that is that i am still learning about winsock and everything and i plan to keep it to the end.

##### Share on other sites
Even if you aren't doing any fancy encoding, you still need a format for your "packets". If the server receives "01555" - does that mean packet id = 01 and packet data = 555 or does it mean packet id = 0 and packet data = 1555?

If you are using TCP then remember there are no packets at your level - only a stream. How does the server know where one "packet" ends and the next begins if it receives 01555034243507895? You will also have to handle the case where you receive an incomplete packet by storing the partial data until the rest arrives.

If you are using UDP you will need to be able to handle missing, duplicate or out-of-order packets.

##### Share on other sites
Quote:
 Original post by rip-offEven if you aren't doing any fancy encoding, you still need a format for your "packets". If the server receives 01555 as text, does that mean packet id = 01 and packet data = 555 or does it mean packet id = 0 and packet data = 1555. If you are using TCP, remember there are no packets at your level, only a stream. How does it know where one "packet" ends and the next begins if it receives 015550155501555? You will also have to handle the case where you receive an incomplete packet by storing the partial data until the rest arrives.

i guess i seperate them by by adding a packet size?

##### Share on other sites
Good idea. But you still need a format for the packet size [smile]

Don't worry, it can be as easy as "the first X digits are the packet size". Alternatively in your text based protocol you could use a certain character as a delimiter. However this does mean that you would need to ensure that no legitimate message could contain this delimiter (or implement escape characters).

##### Share on other sites
Quote:
 Original post by rip-offGood idea. But you still need a format for the packet size [smile]Don't worry, it can be as easy as "the first X digits are the packet size". Alternatively in your text based protocol you could use a certain character as a delimiter. However this does mean that you would need to ensure that no legitimate message could contain this delimiter (or implement escape characters).

the stop character sounds lighter than using a size in the packet. if i use ';' as the stop character, i can always implant a little function to make sure ; will only be used as a stop character.

so lets say my packet formad is 2 or three digits for the id, rest for data and in the end a(an?) ;. i still have to somehow make a string out of it, to first enter the id, then add the data from a variable without overwriting the id, and then add ; without overwriting the id+data and i am still not sure how to do it.

## Create an account

Register a new account

• ### Forum Statistics

• Total Topics
628378
• Total Posts
2982334

• 10
• 9
• 15
• 24
• 11