I want to know how to get number to string without standard C or C++ functions, for example:
char str[20];
int num = 1234;
// How to convert that number to string (str)?
Thanks.
Using C (not C++)
Assuming you're preallocating your buffer for str as in your question:
char *itostr(int num, char *str) {
int len = 1;
long tmp = num;
int sign = num < 0;
if (sign) {
str[0] = '-';
tmp = -tmp;
}
while (num/=10) ++len;
str[len+sign] = 0;
while (len--) {
str[len+sign] = '0'+tmp%10;
tmp /= 10;
}
return str;
}
To get the lowest digit, use num % 10. To convert a digit to a character, add '0'. To remove the lowest digit after you've handled it, divide by 10: num /= 10;. Repeat until done.
Convert it char by char, e.g. the last char of the string is '4', the previous one is '3' and so on. Use math to determine the chars, it might be easier to create "4321" string and then rotate it.
An "after accepted answer" that works for all int including INT_MIN.
static char *intTostring_helper(int i, char *s) {
if (i < -9) {
s = intTostring_helper(i/10, s);
}
*s++ = (-(i%10)) + '0' ;
return s;
}
char *intTostring(int i, char *dest) {
char *s = dest;
if (i < 0) { // If non 2s compliment, change to some IsSignBitSet() function.
*s++ = '-';
}
else {
i = -i;
}
s = intTostring_helper(i, s);
*s = '\0';
return dest;
}
A simplistic way to do this is to leave a lot of leading zeros. I like it because it uses only basic code, and doesn't require any dynamic memory allocation. It should consequently also be very fast:
char * convertToString(int num, str) {
int val;
val = num / 1000000000; str[0] = '0' + val; num -= val * 1000000000;
val = num / 100000000; str[1] = '0' + val; num -= val * 100000000;
val = num / 10000000; str[2] = '0' + val; num -= val * 10000000;
val = num / 1000000; str[3] = '0' + val; num -= val * 1000000;
val = num / 100000; str[4] = '0' + val; num -= val * 100000;
val = num / 10000; str[5] = '0' + val; num -= val * 10000;
val = num / 1000; str[6] = '0' + val; num -= val * 1000;
val = num / 100; str[7] = '0' + val; num -= val * 100;
val = num / 10; str[8] = '0' + val; num -= val * 10;
val = num; str[9] = '0' + val;
str[10] = '\0';
return str;
}
Of course, there are tons of tweaks you could do to this - modifying the way the destination array gets created is possible, as is adding a boolean that says to trim leading 0s. And we could make this much more efficient using a loop. Here's in improved method:
void convertToStringFancier(int num, char * returnArrayAtLeast11Bytes, bool trimLeadingZeros) {
int divisor = 1000000000;
char str[11];
int i;
int val;
for (i = 0; i < 10; ++i, divisor /= 10) {
val = num / divisor;
str[i] = '0' + val;
num -= val * divisor;
}
str[i] = '\0';
// Note that everything below here is just to get rid of the leading zeros and copy the array, which is longer than the actual number conversion.
char * ptr = str;
if (trimLeadingZeros) {
while (*ptr == '0') { ++ptr; }
if (*ptr == '\0') { // handle special case when the input was 0
*(--ptr) = '0';
}
for (i = 0; i < 10 && *ptr != '\0'; ++i) {
while (*ptr != '\0') {
returnArrayAtLeast11Bytes[i] = *ptr;
}
returnArrayAtLeast11Bytes[i] = '\0';
}
Related
I want to write a function to reverse one of two parts of number :
Input is: num = 1234567; part = 2
and output is: 1234765
So here is part that can be only 1 or 2
Now I know how to get part 1
int firstPartOfInt(int num) {
int ret = num;
digits = 1, halfDig = 10;
while (num > 9) {
ret = ret / 10;
digits++;
}
halfDigits = digits / 2;
for (int i = 1; i < halfDigits; i++) {
halfDigits *= 10;
}
ret = num;
while (num > halfDigits) {
ret = ret / 10;
}
return ret;
}
But I don't know how to get part 2 and reverse the number. If you post code here please do not use vector<> and other C++ feature not compatible with C
One way is to calculate the total number of digits in the number and then calculate a new number extracting digits from the original number in a certain order, complexity O(number-of-digits):
#include <stdio.h>
#include <stdlib.h>
unsigned reverse_decimal_half(unsigned n, unsigned half) {
unsigned char digits[sizeof(n) * 3];
unsigned digits10 = 0;
do digits[digits10++] = n % 10;
while(n /= 10);
unsigned result = 0;
switch(half) {
case 1:
for(unsigned digit = digits10 / 2; digit < digits10; ++digit)
result = result * 10 + digits[digit];
for(unsigned digit = digits10 / 2; digit--;)
result = result * 10 + digits[digit];
break;
case 2:
for(unsigned digit = digits10; digit-- > digits10 / 2;)
result = result * 10 + digits[digit];
for(unsigned digit = 0; digit < digits10 / 2; ++digit)
result = result * 10 + digits[digit];
break;
default:
abort();
}
return result;
}
int main() {
printf("%u %u %u\n", 0, 1, reverse_decimal_half(0, 1));
printf("%u %u %u\n", 12345678, 1, reverse_decimal_half(12345678, 1));
printf("%u %u %u\n", 12345678, 2, reverse_decimal_half(12345678, 2));
printf("%u %u %u\n", 123456789, 1, reverse_decimal_half(123456789, 1));
printf("%u %u %u\n", 123456789, 2, reverse_decimal_half(123456789, 2));
}
Outputs:
0 1 0
12345678 1 43215678
12345678 2 12348765
123456789 1 543216789
123456789 2 123459876
if understand this question well you need to reverse half of the decimal number. If the number has odd number of digits I assume that the first part is longer (for example 12345 - the first part is 123 the second 45). Because reverse is artihmetic the reverse the part 1 of 52001234 is 521234.
https://godbolt.org/z/frXvCM
(some numbers when reversed may wrap around - it is not checked)
int getndigits(unsigned number)
{
int ndigits = 0;
while(number)
{
ndigits++;
number /= 10;
}
return ndigits;
}
unsigned reverse(unsigned val, int ndigits)
{
unsigned left = 1, right = 1, result = 0;
while(--ndigits) left *= 10;
while(left)
{
result += (val / left) * right;
right *= 10;
val = val % left;
left /= 10;
}
return result;
}
unsigned reversehalf(unsigned val, int part)
{
int ndigits = getndigits(val);
unsigned parts[2], digits[2], left = 1;
if(ndigits < 3 || (ndigits == 3 && part == 2))
{
return val;
}
digits[0] = digits[1] = ndigits / 2;
if(digits[0] + digits[1] < ndigits) digits[0]++;
for(int dig = 0; dig < digits[1]; dig++) left *= 10;
parts[0] = val / left;
parts[1] = val % left;
parts[part - 1] = reverse(parts[part - 1], digits[part - 1]);
val = parts[0] * left + parts[1];
return val;
}
int main()
{
for(int number = 0; number < 40; number++)
{
unsigned num = rand();
printf("%u \tpart:%d\trev:%u\n", num,(number & 1) + 1,reversehalf(num, (number & 1) + 1));
}
}
My five cents.:)
#include <iostream>
int reverse_part_of_integer( int value, bool first_part = false )
{
const int Base = 10;
size_t n = 0;
int tmp = value;
do
{
++n;
} while ( tmp /= Base );
if ( first_part && n - n / 2 > 1 || !first_part && n / 2 > 1 )
{
n = n / 2;
int divider = 1;
while ( n-- ) divider *= Base;
int first_half = value / divider;
int second_half = value % divider;
int tmp = first_part ? first_half : second_half;
value = 0;
do
{
value = Base * value + tmp % Base;
} while ( tmp /= Base );
value = first_part ? value * divider + second_half
: first_half * divider +value;
}
return value;
}
int main()
{
int value = -123456789;
std::cout << "initial value: "
<< value << '\n';
std::cout << "First part reversed: "
<< reverse_part_of_integer( value, true ) << '\n';
std::cout << "Second part reversed: "
<< reverse_part_of_integer( value ) << '\n';
}
The program output is
initial value: -123456789
First part reversed: -543216789
Second part reversed: -123459876
Just for fun, a solution that counts only half the number of digits before reversing:
constexpr int base{10};
constexpr int partial_reverse(int number, int part)
{
// Split the number finding its "halfway"
int multiplier = base;
int abs_number = number < 0 ? -number : number;
int parts[2] = {0, abs_number};
while (parts[1] >= multiplier)
{
multiplier *= base;
parts[1] /= base;
}
multiplier /= base;
parts[0] = abs_number % multiplier;
// Now reverse only one of the two parts
int tmp = parts[part];
parts[part] = 0;
while (tmp)
{
parts[part] = parts[part] * base + tmp % base;
tmp /= base;
}
// Then rebuild the number
int reversed = parts[0] + multiplier * parts[1];
return number < 0 ? -reversed : reversed;
}
int main()
{
static_assert(partial_reverse(123, 0) == 123);
static_assert(partial_reverse(-123, 1) == -213);
static_assert(partial_reverse(1000, 0) == 1000);
static_assert(partial_reverse(1009, 1) == 109);
static_assert(partial_reverse(123456, 0) == 123654);
static_assert(partial_reverse(1234567, 0) == 1234765);
static_assert(partial_reverse(-1234567, 1) == -4321567);
}
I'm new to C++ and our teacher asked us to get a function that does the above title. So far I've got a function that converts a string to an integer, but I have no idea about how to modify it to make it work if the numbers in the string would represent a float.
int convert(char str[], int size) {
int number = 0;
for (int i = 0; i < size; ++i) {
number += (str[i] - 48)*pow(10, (size - i - 1));
}
return number;
}
If I run:
char myString[] = "12345";
convert(myString, 5);
I get:
12345
But if I run:
char myString[] = "123.45";
convert(myString, 5);
I get:
122845
How could I modify my program to work with floats too? I know convert function is meant to return an int so, should I use two more functions?
I was thinking about one that determinates if the string is inteded to be converted to an integer or a string, and the other that'll actually convert the string to a float.
Here is the function for doing so...
template<class T, class S>
T convert_string_to_number(S s)
{
auto result = T(0.l);
if (s.back() == L'F' || s.back() == L'f')
s = s.substr(0u, s.size() - 1u);
auto temp = s;
auto should_add = false;
if (!std::is_floating_point<T>::value)
{
should_add = temp.at(temp.find_first_of(L'.') + 1) >= '5';
temp.erase(temp.begin() + temp.find_first_of(L'.'), temp.end());
}
else if (temp.find_first_of(L'.') != S::npos)
temp.erase(temp.begin() + temp.find_first_of(L'.'));
for (int i = temp.size() - 1u; i >= 0; --i)
if (temp[i] >= L'0' && temp[i] <= L'9')
result += T(std::powl(10.l, temp.size() - i - 1.l) * (temp[i] - L'0'));
else
throw std::invalid_argument("Invalid numerical string!");
if (s.find(L'-') != S::npos)
result = -T(std::fabs(result));
if (s.find(L'.') != S::npos && std::is_floating_point<T>::value)
result /= T(std::powl(10.l, s.size() - s.find(L'.') - 1.l));
return std::is_floating_point<T>::value ? T(result) : T(result + T(should_add));
}
Just use it like you typically would...
auto some_number = convert_string_to_number<float>(myString);...
For the floating point part of the assignment: what about regular expressions? It is also kind of built-in functionality, but general purpose, not designed for your particular task, so I hope your teacher will be fine with this idea.
You can use the following regex: [+-]?([0-9]*[.])?[0-9]+ (I got it from this answer) to detect if provided string is a floating point number. Then you can modify the expression a little bit to capture the +/- signs and parts before/after the dot separator. Once you extract these features the task should be relatively simple.
Also please change your method signature to: float convert(const std::string& str).
Try this :
int convert(char str[], int size) {
int number = 0;
for (int i = 0; i < size; ++i) {
number += (str[i] - 48)*pow(10, (size - i - 1));
}
return number;
}
int pow10(int radix)
{
int r = 1;
for (int i = 0; i < radix; i++)
r *= 10;
return r;
}
float convert2float(char str[], int size) { //size =6
// convert to string_without_decimal
char str_without_decimal[10];
int c = 0;
for (int i = 0; i < size; i++)
{
if (str[i] >= 48 && str[i] <= 57) {
str_without_decimal[c] = str[i];
c++;
}
}
str_without_decimal[c] = '\0'; //str_without_decimal = "12345"
//adjust size if dot present or not. If no dot present => size = c
size = (size != c ?) size - 1 : size; //size = 5 = 6-1 since dot is present
//convert to decimal
int decimal = convert(str_without_decimal, size); //decimal = 12345
//get divisor
int i;
for (i = size; i >= 0; i--) {
if (str[i] == '.') break;
}
int divisor = pow10(size - i); //divisor = 10;
return (float)decimal/(float) divisor; // result = 12345 /10
}
int main()
{
char str[] = "1234.5";
float f = convert2float(str, 6);
cout << f << endl;
return 0;
}
I'm posting this although much has already been posted about this question. I didn't want to post as an answer since it's not working. The answer to this post (Finding the rank of the Given string in list of all possible permutations with Duplicates) did not work for me.
So I tried this (which is a compilation of code I've plagiarized and my attempt to deal with repetitions). The non-repeating cases work fine. BOOKKEEPER generates 83863, not the desired 10743.
(The factorial function and letter counter array 'repeats' are working correctly. I didn't post to save space.)
while (pointer != length)
{
if (sortedWordChars[pointer] != wordArray[pointer])
{
// Swap the current character with the one after that
char temp = sortedWordChars[pointer];
sortedWordChars[pointer] = sortedWordChars[next];
sortedWordChars[next] = temp;
next++;
//For each position check how many characters left have duplicates,
//and use the logic that if you need to permute n things and if 'a' things
//are similar the number of permutations is n!/a!
int ct = repeats[(sortedWordChars[pointer]-64)];
// Increment the rank
if (ct>1) { //repeats?
System.out.println("repeating " + (sortedWordChars[pointer]-64));
//In case of repetition of any character use: (n-1)!/(times)!
//e.g. if there is 1 character which is repeating twice,
//x* (n-1)!/2!
int dividend = getFactorialIter(length - pointer - 1);
int divisor = getFactorialIter(ct);
int quo = dividend/divisor;
rank += quo;
} else {
rank += getFactorialIter(length - pointer - 1);
}
} else
{
pointer++;
next = pointer + 1;
}
}
Note: this answer is for 1-based rankings, as specified implicitly by example. Here's some Python that works at least for the two examples provided. The key fact is that suffixperms * ctr[y] // ctr[x] is the number of permutations whose first letter is y of the length-(i + 1) suffix of perm.
from collections import Counter
def rankperm(perm):
rank = 1
suffixperms = 1
ctr = Counter()
for i in range(len(perm)):
x = perm[((len(perm) - 1) - i)]
ctr[x] += 1
for y in ctr:
if (y < x):
rank += ((suffixperms * ctr[y]) // ctr[x])
suffixperms = ((suffixperms * (i + 1)) // ctr[x])
return rank
print(rankperm('QUESTION'))
print(rankperm('BOOKKEEPER'))
Java version:
public static long rankPerm(String perm) {
long rank = 1;
long suffixPermCount = 1;
java.util.Map<Character, Integer> charCounts =
new java.util.HashMap<Character, Integer>();
for (int i = perm.length() - 1; i > -1; i--) {
char x = perm.charAt(i);
int xCount = charCounts.containsKey(x) ? charCounts.get(x) + 1 : 1;
charCounts.put(x, xCount);
for (java.util.Map.Entry<Character, Integer> e : charCounts.entrySet()) {
if (e.getKey() < x) {
rank += suffixPermCount * e.getValue() / xCount;
}
}
suffixPermCount *= perm.length() - i;
suffixPermCount /= xCount;
}
return rank;
}
Unranking permutations:
from collections import Counter
def unrankperm(letters, rank):
ctr = Counter()
permcount = 1
for i in range(len(letters)):
x = letters[i]
ctr[x] += 1
permcount = (permcount * (i + 1)) // ctr[x]
# ctr is the histogram of letters
# permcount is the number of distinct perms of letters
perm = []
for i in range(len(letters)):
for x in sorted(ctr.keys()):
# suffixcount is the number of distinct perms that begin with x
suffixcount = permcount * ctr[x] // (len(letters) - i)
if rank <= suffixcount:
perm.append(x)
permcount = suffixcount
ctr[x] -= 1
if ctr[x] == 0:
del ctr[x]
break
rank -= suffixcount
return ''.join(perm)
If we use mathematics, the complexity will come down and will be able to find rank quicker. This will be particularly helpful for large strings.
(more details can be found here)
Suggest to programmatically define the approach shown here (screenshot attached below) given below)
I would say David post (the accepted answer) is super cool. However, I would like to improve it further for speed. The inner loop is trying to find inverse order pairs, and for each such inverse order, it tries to contribute to the increment of rank. If we use an ordered map structure (binary search tree or BST) in that place, we can simply do an inorder traversal from the first node (left-bottom) until it reaches the current character in the BST, rather than traversal for the whole map(BST). In C++, std::map is a perfect one for BST implementation. The following code reduces the necessary iterations in loop and removes the if check.
long long rankofword(string s)
{
long long rank = 1;
long long suffixPermCount = 1;
map<char, int> m;
int size = s.size();
for (int i = size - 1; i > -1; i--)
{
char x = s[i];
m[x]++;
for (auto it = m.begin(); it != m.find(x); it++)
rank += suffixPermCount * it->second / m[x];
suffixPermCount *= (size - i);
suffixPermCount /= m[x];
}
return rank;
}
#Dvaid Einstat, this was really helpful. It took me a WHILE to figure out what you were doing as I am still learning my first language(C#). I translated it into C# and figured that I'd give that solution as well since this listing helped me so much!
Thanks!
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Text.RegularExpressions;
namespace CsharpVersion
{
class Program
{
//Takes in the word and checks to make sure that the word
//is between 1 and 25 charaters inclusive and only
//letters are used
static string readWord(string prompt, int high)
{
Regex rgx = new Regex("^[a-zA-Z]+$");
string word;
string result;
do
{
Console.WriteLine(prompt);
word = Console.ReadLine();
} while (word == "" | word.Length > high | rgx.IsMatch(word) == false);
result = word.ToUpper();
return result;
}
//Creates a sorted dictionary containing distinct letters
//initialized with 0 frequency
static SortedDictionary<char,int> Counter(string word)
{
char[] wordArray = word.ToCharArray();
int len = word.Length;
SortedDictionary<char,int> count = new SortedDictionary<char,int>();
foreach(char c in word)
{
if(count.ContainsKey(c))
{
}
else
{
count.Add(c, 0);
}
}
return count;
}
//Creates a factorial function
static int Factorial(int n)
{
if (n <= 1)
{
return 1;
}
else
{
return n * Factorial(n - 1);
}
}
//Ranks the word input if there are no repeated charaters
//in the word
static Int64 rankWord(char[] wordArray)
{
int n = wordArray.Length;
Int64 rank = 1;
//loops through the array of letters
for (int i = 0; i < n-1; i++)
{
int x=0;
//loops all letters after i and compares them for factorial calculation
for (int j = i+1; j<n ; j++)
{
if (wordArray[i] > wordArray[j])
{
x++;
}
}
rank = rank + x * (Factorial(n - i - 1));
}
return rank;
}
//Ranks the word input if there are repeated charaters
//in the word
static Int64 rankPerm(String word)
{
Int64 rank = 1;
Int64 suffixPermCount = 1;
SortedDictionary<char, int> counter = Counter(word);
for (int i = word.Length - 1; i > -1; i--)
{
char x = Convert.ToChar(word.Substring(i,1));
int xCount;
if(counter[x] != 0)
{
xCount = counter[x] + 1;
}
else
{
xCount = 1;
}
counter[x] = xCount;
foreach (KeyValuePair<char,int> e in counter)
{
if (e.Key < x)
{
rank += suffixPermCount * e.Value / xCount;
}
}
suffixPermCount *= word.Length - i;
suffixPermCount /= xCount;
}
return rank;
}
static void Main(string[] args)
{
Console.WriteLine("Type Exit to end the program.");
string prompt = "Please enter a word using only letters:";
const int MAX_VALUE = 25;
Int64 rank = new Int64();
string theWord;
do
{
theWord = readWord(prompt, MAX_VALUE);
char[] wordLetters = theWord.ToCharArray();
Array.Sort(wordLetters);
bool duplicate = false;
for(int i = 0; i< theWord.Length - 1; i++)
{
if(wordLetters[i] < wordLetters[i+1])
{
duplicate = true;
}
}
if(duplicate)
{
SortedDictionary<char, int> counter = Counter(theWord);
rank = rankPerm(theWord);
Console.WriteLine("\n" + theWord + " = " + rank);
}
else
{
char[] letters = theWord.ToCharArray();
rank = rankWord(letters);
Console.WriteLine("\n" + theWord + " = " + rank);
}
} while (theWord != "EXIT");
Console.WriteLine("\nPress enter to escape..");
Console.Read();
}
}
}
If there are k distinct characters, the i^th character repeated n_i times, then the total number of permutations is given by
(n_1 + n_2 + ..+ n_k)!
------------------------------------------------
n_1! n_2! ... n_k!
which is the multinomial coefficient.
Now we can use this to compute the rank of a given permutation as follows:
Consider the first character(leftmost). say it was the r^th one in the sorted order of characters.
Now if you replace the first character by any of the 1,2,3,..,(r-1)^th character and consider all possible permutations, each of these permutations will precede the given permutation. The total number can be computed using the above formula.
Once you compute the number for the first character, fix the first character, and repeat the same with the second character and so on.
Here's the C++ implementation to your question
#include<iostream>
using namespace std;
int fact(int f) {
if (f == 0) return 1;
if (f <= 2) return f;
return (f * fact(f - 1));
}
int solve(string s,int n) {
int ans = 1;
int arr[26] = {0};
int len = n - 1;
for (int i = 0; i < n; i++) {
s[i] = toupper(s[i]);
arr[s[i] - 'A']++;
}
for(int i = 0; i < n; i++) {
int temp = 0;
int x = 1;
char c = s[i];
for(int j = 0; j < c - 'A'; j++) temp += arr[j];
for (int j = 0; j < 26; j++) x = (x * fact(arr[j]));
arr[c - 'A']--;
ans = ans + (temp * ((fact(len)) / x));
len--;
}
return ans;
}
int main() {
int i,n;
string s;
cin>>s;
n=s.size();
cout << solve(s,n);
return 0;
}
Java version of unrank for a String:
public static String unrankperm(String letters, int rank) {
Map<Character, Integer> charCounts = new java.util.HashMap<>();
int permcount = 1;
for(int i = 0; i < letters.length(); i++) {
char x = letters.charAt(i);
int xCount = charCounts.containsKey(x) ? charCounts.get(x) + 1 : 1;
charCounts.put(x, xCount);
permcount = (permcount * (i + 1)) / xCount;
}
// charCounts is the histogram of letters
// permcount is the number of distinct perms of letters
StringBuilder perm = new StringBuilder();
for(int i = 0; i < letters.length(); i++) {
List<Character> sorted = new ArrayList<>(charCounts.keySet());
Collections.sort(sorted);
for(Character x : sorted) {
// suffixcount is the number of distinct perms that begin with x
Integer frequency = charCounts.get(x);
int suffixcount = permcount * frequency / (letters.length() - i);
if (rank <= suffixcount) {
perm.append(x);
permcount = suffixcount;
if(frequency == 1) {
charCounts.remove(x);
} else {
charCounts.put(x, frequency - 1);
}
break;
}
rank -= suffixcount;
}
}
return perm.toString();
}
See also n-th-permutation-algorithm-for-use-in-brute-force-bin-packaging-parallelization.
im getting strange issues, when casting char to int in Arduino IDE. The method should check an array of char for "IP". If there is one number ore more numbers after the chars, they should be converted to int.
int getPin(char dataFromAndroid[ ]){
for(int i = 0; i < 10; i++) {
if(dataFromAndroid[i] == 'I') {
if(dataFromAndroid[i + 1] == 'P') { // Digitaler Pin
char c1 = dataFromAndroid[i + 2];
char c2 = dataFromAndroid[i + 3];
int digPinNr;
char str;
str+=c1;
if(c2 != '0') {
str+=c2;
}
digPinNr = str -'0';
Serial.print("c1:");
Serial.print(c1);
Serial.print("c2:");
Serial.print(c2);
Serial.print("str");
Serial.print(str);
Serial.print("Pin:");
Serial.println(digPinNr);
return digPinNr;
}
}
}
}
Sometimes the program gets 5 instead of 7 (see the outup). Can some help me please ?!
Empfangen:W204IP5 c1:5c2: str5Pin:5
Empfangen:W106IP5 c1:5c2: str7Pin:7
I have found a solution now for the problem. I have just changed the char array to a string, and the converting is done like : digPinNr = str.toInt();
Here's the full solution:
int getPin(char dataFromAndroid[ ]){
for(int i = 0; i < 10; i++) {
if(dataFromAndroid[i] == 'I') {
if(dataFromAndroid[i + 1] == 'P') { // Digitaler Pin
char c1 = dataFromAndroid[i + 2];
char c2 = dataFromAndroid[i + 3];
int digPinNr;
String str="";
str+=c1;
if(c2 != '0') {
str+=c2;
}
digPinNr = str.toInt();
Serial.print("c1:");
Serial.print(c1);
Serial.print("c2:");
Serial.print(c2);
Serial.print("str");
Serial.print(str);
Serial.print("Pin:");
Serial.println(digPinNr);
return digPinNr;
}
}
}
}
I have been trying to carry out a conversion from CString that contains Hex string to a Byte array and have been
unsuccessful so far. I have looked on forums and none of them seem to help so far. Is there a function with just a few
lines of code to do this conversion?
My code:
BYTE abyData[8]; // BYTE = unsigned char
CString sByte = "0E00000000000400";
Expecting:
abyData[0] = 0x0E;
abyData[6] = 0x04; // etc.
You can simply gobble up two characters at a time:
unsigned int value(char c)
{
if (c >= '0' && c <= '9') { return c - '0'; }
if (c >= 'A' && c <= 'F') { return c - 'A' + 10; }
if (c >= 'a' && c <= 'f') { return c - 'a' + 10; }
return -1; // Error!
}
for (unsigned int i = 0; i != 8; ++i)
{
abyData[i] = value(sByte[2 * i]) * 16 + value(sByte[2 * i + 1]);
}
Of course 8 should be the size of your array, and you should ensure that the string is precisely twice as long. A checking version of this would make sure that each character is a valid hex digit and signal some type of error if that isn't the case.
How about something like this:
for (int i = 0; i < sizeof(abyData) && (i * 2) < sByte.GetLength(); i++)
{
char ch1 = sByte[i * 2];
char ch2 = sByte[i * 2 + 1];
int value = 0;
if (std::isdigit(ch1))
value += ch1 - '0';
else
value += (std::tolower(ch1) - 'a') + 10;
// That was the four high bits, so make them that
value <<= 4;
if (std::isdigit(ch2))
value += ch1 - '0';
else
value += (std::tolower(ch1) - 'a') + 10;
abyData[i] = value;
}
Note: The code above is not tested.
You could:
#include <stdint.h>
#include <sstream>
#include <iostream>
int main() {
unsigned char result[8];
std::stringstream ss;
ss << std::hex << "0E00000000000400";
ss >> *( reinterpret_cast<uint64_t *>( result ) );
std::cout << static_cast<int>( result[1] ) << std::endl;
}
however take care of memory management issues!!!
Plus the result is in the reverse order as you would expect, so:
result[0] = 0x00
result[1] = 0x04
...
result[7] = 0x0E