How to Get Last Four Number to String From Character Array in Mikroc Pro - mikroc

I have character array like bellow,
char ch1_on[]="0123456789";
I need to get last four number (6789) of above variable to int variable. how can i do it?

The function that you need is "memmove" from the MikroC library.
Its prototype is defined as: void *memmove(void *to, void *from, int n);
where void *to is a temporary char array (This will hold the substring 6789), void *from is your char array ch1_on plus the starting index of what you need to copy (In your case +6 because you want to copy the characters from index 6 to 9) and int n where 'n' is the number of characters to copy (which is 4 in your case; 6, 7, 8, 9).
So to work on it, you just need to declared a holder:
char converted[] = "0000";
and do a memmove:
memmove(converted, ch1_on + 6, 4);
and finally, use atoi to convert the substring to integer.
result = atoi(converted);
result will hold the final integer.
For more information, please refer to the help section of MikroC and search for 'memmove' under the ANSI C String Library topic.

Related

Different result between Serial.print and Serial.printf in ESP32

I want to print my string variable using printf method:
id = 6415F1BF713C
Serial.printf("id: %s\n\n", id);
Serial.print(id);
The result that I got was:
id: ⸮⸮⸮?
6415F1BF713C
is there any thing that's wrong?
Thanks.
Update :
//get device id
String getDeviceID() {
uint64_t chipid = ESP.getEfuseMac(); // The chip ID is essentially its MAC address(length: 6 bytes).
uint16_t chip = (uint16_t)(chipid >> 32);
char devID[40];
snprintf(devID, 40, "%04X%08X", chip, (uint32_t)chipid);
return devID;
}
String id = getDeviceID();
Serial.printf("id: %s\n\n", id);
Serial.print(id);
You didn't offer enough code to properly debug this, but I'm guessing what you mean is
String id = "6415F1BF713C";
Serial.printf("id: %s\n\n", id);
Serial.print(id);
The %s format in the printf() method expects to take a C/C++ char *, not a String. When you passed it a String, it printed the memory address of the String object - four characters which would appear as garbage, as you saw.
C and C++ use char * (pointers to characters) and char [] (arrays of characters) to represent strings. These are different from the Arduino String class, and people often confuse them.
To use the printf() method with a String you need to get its C string pointer, like this:
Serial.printf("id: %s\n\n", id.c_str());
The reason that this:
Serial.print(id);
works is that the print() method has a form that specifically expects to take a String object as an argument.

How can a 1 byte int conversion of a QByteArray fail?

So here is the thing, I'm receiving 1 byte from Bluetooth transmission. When using QDebug I get this message:
The array with error has "\x06"
The line that fails is this:
bool ok = true;
int v = value.toInt(&ok,0);
Because ok has false. But I'm trying to wrap my head around the fact that, How can the conversion fail in the first place if the data represented in that byte (as a sequence of zeros and ones) will always have a valid integer representation. (one byte can always be represented as a int between -127 and 128). So I'm left with the question, how can the conversion fail?
Reading the documentation does not provide many clues as it does not say how the byte array will be interpreted.
QByteArray::toInt converts a string representation in the default C locale to an integer. That means to successfully convert the value in your example, your byte array must contain the string "0x06", which consists of 4 bytes.
To convert a single byte to an int, just extract it:
int i = value[0];
Type promotion will widen the char to an int

SQLite dropping zeros

I'm using google wrapper (sqlite3pp) to insert a char array that contain some zeros. The problem that is the SQLite is dropping the zero and the next elements after it.
char array[11] = {1,2,3,4,5,0,3,4,0,6,7};
sqlite3pp::command cmd(db, "INSERT INTO messages (id, payload) VALUES (?, ?)");
cmd.bind(1,index);
cmd.bind(2,&array[0],sizeof(array));
This code only insert: 1 2 3 4 5
The payload type is varchar.
Any idea?
sqlite3pp defines, among others, these two overloads for the bind() function:
int bind(int idx, char const* value, bool fstatic = true);
int bind(int idx, void const* value, int n, bool fstatic = true);
You want to use the second one with explicit length, but the first one is selected, while sizeof(array), evaluated to be 11, is truncated to bool value true and passed as fstatic instead of size. The wrapper then thinks the value is a plain NUL-terminated string and thus stores just the part till the first zero.
You can help the compiler to select the right version e.g. by providing the implicit parameter like so:
cmd.bind(2, &array[0], sizeof(array), true);
(Or false when the array will be deallocated before the query is done executing.)
Additionally, there can be problems with reading the rows as well - e.g. the default sqlite3pp getter for std::string won't work with binary zeroes and the content needs to be retrieved explicitly like this:
payload.assign(static_cast<const char*>(i->get<const void*>(2)), i->column_bytes(2));

