The online racing simulator
C++ - Is_mst
(24 posts, started )
C++ - Is_mst
Hi

I'm having a little trouble trying to send an IS_MST through C++. I've used the C example to set it up, and it can establish a connection. I'm trying to send a message on connection though. Here's what I have:

struct IS_MST is_mst;
memset(&is_mst, 0, sizeof(struct IS_MST));
is_mst.Size = sizeof(struct IS_MST);
is_mst.Type = ISP_MST;
is_mst.ReqI = 0;
is_mst.Zero = 0;

is_mst.Msg[64] = ("^7InSim Connected Successfully! ");

I realise that all of the spaces may not be the best way to make it a 64-byte char, but I don't think that's causing the problem. I get the error message:

error C2440: '=' : cannot convert from 'const char [64]' to 'char'

But I can't see anything that says it's a const char? A google search told me that I can't cast it to a char. So how do I get it to read it as a char?

Any help would be excellent, my C++ is gone fairly rusty at this stage, haven't touched it in months

Rob
strncpy(is_mst.Msg, "^7InSim Connected Successfully!", 63);

It's a character array, not a std::string ("subtle" difference, so you must treat it as a char array)
You're attempting to stuff 64-chars of (constant) text into one char (at index 64 in an arrray), that's not possible

Try something like this instead (size unsafe though):

strcpy(is_mst.Msg, "^7InSim Connected Successfully! ");

Thanks for the replies

When I try

char Message[64] = strncpy(is_mst.Msg, "^7InSim Connected Successfully!", 63);
is_mst.Msg[64] = Message;

and
is_mst.Msg[64] = strncpy(is_mst.Msg, "^7InSim Connected Successfully!", 63);

and
is_mst.Msg[64] = strncpy(is_mst.Msg, "^7InSim Connected Successfully!");

I get an error message 'cannot convert from 'char *' to 'char''

Sorry to be so dependant, but what is a char *? Google treats it as a wildcard, so that doesn't show anything with a search One page that I did find says that char * is the same as char[], and that they are interchangeable though?

Thanks for the help, it's definitely an improvement from where I was
A char * is a pointer to the location of a character array in the memory (think of it as an address). Depending on how pedantic your compiler is setup to be, will depend on whether or not it'll allow you to do the code that was given as an example originally.

EDIT: Whoa, I've just noticed what you're doing in the code above (I need to start reading more carefully today).

Dont' assign the output of strncpy to your message. What you want to be doing is something like this;
struct IS_MST is_mst;
memset(&is_mst, 0, sizeof(struct IS_MST));
is_mst.Size = sizeof(struct IS_MST);
is_mst.Type = ISP_MST;
is_mst.ReqI = 0;
is_mst.Zero = 0;
strncpy(is_mst.Msg, "^7InSim Connected Successfully!", 63);

or, if your compiler is really fussy;
strncpy(&(is_mst.Msg), "^7InSim Connected Successfully!", 63);

You're more in the realm of C, rather than what may normally be considered the ++ parts of C++

You'll notice I use strncpy, rather than strcpy. The reason for this is that if you try and copy something too large for the character array, you'll end up out of bounds. strncpy allows you to state the max length to copy into the memory destination (your Msg, in this instance). If someone can push too far you can end up with usable exploits, etc. It's a bit out of the realm of discussion, but basically treat everything with care at this sort of level. There is no "real" bounds checking when you're this far in the dirty stuff

Edit 2: I think you might need to a quick read over of what pointers and references are dougie..
Thanks a million for that TAA

Was just about to give up, but saw your edit. Works like a charm

Out of curiosity, why doesn't the output get used as the message?

E: I'll have a look at pointers and references now, C# has dumbed me down
Quote from dougie-lampkin :Out of curiosity, why doesn't the output get used as the message?

C (and C++, which is just an extension to C at the end of the day) isn't memory managed (as such - I'm not going to get into the complicated argument of user malloc'ed memory, and stuff that the compiler will magically free in certain situations as its a bit complicated), which means you have a fair bit of control over how everything gets allocated, etc.

Character arrays (also known as NULL terminated strings - this is why you tend to write to length of string - 1, so that you can terminate the string with a \0 - InSim isn't fussy in most cases, however it's still good practise tbh) are pretty much your basic string. It's effectively an area of contiguous memory which you write to. In this case it's 64 bytes all sat next to each other. What strncpy and it's cousin memcpy do is take one string (or item of memory) and copy it verbatim into your destination area of memory (in this case a 64 byte area of memory, which is your character array).

