This question already has answers here:
Encode/Decode URLs in C++ [closed]
(19 answers)
Closed 4 months ago.
I am trying to process instructions from a web page, but special characters are encoded.
Here is an example:
command=setkey
page=1
key=D
value=N%6eE8qiCZ\r
this is received as
"command=setkey&page=1&key=D&value=N%256eE8qiCZ%5Cr"
"%" is converted to "%25", "\" becomes "%5C".
Is there easy way to return "N%256eE8qiCZ%5Cr" to "N%6eE8qiCZ\r" ?
Here is one solution I found with hint "urlEncode" (thanks lorro):
//decode received web form string
unsigned char h2int(char c)
{
if (c >= '0' && c <='9'){
return((unsigned char)c - '0');
}
if (c >= 'a' && c <='f'){
return((unsigned char)c - 'a' + 10);
}
if (c >= 'A' && c <='F'){
return((unsigned char)c - 'A' + 10);
}
return(0);
}
String urldecode(String str)
{
String encodedString="";
char c;
char code0;
char code1;
for (int i =0; i < str.length(); i++){
c=str.charAt(i);
if (c == '+'){
encodedString+=' ';
}else if (c == '%') {
i++;
code0=str.charAt(i);
i++;
code1=str.charAt(i);
c = (h2int(code0) << 4) | h2int(code1);
encodedString+=c;
} else{
encodedString+=c;
}
yield();
}
return encodedString;
}
Called like this:
String webresponse = "command=setkey&page=1&key=D&value=N%256eE8qiCZ%5Cr";
String result = urldecode(webresponse);
Serial.println(result);
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
Suppose I have a piece of code like
unsigned char *tag = NULL;
tag = (unsigned char *)malloc(8);
memset(tag, 0, 8);
memcpy(tag, (const char *)"50C59390",8);
I have to send it as length 4. So I am trying to convert it in 4 byte hex like 0x50C59390.
unsigned char * buffer = (unsigned char *)calloc(4, sizeof(char));
int index,j = 0;
for(index = 0 ; index < 8; index++)
{
buffer[j] = (tag[index] & 0x0F) | (tag[++index]>>4 & 0xF0);
printf("%02X", buffer[j]);
j++;
}
I am trying above code. but its not working as required.
You can't just copy ascii characters as hex values. You need to convert them.
Something like:
unsigned char convert(unsigned char ch)
{
if (ch >= '0' && ch <= '9')
{
return ch -'0';
}
if (ch >= 'a' && ch <= 'f')
{
return ch -'a' + 10;
}
if (ch >= 'A' && ch <= 'F')
{
return ch -'A' + 10;
}
return 0; // or some error handling
}
and use it like:
for(index = 0 ; index < 8; index = index + 2)
{
buffer[j] = convert(tag[index]) << 4;
buffer[j] += convert(tag[index+1]);
printf("%02X", buffer[j]);
j++;
}
See it online here: https://ideone.com/e2FPCT
From your question I am not exactly sure whether you try to convert to or from a string. However, if you have C++11 available, you can use std::stoi() and std::to_string() for easy conversion:
int hex_value = std::stoi(tag, nullptr, 16)
Note how the third argument of std::stoi() denominates the base (in this case 16 for hexadecimal).
I have the IR code in form of hexadecimal stored in string (without 0x prefix) which has to be transmited via sendNEC() from IRremote.h. What's the easiest way to convert string in form like "FFFFFF" to 0xFFFFFF?
if you get every char of the string and converted to a numeric hex value then you will need only to calculate the power of every digit, that conversion returns a number which can be represented in several ways (hex in your case)
std::string w("ABCD");
unsigned int res = 0;
for (int i = w.length()-1; i >= 0; i--)
{
unsigned int t = parseCharToHex(w[w.length() - 1 - i]);
std::cout << std::hex << t << std::endl;
res += pow(16, i) * t;
}
std::cout << "res: " << std::dec << res << std::endl;
the function parseCharToHex:
unsigned int parseCharToHex(const char charX)
{
if ('0' <= charX && charX <= '9') return charX - '0';
if ('a' <= charX && charX <= 'f') return 10 + charX - 'a';
if ('A' <= charX && charX <= 'F') return 10 + charX - 'A';
}
pow function is required from the arduino doc here
This is a dirty code which works well under severe limitations:
no error checking needed
string format is exactly known and is F...F'\0'
it is assumed that codes for '0' to '9' and 'A' to 'F' are subsequent and growing
The trick is to use character codes for calculations
_
char * in;
uint64_t out=0;
int counter;
for(counter=0; in[counter]; counter++){
if(in[counter]>='0'&&in[counter]<='9') {
out*=0x10;
out+=in[counter]-'0';
} else {
//assuming that character is from 'A' to 'F'
out*=0x10;
out+=in[counter]-'A'+10;
}
}
void crazyCaps(string& str){
size_t i = 0;
size_t strLength = str.length(); // this line violates the rule as mentioned in the title
while (i < strLength) {
if (i % 2 == 0) {
if (str[i] >= 'A' && str[i] <= 'Z') // this line violates the rule as mentioned in the title
str[i] += 32;
}
else {
if (str[i] >= 'a' && str[i] <= 'z')
str[i] -= 32;
}
i++;
}
My input: "Hey!! THERE!"
My output: "hEy!! tHeRe!"
I'm able to convert the characters to uppercase and lowercase without using toUpper() and toLower() function. However, I'm still using length() and []. So my question is how do you convert "Hey!! THERE!" to "hEy!! tHeRe!" without using length() or [] and toUpper() or toLower().
str[i] is equivalent to *(str + i). Internally, compiler converts str[i] to *(str + i).
This implies, str[i] = *(str + i) = i[str]
Also, a string always ends with \0 (null character). Using these two facts, you can construct something like this:
int i = 0
while(*(str + i) != '\0') {
//change the case by adding or subtracting 32
i++;
}
EDIT: By string, I mean regular C string and not std::string
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
I wanted to write a C++ program that checks whether a string contains every letter in the alphabet from a to z.
bool allLetters(string s) {
vector<bool> checked(255, false);
for (int i=0; i < int(s.size()); ++i)
checked[s[i]] = true;
for (int i='a'; i <= 'z'; ++i)
if (!checked[i])
return false;
return true;
}
Assuming a character set where the letters are contiguous from a to z:
bool contains_all_letters(const char * p)
{
unsigned seen = 0;
while (*p)
{
unsigned c = *p++ - 'a';
if (c < 26)
{
seen |= (1 << c);
}
}
return seen == (1 << 26) - 1;
}
You can always do this (in ASCII)
bool has_alphabet(std::string const &s)
{
std::bitset<26> alphabet;
for (char c : s) {
if (c >= 'A' && c <= 'Z')
alphabet.set(c - 'A');
else if (c >= 'a' && c <= 'z')
alphabet.set(c - 'a');
}
return 26 == alphabet.count();
}
You need to include the bitset header and no matter whether caps are before or after lower letters or they have other symbols between them, this will work
I have a hex value in a char pointer (for example 'F3'), and I would like to convert it to byte, because I want it to put in an array. I know that there are many solutions, but they are not what I wanted.
Thanks in advance!
EDIT:
Okay, maybe I have not written everything.
What I have now:
char aChar[5];
itoa (j, aChar, 16);
j is now 3, and I just want it in byte. Atoi, scanf doesn't help, those are the different solutions.
Since you've tagged this C++ and not C, I'm not going to use any C functions (except assert() to demonstrate the behaviour, edge conditions, et cetera). Here's a sample file. Let's call it hex2byte.cpp:
#include <sstream>
#include <cassert>
unsigned char hex2byte(const char* hex)
{
unsigned short byte = 0;
std::istringstream iss(hex);
iss >> std::hex >> byte;
return byte % 0x100;
}
int main()
{
const char* hex = "F3";
assert(hex2byte(hex) == 243);
assert(hex2byte("") == 0);
assert(hex2byte("00") == 0);
assert(hex2byte("A") == 10);
assert(hex2byte("0A") == 10);
assert(hex2byte("FF") == 255);
assert(hex2byte("EEFF") == 255);
assert(hex2byte("GG") == 00);
assert(hex2byte("a") == 10);
assert(hex2byte("0a") == 10);
assert(hex2byte("f3") == 243);
assert(hex2byte("ff") == 255);
assert(hex2byte("eeff") == 255);
assert(hex2byte("gg") == 00);
}
Make it:
% make hex2byte
g++ -Wall -Wextra -Wshadow -pedantic -Weffc++ -Werror hex2byte.cpp -o hex2byte
Run it:
% ./hex2byte
No assertions. Add error handling to taste (such as checking for when hex == NULL, et cetera).
A byte is usually simply an unsigned char
myArray[n] = (unsigned char)*p;
Or do you mean that you have a string representation of an hex value?
Given a char * with "F3":
char *hexstr = "F3";
Then you can do this:
unsigned char byteval =
(((hexstr[0] >= 'A' && hexstr[0] <= 'Z') ? (10 + hexstr[0] - 'A') :
(hexstr[0] >= 'a' && hexstr[0] <= 'z') ? (10 + hexstr[0] - 'a') :
(hexstr[0] >= '0' && hexstr[0] <= '9') ? (hexstr[0] - '0') : 0) << 4) |
((hexstr[1] >= 'A' && hexstr[1] <= 'Z') ? (10 + hexstr[1] - 'A') :
(hexstr[1] >= 'a' && hexstr[1] <= 'z') ? (10 + hexstr[1] - 'a') :
(hexstr[1] >= '0' && hexstr[1] <= '9') ? (hexstr[1] - '0') : 0);
I'm sorry for its ugliness; I'm sure it can be improved.
You can turn this into a function:
inline unsigned char hextobyte(const char *s) {
return
(((s[0] >= 'A' && s[0] <= 'Z') ? (10 + s[0] - 'A') :
(s[0] >= 'a' && s[0] <= 'z') ? (10 + s[0] - 'a') :
(s[0] >= '0' && s[0] <= '9') ? (s[0] - '0') : 0) << 4) |
((s[1] >= 'A' && s[1] <= 'Z') ? (10 + s[1] - 'A') :
(s[1] >= 'a' && s[1] <= 'z') ? (10 + s[1] - 'a') :
(s[1] >= '0' && s[1] <= '9') ? (s[1] - '0') : 0);
}
I can think of at least five ways:
using sscanf with %x
using strtol with the correct base
using istringstream (though you'll have to down cast from unsigned short to unsigned char)
boost::spirit
hand rolled loop to parse character-by-character
None of the ways you listed would work. But your question still isn't really clear, you have a char which somehow you converted to hex using itoa and now you want to convert to a byte!?! what's wrong with a cast? e.g. unsigned char byte = static_cast<unsigned char>(charvalue);