How to sprintf an unsigned char? - c++

This doesn't work:
unsigned char foo;
foo = 0x123;
sprintf("the unsigned value is:%c",foo);
I get this error:
cannot convert parameter 2 from
'unsigned char' to 'char'

Before you go off looking at unsigned chars causing the problem, take a closer look at this line:
sprintf("the unsigned value is:%c",foo);
The first argument of sprintf is always the string to which the value will be printed. That line should look something like:
sprintf(str, "the unsigned value is:%c",foo);
Unless you meant printf instead of sprintf.
After fixing that, you can use %u in your format string to print out the value of an unsigned type.

Use printf() formta string's %u:
printf("%u", 'c');

EDIT
snprintf is a little more safer. It's up to the developer to ensure the right buffer size is used.
Try this :
char p[255]; // example
unsigned char *foo;
...
foo[0] = 0x123;
...
snprintf(p, sizeof(p), " 0x%X ", (unsigned char)foo[0]);

I think your confused with the way sprintf works. The first parameter is a string buffer, the second is a formatting string, and then the variables you want to output.

You should not use sprintf as it can easily cause a buffer overflow.
You should prefer snprintf (or _snprintf when programming with the Microsoft standard C library). If you have allocated the buffer on the stack in the local function, you can do:
char buffer[SIZE];
snprintf(buffer, sizeof(buffer), "...fmt string...", parameters);
The data may get truncated but that is definitely preferable to overflowing the buffer.

Related

Making a std::string out of a Char* in C++

OSX 10.8, Carbon
I have a std::string that I want to derive from a Char*
Example:
CFStringRef *s;
char *c[128];
CFStringGetCString(*s, *c, 128, kCFStringEncodingUTF8);
int size = sizeof(c);
g_uid.assign(c, size);
But I am getting an invalid conversion and I dont understand why
error: invalid conversion from 'char**' to 'long unsigned int'
std::string g_uid = ""; is defined as a global
You're too generous with the asterisks - you generally don't need a pointer to CFStringRef, and your array is actually an array of pointers, which is not what you want.
It should look more like this:
CFStringRef s;
char c[128];
if (CFStringGetCString(s, c, 128, kCFStringEncodingUTF8))
{
g_uid = c;
}
else
{
// 128 characters wasn't enough.
}
If c where a char*, the following would work:
g_uid.assign(c, size);
The problem is that c isn't char*, it's an array of 128 char*s:
char *c[128];
This is a common beginners mistake in C/C++. I remember making this same mistake back in the day. A declaration like
char *c[128]; isn't giving you an array of 128 characters as you might be led to believe. Its actually giving you an array of 128 pointers to chars. You don't want that.
You want to declare an array of 128 chars which looks like:
char c[128];
Now you might not think that c was a char* because you don't see any *s but any time you declare an array of something, that variable is automatically a pointer of whatever type you specify. It actually points to the address of the very first element of the array.

C++ append unsigned char to wstring

I want to append an unsigned char to a wstring for debugging reasons.
However, I don't find a function to convert the unsigned char to a wstring, so I can not append it.
Edit:
The solutions posted so far do not really do what I need.
I want to convert 0 to "0".
The solutions so far convert 0 to a 0 character, but not to a "0" string.
Can anybody help?
Thank you.
unsigned char SomeValue;
wstring sDebug;
sDebug.append(SomeValue);
The correct call for appending a char to a string (or in this case, a wchar_t to a wstring) is
sDebug.push_back(SomeValue);
Documentation here.
To widen your char to a wchar_t, you can also use std::btowc which will widen according to your current locale.
sDebug.push_back(std::btowc(SomeValue));
Just cast your unsigned char to char:
sDebug.append(1, static_cast<char>(SomeValue));
And if you want to use operator+ try this:
sDebug+= static_cast<char>(SomeValue);
Or even this:
sDebug+=boost::numeric_cast<char>(SomeValue);
There's an overload of append that also takes the number of times to append the given character:
sDebug.append(1, SomeValue);
However, this will result in a conversion between unsigned char and wchar_t. Perhaps you want SomeValue to be a wchar_t.
wstring has a constructor that takes a char. That would create a wstring from a char which you can then append.

C++ atoi with unsigned char

I got an unsigned char with the value of 1, I need to put this in a string like "1".
But if I try to put this directly into a stringstream it will get the value of char(1) and I need it to be "1".
I know that if I can get this into the function atoi it will return the "1" value.
But I tried to cast it to char and put it in the atoi function, but it throws an exception.
Already tried to put it in a string and them cast c_str() into atoi function, but without success yet.
If someone can help me I'll apreciate.
Simply cast a char to an int before inserting it into the std::stringstream:
ss << static_cast<int>(c);
This will treat the value of the char not as a character but as a numerical value.
I believe you're confusing two functions here.
You wish to convert an integer to a string.
atoi (ascii to integer) however takes a string and parses it into an integer, making "123" into 123.
You are looking for the itoa function here, which has this prototype:
char * itoa ( int value, char * str, int base );
In your case, this would look like this:
char Buf[10];
itoa(123, Buf, 10);
printf("%s", Buf); //Outputs 123
Please remember though, that itoa is not part of the standard, even though it is supported by some compilers. For a more standard-compliant version use:
sprintf(Buf, "%d", 123);
Of course all of this is plain C, but any C++ compiler will work with this all the same.
To convert a numeric value in the range [0,9] to the corresponding character, just add '0' to it. That's guaranteed to work on all systems.

