Concatenating char and string in Arduino - c++

I'm playing with an Arduino board and the samples provided. Trying to get a message I received to be displayed on the LCD. I'm struggling to figure out how to work with some of the pre-built code.
I get the error: invalid conversion from 'const unsigned char*' to 'const char*
I tried modify the payload parameter type but it breaks other references to MessageCallback.
Screen.print() definition in the documentation for the arduino board:
int print(unsigned int line, const char s, bool wrap)
Code:
static int MessageCallback(const unsigned char *payload)
{
int result = 200;
const char screenMsg[100];
strcpy(screenMsg,"Set Temp: ");
strcat(screenMsg,payload);
Screen.print(1, screenMsg, true);
return result;
}

Strcat's arguments are (char *, const char *). You can cast "payload" to a char* by doing "strcat(screenMsg, (char*)payload);". Read Strcat two unsigned char in C.

If you just change to char screenMsg[100]; it should work.
The print function will not change the string you provide to it, is all that
const char s
means.

Related

How would I pass a string to a function argument defined as const unsigned char*?

I copied Base64 encode/decode functions from Stack Overflow. The decode function works great. My problem is with the encode. I get the following error using Visual Studio 2022:
error C2664: 'std::string Base64_encode(const unsigned char *,size_t)': cannot convert argument 1 from 'const _Elem *' to 'const unsigned char *'
Code snippet:
string Base64_decode(const void* data, const size_t len);
string Base64_encode(const unsigned char* src, size_t len);
int main(int argc, char* argv[])
{
string lsOriginal;
string lsEncoded;
string lsDecoded;
lsEncoded = Base64_encode(lsOriginal.c_str(), lsOriginal.size());
lsDecoded = Base64_decode(lsBase64.c_str(), lsBase64.size());
I tried using reinterpret_cast but I couldn't get it to work. I've never used it before so I'm struggling to get it to compile.
The problem is that std::string::c_str returns a const char* and your function Base64_encode takes an const unsigned char*but there is no implicit conversion from a const char* to const unsigned char*.
To solve this you could use reinterpret_cast as shown below:
Base64_encode(reinterpret_cast<const unsigned char *>(lsOriginal.c_str()), lsOriginal.size());
Working demo
You can even change the functions to so that their first parameter is a const std::string&. Then there will be no need to have the second parameter corresponding to size since we can use std::string::size member function.
//------------------------vvvvvvvvvvvvvvvvvv------------------->first parameter is lvalue reference to const std::string
std::string Base64_encode(const std::string& src)
//----------------------------------------------^-------------->no need for having second parameter
{
return "fd";//return something
}
int main(int argc, char* argv[])
{
std::string lsOriginal = "fdfd";
std::string lsEncoded;
//--------------------------vvvvvvvvv---------------------->pass the original string by reference
lsEncoded = Base64_encode(lsOriginal);
}

char array to unsigned char *

So i have this function which receives a pointer:
int myfunc( const char *token, unsigned char *plaintext )
I do my stuff and i end up with a char array:
unsigned char my_plaintext[1024];
Now i need to set that pointer (plaintext) to what's in my_plaintext.
I've tried many different ways but i haven't yet figure this one out...
This part is in a cpp file, and i've even tried:
std::string tmpstr( my_plaintext );
But this comes back with:
token_crypto.cpp:131:13: error: invalid conversion from 'char*' to 'unsigned char*' [-fpermissive]
my_plaintext
^~~~~~~~~~~~
And
std::string tmpstr( (char *)my_plaintext );
'�5�B'
this does compiles but the content is all wrong:
EDIT:
The content of my_plaintext is fine:
int myfunc( const char *token, unsigned char *plaintext ) {
unsigned char my_plaintext[1024];
... some processing stuff (specifically gcm_decrypt) to which is pass my_plaintext ...
cout << my_plaintext
// prints: hello:world
but then however i try set the contents of plaintext to whatever is in my_plaintext either fails at compilation or prints some weird characters.
If you know that plaintext already points at an array that is 1024 long (or longer) then you can use memmove():
int myfunc( const char *token, unsigned char *plaintext )
{
unsigned char my_plaintext[1024];
/* ... fill in my_plaintext here ... */
memmove(plaintext, my_plaintext, 1024);
/* ... rest of function ... */
}
Note that the parameters to memmove are destintation and then source rather than the other way round.
It's up to the caller of your function to make sure the pointer they pass in points to at least 1024 bytes.
You can use memcpy() instead in this case, but using memmove() is good practice in general.
The C++ string constructor doesn't take an unsigned char *. See the C++ reference here:
http://www.cplusplus.com/reference/string/string/string/
You need to cast the unsigned char array to a char array. See how to do that here:
How to Convert unsigned char* to std::string in C++?

Argument of type "unsigned char *" is incompatible with parameter of type "const char *"

I was using the Decoder for Microsoft Script Encoder. It works perfectly well when I run it in Codeblocks. But when I run it in Visual Studio, it shows me the following errors
Snippet 1:
char decodeMnemonic(unsigned char *mnemonic)
{
int i = 0;
while (entities[i].entity != NULL)
{
**if (strcmp(entities[i].entity, mnemonic) == 0)**
**//Error 1: cannot convert argument 2 from 'unsigned char *'
// to 'const char *'**
return entities[i].mappedchar;
i++;
}
printf("Warning: did not recognize HTML entity '%s'\n", mnemonic);
return '?';
}
I had to integrate the Decoder in a program, so instead of passing the filenames as command line arguments, I have given their filepaths myself in the code.
Snippet 2:
int main()
{
unsigned char *inname = "C:\\Users\\Karthi\\Desktop\\Project Winter 2018-19\\poweliks_sample\\poweliks_encoded_js.bin";
unsigned char *outname = "C:\\Users\\Karthi\\Desktop\\Project Winter 2018-19\\poweliks_sample\\decoded1.txt";
unsigned int cp = 0;
//**Error 2: 'initializing': cannot convert from 'const char [87]' to 'unsigned char *'**
You can use reinterpret_cast (for unsigned char* to const char*). But if you go from const unsigned char* to a non const type, you have to use const_cast first, since reinterpret_cast cannot cast away a const.
The paragraph below gives a brief overview, why your code did not work.
According to C99 Standard (similiar to other C standards), a string literal has static storage duration and its type is char[] The standard says:
If the program attempts to modify such an array, the behavior is undefined.
The reason why your program worked, when you used argv is, that argv is not considered as an array of string literals. This means you can modify them.
Here are the solutions for your problems:
Snippet 1:
strcmp is a method to compare two C Strings. It expects const char* types.
int strcmp ( const char * str1, const char * str2 );
You have two option to solve it:
Declare your method like this
char decodeMnemonic(const char *mnemonic)
Use C++Strings and declare your method like this
char decodeMnemonic(std::string mnemonic)
If you use the second solutions you have to call the c_str()-Method to use it in strcmp
if (strcmp(entities[i].entity, mnemonic.c_str()) == 0)
Or you use only C++-String: read here how to use it: http://www.cplusplus.com/reference/string/string/compare/
Snippet 2: You can't use it like this because you have string literals which are arrays constant characters.
Please use C++-Strings. You work with C++, so use his features (https://www.geeksforgeeks.org/stdstring-class-in-c/)
Anyway if you want to use it C-like: https://www.programiz.com/c-programming/c-strings
char c[] = "abcd";
char c[50] = "abcd";
Or with const (C++)
char *str1 = "string Literal";
const char *str2 = "string Literal";

C++ cast char * to unsigned char

I am working in a c++ project where I have to use < openssl/sha.h> and I am using in particular the SHA1 function. My problem is, that the function receives unsigned char[], and I need to get processed parameters passed as arguments to the program:
int main(int argc, char* argv[])
{
unsigned char message[] = argv[1];
/* program continues using message */
}
And the error I am getting is the following:
error: array initializer must be an initializer list or string literal
const unsigned char message[] = argv[1];
^
So I am not getting to cast appropiately the argument input to the 'message' variable, to make the appropiate call to SHA1 function.
Thanks!!
An array cannot be initialized from a pointer. You should probably use an unsigned char * instead:
unsigned char *message = reinterpret_cast<unsigned char *>(argv[1]);

Conversion from 'const char *' to 'unsigned char *' in C++?

I have an encryption function declared as follows: int encrypt(unsigned char* keydata, int keydata_len, unsigned char *plaintext, int plaintext_len, unsigned char *ciphertext). This works perfectly and now I call it according to the given snippet.
const char *password = "password";
len = encrypt(password, (int)strlen(password), (unsigned char*)(content.c_str()), (int)strlen(content.c_str()), ciphertext);
On compiling the C++ code I get an error as:
crest.cc:52:13: error: no matching function for call to 'encrypt'
len = encrypt(password, (int)strlen(password), (unsigned char*)(content.c_str()), (int)strlen(content.c_str()), ciphertext);
^~~~~~~
./aes.h:10:5: note: candidate function not viable: no known conversion from 'const char *' to 'unsigned char *' for 1st argument
int encrypt(unsigned char* keydata, int keydata_len, unsigned char *plaintext, int plaintext_len, unsigned char *ciphertext);
What is the correct way to typecast in C++ to get around this error ?
There are several problems with this code, and the only (correct) way to fix them is to ensure that you use the correct data types in the first place.
So, instead of const char *password = "password", use unsigned char password[] = "password"; (of course, this will probably give you trouble with strlen, since it won't like unsigned char) - using sizeof(password)-1 will work in THIS instance, but is ill advised as a general solution, since password may well be not be directly available as an array - not sure quite what you should do as an "ideal" solution, really.
Now, the question can be asked whether it is actually correct to have a non-const input to the function. If you have the source for encrypt, you may want to change the function to encrypt(const unsigned char* keydata, size_t keydata_len, const unsigned char* plaintext, size_t plaintext_len, unsigned char* ciphertext) - still doesn't fix the problem with strlen of unsigned char of course, but it's what I'd expect the prototype to be for a function like this.
An alternative would be to rewrite the encrypt function to make casts to unsigned only internally, and use char * inputs (with const where relevant).
Note that it's NOT valid to cast away constness EXCEPT for cases where you know that the original content is not const (which I think is NOT guaranteed to be the case for std::string::c_str(), but std::string::data() should work)