I am doing a small parser that should convert a string into an Hexadecimal value,I am using arduino as platform but I am getting stack with it.
My string is data = "5449"
where each element is an char, so I would like to translate it to a HEX value like dataHex = 0x54 0x59, and finally those values should be translate to ASCII as dataAscii= TI
How can I do this?
I was thinking of splitting it into an char array with dataCharArray = 54 49 and later converting those values to the chars T and I, but I am not sure whether or not that is the best way.
Thanks in advance,
regards!
I don't have arduino installed in my PC right now, so let's hope the following works:
char nibble2c(char c)
{
if ((c>='0') && (c<='9'))
return c-'0' ;
if ((c>='A') && (c<='F'))
return c+10-'A' ;
if ((c>='a') && (c<='a'))
return c+10-'a' ;
return -1 ;
}
char hex2c(char c1, char c2)
{
if(nibble2c(c2) >= 0)
return nibble2c(c1)*16+nibble2c(c2) ;
return nibble2c(c1) ;
}
String hex2str(char *data)
{
String result = "" ;
for (int i=0 ; nibble2c(data[i])>=0 ; i++)
{
result += hex2c(data[i],data[i+1]) ;
if(nibble2c(data[i+1])>=0)
i++ ;
}
return result;
}
Related
Hi I tried to write my own version of memmove and I find the following code resulting in a segmentation fault. It would be great if someone could help me figure out why this behavior would occur!
However, when I use something like:
char source[20] = "Hello, this is Piranava", the code works fine!
void *memmoveLocal(void *dest, const void *src, unsigned int n)
{
char *destL = dest;
const char *srcL = src;
int i = 0;
if(dest == NULL || src == NULL)
{
return NULL;
}
else
{
// if dest comes before source, even if there's an overlap, we should move forward
// because if there's an overlap (when dest < src) and we move backward, we'd overwrite the overlapping bytes in src
if(destL < srcL)
{
printf("Forward\n");
while(i < n)
{
destL[i] = srcL[i];
i++;
}
}
else // in all other cases (even if there's overlap or no overlap, we can move backward)
{
printf("Backward\n");
i = n - 1;
while(i >= 0)
{
destL[i] = srcL[i];
i--;
}
}
}
return dest;
}
void main()
{
char *source = "Hello, this is ABC";
char *destination = malloc(strlen(source)+1);
memmoveLocal(source+5, source, 5);
printf("Source: %s \nDestination: %s, size: %d\n", source, destination, strlen(destination));
}
However, if I replace
char *source = "Hello, this is ABC";
with
char source[20] = "Hello, this is ABC";
, it works fine!
memmoveLocal(source+5, source, 5);
You are trying to overwrite a string literal, which is not writable.
Did you intend to memmoveLocal(destination, source+5, 5) instead?
char source[20] = "Hello, this is ABC";
That turns source from a string literal into a char[] array initialized with a string literal. The array is writable, so your program no longer crashes.
I don't know why output is printed in ascii code instead of integer value ,what wrong with my code ?
import 'dart:io';
void main() {
int n = 0;
print("input: ");
do {
n = stdin.readByteSync();
} while (n>1000 || n<0);
if (n % 4 == 0) {
print("output: ");
print(n);
n++;
} else {
print("output: ");
n--;
print(n);
}
}
Paste your code so it can be easier to help you.
I could have given you a fixed source code if you would have provided.
Instead, I'll try to explain:
Your stdin will be provided as a string, you read it as bytes so 5 will be come 35 as hex.
When you print it, my guess is that it will automatically be converted to a decimal value (53, and the output shows 52 because 53 % 4 = 1 and then to decrease with n-- before printing it so it become 52).
Those numbers like you said of the ASCII Table.
In order to fix it, make sure you have the string representation of the input (stdin). Then convert the value to integer: "2".toInt()
Edit:
I could have easily find the complete solution,
You need to get the stdin as a string first: readLineSync and convert it to int:
n = int.parse(stdin.readLineSync());
Note: Code not tested, but it's pretty straight forward.
Get the value as String using stdin.readLineSync() then parse it to int like below:
import 'dart:io';
void main() {
int n = 0;
print("input: ");
do {
n = int.parse(stdin.readLineSync());
} while (n>1000 || n<0);
if (n % 4 == 0) {
print("output: ");
print(n);
n++;
} else {
print("output: ");
n--;
print(n);
}
}
Trying to insert some data from CSV to Firebird table in Qt. DB is in ASCII. When inserting some strings with non-ascii symbols get error:
Cannot transliterate character between character sets
Setting QSqlDatabase::setConnectOptions("ISC_DPB_LC_CTYPE=UTF8;") and converting column to UTF8 (CHARACTER SET UTF8) does not help - same error. Trying to suppress unicode characters with no luck as well:
QTextCodec *codec = QTextCodec::codecForName("latin1");
QByteArray encodedString = codec->fromUnicode(str);
str = QString(encodedString);
QString::toLatin1 () does not suppress characters as well. What solution could be here?
This piece of code should do what you need:
QString h("Honkäüö?ß#asdfe");
unsigned char * data = (unsigned char*)h.data();
QString result;
for(int i = 0; h.size()*2; i+=2) {
if(data[i] > 127) {
result.append("?");
} else {
result.append(QChar(data[i]));
}
}
Here is another, more robust, version:
QString h("Honkäüö?ß#asdfe");
QString result;
for(int i = 0; i < h.size(); ++i) {
QChar qc = h.at(i);
unsigned char c = *(unsigned char*)(&qc);
if(c >= 127) {
result.append("?");
} else if (QChar(c).isPrint()) {
result.append(QChar(c));
}
}
QString result is just used to show what is extracted. You could copy the data[i] in a char array or a append to a QByteArray.
result is Honk?????????#asdfe
This works well for 16bit characters. 32bit characters result in additional '?'s or other characters.
This code extract any unicode (emojis) from qstring (16 or 32 bits) and toReturn contain only characters from ASCII table ( unicode value less than 256 )
QString cleanQString(QString toClean) {
QString toReturn="";
for(int i=0;i<toClean.size();i++){
if(toClean.at(i).unicode()<256){
toReturn.append(toClean.at(i));
}
}
return toReturn;
}
I have a String variable and I want to extract the three substrings separeted by ; to three string variables.
String application_command = "{10,12; 4,5; 2}";
I cannot use substring method because this string can be like any of the following or similar patterns also.
String application_command = "{10,12,13,9,1; 4,5; 2}"
String application_command = "{7; 1,2,14; 1}"
The only thing that is common in these patterns is there are three sections separated by ;.
Any insight is much appreciated.
Thank you
I think you need a split-string-into-string-array function with a custom separator character.
There are already several sources on the web and at stackoverflow (e.g. Split String into String array).
// https://stackoverflow.com/questions/9072320/split-string-into-string-array
String getValue(String data, char separator, int index)
{
int found = 0;
int strIndex[] = {0, -1};
int maxIndex = data.length()-1;
for(int i=0; i<=maxIndex && found<=index; i++){
if(data.charAt(i)==separator || i==maxIndex){
found++;
strIndex[0] = strIndex[1]+1;
strIndex[1] = (i == maxIndex) ? i+1 : i;
}
}
return found>index ? data.substring(strIndex[0], strIndex[1]) : "";
}
You can use this function as follows (with ";" as separator):
String part01 = getValue(application_command,';',0);
String part02 = getValue(application_command,';',1);
String part03 = getValue(application_command,';',2);
EDIT: correct single quotes and add semicolons in the example.
The new SafeString Arduino library (available from the library manager) provides a number of tokenizing/substring methods without the heap fragmentation of the String class
See https://www.forward.com.au/pfod/ArduinoProgramming/SafeString/index.html
for a detailed tutorial
In this case your can use
#include "SafeString.h"
void setup() {
Serial.begin(9600);
createSafeString(appCmd, 50); // large enought for the largest cmd
createSafeString(token1, 20);
createSafeString(token2, 20);
createSafeString(token3, 20);
appCmd = "{10,12,13,9,1; 4,5; 2}";
size_t nextIdx = 1; //step over leading {
nextIdx = appCmd.stoken(token1, nextIdx, ";}");
nextIdx++; //step over delimiter
nextIdx = appCmd.stoken(token2, nextIdx, ";}");
nextIdx++; //step over delimiter
nextIdx = appCmd.stoken(token3, nextIdx, ";}");
nextIdx++; //step over delimiter
// can trim tokens if needed e.g. token1.trim()
Serial.println(token1);
Serial.println(token2);
Serial.println(token3);
}
void loop() {
}
Also look at pfodParser which parses these types of messages { } for use by pfodApp.
Do not forget to call delete[] to free the memory after the use of the array, that said here is my solution:
String* split(String& v, char delimiter, int& length) {
length = 1;
bool found = false;
// Figure out how many itens the array should have
for (int i = 0; i < v.length(); i++) {
if (v[i] == delimiter) {
length++;
found = true;
}
}
// If the delimiter is found than create the array
// and split the String
if (found) {
// Create array
String* valores = new String[length];
// Split the string into array
int i = 0;
for (int itemIndex = 0; itemIndex < length; itemIndex++) {
for (; i < v.length(); i++) {
if (v[i] == delimiter) {
i++;
break;
}
valores[itemIndex] += v[i];
}
}
// Done, return the values
return valores;
}
// No delimiter found
return nullptr;
}
Here is an example of how to use:
void loop() {
String test = "1,2,3,4,5";
int qtde;
String* t = split(test, ',', qtde);
for (int i = 0; i < qtde; i++) {
Serial.println(t[i]);
delay(1000);
}
delete[] t;
}
I'm trying to parse a QString character by character with a while loop, but I can't figure out how to parse an individual character to char type. Here's my code, I know it's not optimal:
QString temp = (QString)t[0];
int i = 1;
while (t[i] != " ");
{
temp.append(t[i]);
i += 1;
}
I've seen the casting with toLocal8bit function, but whatever I try I just cannot adapt it to my code.
Qt Creator shows this error:
error: conversion from 'const char [2]' to 'QChar' is ambiguous
in line with the while function call
You can use C++ 11 range based for loop
for (auto chr : text)
{
if (!chr.isDigit()) // for exmpl.
return false;
}
Why don't you try that :
QString test = "test";
for(int i = 0; i< test.length(); i++)
{
if (test.at(i) != " ")
test.at(i).toLatin1();
}