I am trying to convert a byte* parameter passed into an mqtt callback function to an int for comparison and I can't seem to get it working. Any help would be welcomed.
int fsrReading;
void callback(char* topic, byte* payload, unsigned int length) {
for (int i=0;i<length;i++) {
Serial.print((char)payload[i]); // This works well
fsrReading = int((char)payload[i]);
if (fsrReading < 0){
...
The correct way to do this depends on exactly what representation of a number is being used.
I suspect the message is a string representation of a number: "1234", which is being received as an array of ascii byte values.
If that is the case, you can rebuild a String object and convert it to an int:
int fsrReading;
void callback(char* topic, byte* payload, unsigned int length) {
String value = "";
for (int i=0;i<length;i++) {
value += (char)payload[i];
}
fsrReading = value.toInt();
...
There is an example of converting a String to an Int in the arduino tutorials here: https://www.arduino.cc/en/Tutorial/StringToIntExample
EDIT: original answer part before explanation:
Depends on compiler, compiler options etc char can be signed or unsigned, cast via (char) can work different than You expect.
Example:
payload[i] is 0x81
unsigned char -> 129, then >0
signed char -> -127, then <0
Your cast via (char) is redundant (and unstable like i said)
I don't give sample code because I don't understand Your goal. Code has contradictions.
Disclaimer: Your byte seems non standard type. I belive that is unsigned char a such type NEVER is <0 .
What is main sense of this variable? In deep, it is signed or unsigned? You can cast (unigned char) but is never<0 or (signed char) - up to You
EDIT:
after comment of asker, and interpretation from knolleary hot to interpret length (important: change of loop sense, maybe you understand author correctly) I give pure C conversion
int val = 0;
for (int i=0; i<length; i++) {
val = val*10 + payload[i]-'0';
}
// If someone know end of number is marked in different way, need implement break of `for`
fsrReading =val;
I believe my is few CPU cycles/RAM better.
EDIT2: I have read few materials from Arduino community, problem with loop concatenation into String is like in many languages: many, many small allocations (while concatenation is totally not required here). Many good Arduino programmers are critical to overuse of String. It isn't "secret knowledge", it is general rule in programming.
http://forum.arduino.cc/index.php?topic=185469.0
http://www.gammon.com.au/concat
Related
I'm reviewing the security of an app for a University project, the app encrypts a file using RSA, specifically it uses this library: https://github.com/ilansmith/rsa (DO NOT use this, it has serious vulnerabilities).
(If you want to take a look, most of the operations between these numbers are implemented in the rsa_num.c file.)
This tool uses arrays of unsigned long long to store the big numbers needed for RSA (n, e and d):
typedef struct {
u64 arr[17]; //u64 is defined as unsigned long long
int top; //points to the last occupied slot of the array
} u1024_t;
The problem is that I don't understand how the numbers are stored in this format.
What I need is being able to print the real numbers in some way, or at least a way to recover the numbers from the components of the arrays.
I tried just concatenating them like strings, but it doesn't seem right.
Thanks to whoever will be able to help!
Thank you #Matthieu! Your comment worked.
I needed to concatenate the unsigned long longs in reverse order and reversing their bytes due to endianness.
Following his solution, I implemented this function, which works perfectly:
void print_u1024(u1024_t number) {
int size = (number.top + 1) * sizeof(u64);
for (int i = size-1; i >= 0; i--) {
printf("%02x", ((unsigned char*)number.arr)[i]);
}
printf("\n");
}
Please note that this solution will probably only work on little-endian systems (most PCs).
After checking out this question I did not found required solution, so I've tried to use strtol in following manner:
in = (unsigned char *)malloc(16);
for(size_t i = 0; i < (size_t)strlen(argv[2]) / 2; i+=2 )
{
long tmp = 0;
tmp = strtol((const char *)argv[2] + i, &argv[2] + 2, 16);
memcpy(&in[i], &tmp, 1);
}
This code produced several intermediate values:
Can someone please explain me why entire in array gets filled by 0xFF(255) bytes and why tmp is not equal it's estimated value?
Tips about how to improve above code to fill in array with correct hex values also welcome.
Your code is erroneous for multiple counts and the casts hide the problems:
Casting the return value of malloc is not necessary in C and can potentially hide an unsafe conversion if you forget to include <stdlib.h>:
in = (unsigned char *)malloc(16);
Casting the return value of strlen to (size_t) is useless, even redundant as strlen is defined to return a size_t. Again you might have forgotten to include <string.h>...
for (size_t i = 0; i < (size_t)strlen(argv[2]) / 2; i += 2) {
long tmp = 0;
strtol takes a const pointer to char, which argv[2] + i will convert to implicitly. The cast (const char*) is useless. The second argument is the address of a char*. You pass the address of the fifth element of argv, in other terms &argv[4], most certainly not what you indent to do, although your loop's purpose is quite obscure...
tmp = strtol((const char *)argv[2] + i, &argv[2] + 2, 16);
Copying the long value in tmp with memcpy would require to copy sizeof(tmp) bytes. Copying the first byte only has an implementation defined effect, depending on the size of char and the endianness of the target system:
memcpy(&in[i], &tmp, 1);
}
You should post a complete compilable example that illustrates your problem, a code fragment is missing important context information, such as what header files are included, how variables are defined and what code is executed before the fragment.
As written, your code does not make much sense, trying to interpret its behavior is pointless.
Regarding the question in reference, your code does not even remotely provide a solution for converting a string of hexadecimal characters to an array of bytes.
Let me start by saying that I openly admit this is for a homework assignment, but what I am asking is not related to the purpose of the assignment, just something I don't understand in C. This is just a very small part of a large program.
So my issue is, I have a set of data that consists various data types as follows:
[16 bit number][16 but number][16 bit number][char[234]][128 bit number]
where each block represents a variable from elsewhere in the program.
I need to send that data 8bytes at a time into a function that accepts uint32_t[2] as an input. How do I convert my 234byte char array into uint32_t without losing the char values?
In other words, I need to be able to convert back from the uint32_t version to the original char array later on. I know a char is 1byte, and the value can also be represented as a number in relation to its ascii value, but not sure how to convert between the two since some letters have a 3 digit ascii value and others have 2.
I tried to use sprintf to grab 8byte blocks from the data set, and store that value in a uint32_t[2] variable. It works, but then I lose the original char array because I can't figure out way to go back/undo it.
I know there has to be a relatively simple way to do this, i'm just lacking enough skill in C to make it happen.
Your question is very confusing, but I am guessing you are preparing some data structure for encryption by a function that requires 8 bytes or 2 uint32_t's.
You can convert a char array to uint32_t as follows
#define NELEM 234
char a[NELEM];
uint64_t b[(NELEM+sizeof(uint64_t)-1)/sizeof(uint64_t)]; // this rounds up to nearest modulo 4
memcpy(b,a,NELEM);
for(i .. ) {
encryption_thing(b[i]);
}
or
If you need to change endianess or something, that is more complicated.
#include <stdint.h>
void f(uint32_t a[2]) {}
int main() {
char data[234]; /* GCC can explicitly align with this: __attribute__ ((aligned (8))) */
int i = 0;
int stride = 8;
for (; i < 234 - stride; i += stride) {
f((uint32_t*)&data[i]); }
return 0; }
I need to send that data 8bytes at a time into a function that accepts
uint32_t[2] as an input. How do I convert my 234byte char array into
uint32_t without losing the char values?
you could use a union for this
typedef union
{
unsigned char arr[128]; // use unsigned char
uint32_t uints[16]; // 128/8
} myvaluetype;
myvaluetype value;
memcpy(value.arr, your_array, sizeof(value.arr));
say the prototype that you want to feed 2 uint32_t at a time is something like
foo(uint32_t* p);
you can now send the data 8 bytes at the time by
for (int i = 0; i < 16; i += 2)
{
foo(myvaluetype.uints + i);
}
then use the same struct to convert back.
of course some care must be taken about padding/alignment you also don't mention if it is sent over a network etc so there are other factors to consider.
So, I wrote a function converting a decimal number into a hexadecimal number by using recursion, but I can't seem to figure out how to add the prefix "0x" and leading zeros to my converted hexadecimal number. Let's say I pass the number 18 into the parameters of my function. The equivalent hexadecimal number should be 0x00000012. However, I only end up getting 12 as my hexidecimal number. The same applies when I pass in a hexidecimal number 0xFEEDDAD. I end up getting only FEEDDAD without the prefix as my answer. Can someone please help me figure this out? I've listed my code below. Also, I'm only allowed to use fputc to display my output.
const char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
void hexout (unsigned long number, FILE * stream)
{
long quotient;
long remainder;
quotient = number / 16;
remainder = number % 16;
if(quotient != 0)
hexout(quotient,stream);
fputc(digits[remainder],stream);
}
void hexout (unsigned long number, FILE * stream)
{
fprintf(stream, "0x%08lX", number);
}
If you cannot use fprintf (neither sprintf), you can use this kind of code (no recursion, but a 8-chars array on the stack):
const char digits[] = "0123456789ABCDEF";
void hexout(unsigned long number, FILE * stream)
{
unsigned long int input = number;
unsigned long int quotient;
unsigned long int remainder;
unsigned short ndigit = 0;
char result[8] = {0};
// Compute digits
do
{
quotient = input / 16;
remainder = input % 16;
result[7-ndigit] = digits[remainder];
input = quotient;
ndigit++;
}
while (ndigit < 8);
// Display result
fputc('0', stream);
fputc('x', stream);
for (ndigit = 0; ndigit < 8; ndigit++)
{
fputc(result[ndigit], stream);
}
}
Of course, this can be improved a lot...
Add digits to a string, and print out string with zero-padding using fprintf. Or just use fprintf to begin with.
Your own hexout fails for obvious reasons. You cannot 'continue' to output a number of zeroes when the value reaches 0, because you don't know how much numbers you already emitted. Also, you don't know when to prepend "0x" -- it should be before you start to emit hex digits, but how can you know you are at the start?
The logical way¹ to do this is to not use recursion, but a simple loop instead. Then again -- unsaid, but a fair bet this is a homework assignment, and in that case any number of silly constraints are possible ("write a C program without using the character '{'" comes to mind). In your case it's "you must use recursion".
You must add a counter to your recursive function; when it reaches 0, you know you have output 0x, and if it's not 0 you need to output a hex digit, irrespective if your value is 0 or not. There are a couple of ways of adding a counter to a recursive function: a global variable (which would be the easiest and utterly ugliest way, so please don't stop reading here), a static variable -- only semantically better than a global --, or a pass-by-reference argument (of which some say is a myth, but then again the end result is the same).
Which method is best for you depends on how well you can defend why you used that method.
¹ So is printf("0x%08X") an "illogical" solution? Yes. It solves the problem but without any further insights. The purpose of this assignment is not to find out the existence of printf and its parameters, it's to learn how (and why) to use recursion.
So here's the code:
int create_mask(unsigned b, unsigned e)
{
unsigned int mask=1;
if(b<e || b<0 || e<0)
{
printf("Wrong values, starting bit can't be smaller than ending.\n");
printf("Both got to be >= 0.\n");
exit(EXIT_FAILURE);
}
while(b>0)
{
printf("%u\n", b);
mask<<=1;
if(b>e)
mask|=1;
b--;
}
return ~mask; /* negates mask for later purpose that is clearing corresponding bits */
}
Function creates mask for some bit operations, but should take two unsigned ints b and e, both non-negative. Question is how to prevent user input of negative numbers?
When function is called with (-1,0) it start the loop, and shoult exit with error.
You could just input a string, check if it contains a '-' character, and yield an error if it does. Else you convert it to an unsigned integer and proceed on. (Reading as a string then converting with strtoul() is preferred over using scanf() anyway, especially while you aren't aware of all of the quirks of scanf().)
char buf[LINE_MAX];
fgets(buf, sizeof buf, stdin);
if (strchr(buf, '-') != NULL) {
fprintf(stderr, "input must be non-negative!\n");
exit(-1);
}
unsigned int n = strtoul(buf, NULL, 0);
Edit:
you can take the long int input and then checks input is in between 0 to ending range of unsigned int .if so then assign to your variable else rise an exception to the user ,you should only give unsigned numbers as input.
long int input;
unsigned int valid_input;
scanf("%ld",&input);
if((0<= input) && (input <= 4294967295))
valid_input= (unsigned int)input ;
else
printf("Unvalid input\n");
As H2CO3 said.
reading input into string and checking for first literal if it is not minus then convert into unsigned integer would be preferable rather than the below method. because half of the part unsigned integers not covered.
you can get the input into int and then if it is non negative then proceed .if it is negative rise an exception to the user ,you should not give negative input.
Take a look at this: Stopping function implicit conversion
I was able to adapt it to your issue, and it stops the program from linking. The info in the above thread seems partially incorrect because the example compiled fine. It failed to link because there was not a template specialization defined. I'm actually a little surprised that the following worked for the int vs unsigned int.
template <class T>
void foo(const T& t);
template <>
void foo<unsigned int>(const unsigned int& t)
{
}
int main(){
foo((unsigned int) 9); // will compile and link
unsigned int value(5);
foo(value);// will compile and link
foo(9.0); // will not link
foo(-9); // will not link
return 0;
}
I think that you might be over thinking this though. Is it really a problem? Would it be better to make your id type an int to begin with? Is there a min/max id that avoids the large numbers that could be mistaken for a twos compliment? This seems like an unfortunate issue with the language that it doesn't provide any easy way to stop an implicit cast.
I tested the example with Visual Studio 2010. Additionally, I didn't have the time to write a test class so if it interests you then you'll have to adapt the example to a foo class to see if it works with a constructor of a class, or if there is another way to use templates to do this. Based on the other answers, and my experience I don't think that you are going to find an easy way to do what you want.