Since your dealing with memory you don't need to assign the return value to your Msg variable, as you've just written the location to which it is actually stored in.

strncpy returns pointer to the location of the memory of which it's written to. So (if you're still following), when you assign the output of strncpy to your Msg variable you're trying to assign a pointer to a character array, and that pointer is pointing to the location you've just written to. So ineffect you're trying to overwrite the memory you're pointing to by telling something that you're pointing to that memory (I've tried really hard to make that easy to understand, but I may have lost some people here, I fear). This is daft for obvious reasons, although perfectly "valid" if the datatypes all matched up (which they don't in this case). In the compiler's eyes this is invalid because a pointer to a character array and a character array are fundamentally 2 different data types. It doesn't care too much that you're doing something potentially a little silly

Now that may be a little confusing, but I think that's about as clear as I can make it without turning into a whole tutorial on C and memory Hopefully it's relatively understandable?

Edit: If not gimme a buzz via pm and we'll figure out a way of getting in touch if you like. I can't spare a lot of time in the evenings, but we can figure something out...
[OT] - I can see you are using too much C# within C++. They are not THAT close in terms of setting objects etc etc... [OT]
Quote from the_angry_angel :Now that may be a little confusing, but I think that's about as clear as I can make it without turning into a whole tutorial on C and memory Hopefully it's relatively understandable?

I did understand that (after a few goes, admittedly :shy! Thanks for the explanation Karl, I see now why it clearly didn't work the first time


Quote from mcgas001 :[OT] - I can see you are using too much C# within C++. They are not THAT close in terms of setting objects etc etc... [OT]

I know, I was just as bad when I was trying Python earlier
Quote from dougie-lampkin :I did understand that (after a few goes, admittedly :shy!

I did reword it a few times, so I apologise if you got it between edits The nytol I took has kinda worn off now though

Quote from dougie-lampkin :I know, I was just as bad when I was trying Python earlier

You'll wear out your tab key if you use Python too much It's a known bug!
Quote from dougie-lampkin :I know, I was just as bad when I was trying Python earlier

Word of advice: Pick a language and stick with it.

Quote from the_angry_angel :You'll wear out your tab key if you use Python too much It's a known bug!

Don't let DarkTimes hear you say that.

E: Just read TAA's C Tutorial, C/C++ Memory allocation can be 'fun' at times..... - I mean This not this!
I'm not going to learn Python (no need - I already have Yabasic for those small scripts), I was just trying to out, as it was mentioned. It's not for me anyway (sorry, I tried!), it's like another syntax

I'm going to give C++ a good go though, as I'm hoping to do some form of computer course in a couple of years. No idea on that either though, everybody I've spoken to has told me how this course is better, and this course is best, and I'd be good at this one, etc. They don't make it easy anyway

Thanks for the help all

(It is the C Tutorial I'm using, I found a post that explains how to use it in VC++ )

E: TAA, just saw your edit. I'm going to be farming this summer, so no internet for me (Don't know how I'm going to survive 2 months with no internet!) Thanks a bunch for the offer though
I disagree. Use the best language for the job. Unless you were just talking about learning, I agree it's better to stick to one language for a little.

OP: Buy "Thinking in C++" by Bruce Eckel if you want to understand C++ and pointers.

Quote from mcgas001 :Word of advice: Pick a language and stick with it.

Quote from dougie-lampkin :I'm not going to learn Python (no need - I already have Yabasic for those small scripts), I was just trying to out, as it was mentioned. It's not for me anyway (sorry, I tried!), it's like another syntax

Python's syntax is practically identical to the C family of languages, it just uses tabs instead of curly-braces.
:bump:

I'm stuck again...I got playing with it, and I'm trying to put 3 different sized chars together into an MST. I'm trying to include NPL->PName in a message that's sent when someone connects. I've tried various things, such as:

strncpy_s(is_mst.Msg, ("/msg " + t->PName + " ^Lconnected"), 63);

strncpy_s(is_mst.Msg, ("/msg " << t->PName << " ^Lconnected"), 63);

strncpy_s(is_mst.Msg, ("/msg " & t->PName & " ^Lconnected"), 63);

strncpy_s(is_mst.Msg, ("/msg ", t->PName, " ^Lconnected"), 63);

None of which compiled, except the last one, which just has the connected bit.

I couldn't find much on t'interwebs, I'm probably just missing something basic though...
<< is the stream insertion operator...which doesn't make sense there and won't compile (a string literal doesn't have operators, same reason try #1 didn't work). & is logical and, which ANDs bits together (e.g. 1 & 0 = 0, 0 & 0 = 0, 1 & 1 = 1), and is definitely not what you want. I don't know why the last thing compiled.

"/msg " isn't a C++ string, which has the overloaded + operator that concatenates. It's just an array of chars with \0 put on the end. You can't use + with c-strings to concatenate, you'd have to use another c std function (strcat, or there's probably an strcat_s that's length safe). The difference is that C++ strings are a class, which has methods and overloaded operators and the like. C-strings are just arrays that happen to have chars in them and always end in a null terminating character (\0). String literals, like "hey there" are basically c-strings (aka char arrays).

For your problem, I'd probably just:
#include <string>
using std::string; (or leave off if you've already got using namespace std

then

string builder = "/msg " + t->PName + "^Lconnected"; //uses the overloaded + operator of the string class
strncpy_s(is_mst.Msg, builder.c_str(), 63); //c_str() returns the c-string equivalent (a char*)

I'm assuming is_mst.Msg is a char*, and t is a pointer with a member PName that's a char*.

You should buy "Thinking in C++" by Bruce Eckel: http://www.amazon.com/Thinking ... qid=1215644946&sr=8-1. You can get a free copy of the older edition on his website, although it's a lot easier to read it from a book.

Quote from dougie-lampkin ::bump:

I'm stuck again...I got playing with it, and I'm trying to put 3 different sized chars together into an MST. I'm trying to include NPL->PName in a message that's sent when someone connects. I've tried various things, such as:

strncpy_s(is_mst.Msg, ("/msg " + t->PName + " ^Lconnected"), 63);

strncpy_s(is_mst.Msg, ("/msg " << t->PName << " ^Lconnected"), 63);

strncpy_s(is_mst.Msg, ("/msg " & t->PName & " ^Lconnected"), 63);

strncpy_s(is_mst.Msg, ("/msg ", t->PName, " ^Lconnected"), 63);

None of which compiled, except the last one, which just has the connected bit.

I couldn't find much on t'interwebs, I'm probably just missing something basic though...

Thanks for the help. It still gives the same error as the original way though,

error C2679: binary '+' : no operator found which takes a right-hand operand of type 'char *' (or there is no acceptable conversion)

on the Builder line...Which is what I couldn't figure, as + is what I'm used to
can you copy/paste the code you're using?
Quote from brianmcd :can you copy/paste the code you're using?

Sure, here's the NCN packet receiver, along with the construction of the MSO packet:

Quote :struct IS_NCN *t = (struct IS_NCN *)p;
struct IS_MST is_mst;
memset(&is_mst, 0, sizeof(struct IS_MST));
is_mst.Size = sizeof(struct IS_MST);
is_mst.Type = ISP_MST;
is_mst.ReqI = 0;
is_mst.Zero = 0;

string builder = "/msg " + t->PName + "^Lconnected"; //uses the overloaded + operator of the string class
strncpy_s(is_mst.Msg, builder.c_str(), 63); //c_str() returns the c-string equivalent (a char*)

Sorry, I wasn't thinking.
string builder = "/msg ";
builder += t->PName;
builder += "^Lconnected";
strncpy_s(is_mst.Msg, builder.c_str(), 63); //c_str() returns the c-string equivalent (a char*)
Quote from brianmcd :Sorry, I wasn't thinking.
string builder = "/msg ";
builder += t->PName;
builder += "^Lconnected";
strncpy_s(is_mst.Msg, builder.c_str(), 63); //c_str() returns the c-string equivalent (a char*)

Cheers mate, just the job
Glad to help. The reason the first thing I posted didn't work is because I made the same mistake as you. Like I said, string literals and c-strings aren't classes, so I was trying to use the + operator on c-strings (which are just arrays)...which doesn't work because they don't support the + operator. The second thing I posted works because you're always adding a C-string to a C++ string, and the C++ string class overloads the + operator to work when adding a c-string to a c++ string.

Really check out that book, Thinking in C++. It's awesome and if you want to study computer science in school, this will get you way ahead.
I'll definitely check that out, I'm hoping to do a programming course in a year or two, so I'm getting all the knowledge I can
#24 - wien

C++ - Is_mst
(24 posts, started )
FGED GREDG RDFGDR GSFDG