Conversion with Pointsers in C

I need to implement but I am not sure how can I as I am completely new into this. A function called get_values that has the prototype:
void get_values(unsigned int value, unsigned int *p_lsb, unsigned int *p_msb,
unsigned int *p_combined)
The function computes the least significant byte and the most significant byte of the value
parameter. In addition, both values are combined. For this problem:
a. You may not use any loop constructs.
b. You may not use the multiplication operator (* or *=).
c. Your code must work for unsigned integers of any size (4 bytes, 8 bytes, etc.).
d. To combine the values, append the least significant byte to the most significant one.
e. Your implementation should be efficient.
The following driver (and associated output) provides an example of using the function you are
expected to write. Notice that in this example an unsigned int is 4 bytes, but your function
needs to work with an unsigned int of any size.
Driver
int main() {
unsigned int value = 0xabcdfaec, lsb, msb, combined;
get_values(value, &lsb, &msb, &combined);
printf("Value: %x, lsb: %x, msb: %x, combined: %x\n", value, lsb, msb, combined);
return 0;
}
Output
Value: abcdfaec, lsb: ec, msb: ab, combined: abec
I think you want to look into bitwise and and bit shifting operators. The last piece of the puzzle might be the sizeof() operator if the question is asking that the code should work with platforms with different sized int types.

Storing a char in a char pointer

I have a global variable that is a *char. My main function header reads as int main(int argc, char* argv[argc]){...}. These two lines of code have to remain the way they are. The first argument of my main function is a number of type *char, that I convert to a char using atoi(...);. I am basically changing the ASCII value to its corresponding character. Now I want to store this local variable character I have into the global variable that is a char pointer. I know the problem is related to allocation of memory, but I am not sure how to go about this.
My code:
char* delim;
int main(int argc, char* argv[argc])
{
char delimCharacter;
if (isdigit(*(argv[3])) == 0) delim = argv[3]; //you can pass in a character or its ascii value
else { //if the argument is a number, then the ascii value is taken
delimCharacter = atoi((argv[3]));
printf("%s\t,%c,\n", argv[3], delimCharacter);
//sprintf( delim, "%c", delimCharacter ); // a failed attempt to do this
*delim = delimCharacter;
//strncpy(delim, delimCharacter, 1); // another failed attempt to do this
}
//printf("%s\n",delim);
This yields a seg fault.
You need to verify you have got (at least) 3 arguments before you start using them.
if (argc < 4)
{
printf("Need 3 args");
exit(1);
}
Then you need to allocate some memory to put the character in.
delim = malloc(2);
// TODO: Should check the result of malloc before using it.
*delim = delimCharacter;
delim[1] = 0; // Need to NULL terminate char*
You're dereferencing an uninitialized pointer. delim never gets initialized when it goes into the else block.
char delim[] = ","; // anything really, as long as as it's one character string
...
delim[0] = delimCharacter;
In addition to your memory issue, I think you are confused about what atoi does. It parses a string representation of a number and returns the equivalent int value, e.g. "10000" => 10,000. I think that you think it will give you the ASCII value of a character, e.g. "A" =>65.
Since you have a char *, and you are (I think) assuming that it contains a single character, you could simply do this:
delimCharacter = *(argv[3]);
However, there really seems to be no need to use the intermediate step of assigning this value to a char variable at all. If the end goal is to have delim point to the char that is the delimiter, then it seems this is all you need to do:
delim = argv[3];
Not only does this remove unnecessary code, but it means you would no longer need to allocate additional memory for delim to point to.
I would also declare delim as a const char * since I assume there is no reason to change it.

Resources