Why do they want an 'unsigned char*' and not just a normal string or 'char*'

EDIT: After taking adivce I have rearranged the parameters & types. But the application crashes when I call the digest() function now? Any ideas whats going wrong?
const std::string message = "to be encrypted";
unsigned char* hashMessage;
SHA256::getInstance()->digest( message, hashMessage ); // crash occurs here, what am I doing wrong?
printf("AFTER: n"); //, hashMessage); // line never reached
I am using an open source implementation of the SHA256 algorithm in C++. My problem is understanding how to pass a unsigned char* version of my string so it can be hashed?
This is the function that takes a unsigned char* version of my string:
void SHA256::digest(const std::string &buf, unsigned char *dig) {
init();
update(reinterpret_cast<const unsigned char *>(buf.c_str()), static_cast<unsigned int>(buf.length()));
final();
digest(dig);
}
How can I convert my string(which I want hashed) to an unsigned char*?
The following code I have made causes a runtime error when I go to print out the string contents:
const std::string hashOutput;
char message[] = "to be encrypted";
printf("BEFORE: %s bb\n", hashOutput.c_str());
SHA256::getInstance()->digest( hashOutput, reinterpret_cast<unsigned char *>(message) );
printf("AFTER: %s\n", hashOutput.c_str()); // CRASH occurs here
PS: I have been looking at many implementations of SHA256 & they all take an unsigned char* as the message to be hashed. Why do they do that? Why not a char* or a string instead?
You have the parameters around the wrong way. Buf is the input (data to be hashed) and dig is the output digest ( the hash).
Furthermore, a hash is binary data. You will have to convert said binary data into some string representation prior to printing it to screen. Normally, people choose to use a hexadecimal string for this.
The reason that unsigned char is used is that it has guaranteed behaviours under bitwise operations, shifts, and overflow.
char, (when it corresponds to signed char) does not give any of these guarantees, and so is far less useable for operations intended to act directly on the underlying bits in a string.
The answer to the question: "why does it crash?" is "you got lucky!". Your code has undefined behaviour. In short, you are writing through a pointer hashMessage that has never been initialised to point to any memory. A short investigation of the source code for the library that you are using reveals that it requires the digest pointer to point to a block of valid memory that is at least SHA256_DIGEST_SIZE chars long.
To fix this problem, all that you need to do is to make sure that the pointer that you pass in as the digest argument (hashMessage) is properly initialised, and points to a block of memory of sufficient size. In code:
const std::string message("to be encrypted");
unsigned char hashMessage[SHA256_DIGEST_SIZE];
SHA256::getInstance()->digest( message, hashMessage );
//hashMessage should now contain the hash of message.
I don't know how a SHA256 hash is produced but maybe it involves some sort of arithmetic that needs to be done on a unsigned data type.
Why does it matter? Get a char* from your string object by calling the c_str() method then cast to unsigned char*.

is it possible snprintf return char array beginning with '\0'?

I have the following code :
string getid()
{
pthread_t tid = pthread_self();
struct timeval tv;
gettimeofday(&tv, NULL);
uint64_t t = static_cast<uint64_t>(tv.tv_sec);
char buf[64];
snprintf(buf, 64, "%ld-%ld", static_cast<uint64_t>(tid), static_cast<uint64_t>(t));
return buf;
}
sometimes, the returned string has 0 size(), I think one possible reason is buf[0] is '\0', that means pthread_self return '\0' beginning char array?
pthread_self returns a pthread_t, which is not necessarily an integer type. So your cast might not even make sense.
Next, %ld refers to a long int, but you're passing uint64_t values. Depending on the size of a long int on your system, that might again not make much sense.
But, to get to your question : check the return value of the snprintf call : it returns the number of characters that have been successfully written. If it's not at least 3, then something went wrong.
to printf a 64bit number, it is not %ld. The most portable is using the very ugly PRIu64 like:
printf("%"PRIu64"\n", u64);
But I think %llu might also work on your platform.
As other have pointed out, you are returning a pointer to an auto array, meaning it will reside in temporary storage (can in some cases not be the stack). Either return the pointer to an array allocated by new or if you do not need to be reentrant, declare the buffer static, but this is not a very good solution, allocating it on the heap with new would be preferred.