convert chars form char array to integer in C - c

from a char array like {T,E,S,T,1,2,3,E,N,D}, I need to get an integer from certain positions. Following with the example, I would like to get an integer from positions 4, 5, 6. So, myInt = 123.
I tried following method but haven't got desired integer.
char receivedata[bytes];
concatVars = concatenate(atoi(receivedata[6] - '0', receivedata[7] - '0');
concatVars = concatenate(concatVars, receivedata[8] - '0');
unsigned concatenate(unsigned x, unsigned y) {
unsigned pow = 10;
while(y >= pow)
pow *= 10;
return x * pow + y;
}

This should do what you want:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int arrToInt(char* arr, int len) {
int toRet = 0;
for(int i = 0; i < len; i++) {
if (isdigit(arr[i])) {
toRet *= 10;
toRet += arr[i] - '0';
}
}
return toRet;
}
int main(int argc, char* argv[]) {
char test[] = {'T', 'E', 'S', 'T', '1', '2', '3', 'E', 'N', 'D'};
int asInt = arrToInt(test, 10);
printf("Got: %d\n", asInt);
}
Output (compiling with -std=c99 to make the int i = 0 inline declaration work):
Got: 123

One way of doing this would be:
int myInt = (((int)myArray[4] - 48) * 100) + (((int)myArray[5] - 48) * 10) + (((int)myArray[6] - 48) * 1);
Note that 48 is the ASCII position of the number 0, thus by converting a character to int and then subtracting 48 you get the numeric value.

Standard library's string-to-integer conversion functions (e.g. strtol) stop automatically once they reach a non-numeric character in the input character sequence. So all you have to do is tell such function where to start. In your case this will perform the conversion
const char *s = "TEST123END";
long myLong = strtol(s + 4, NULL, 10);
int myInt = myLong;
You just have to handle possible errors.

#include <stdio.h>
#include <string.h>
int main(){
char *str = "TEST123END";
char s4_6[4] = {0};
int n;
memcpy(s4_6, str+4, 3);
//if(1==sscanf(str, "%*[^0-9]%d", &n))
//if(1==sscanf(str+4, "%d", &n))
if(1==sscanf(s4_6, "%d", &n))
printf("%d\n", n);
return 0;
}

Here is one way:
int myInt = atoi(&myArray[4]);
Adding to ced-b's response, I prefer this syntax:
myArray[5] - '0'
That is, make it clear you are subtracting off the '0'.
Note: I used specific offset into the string because the OP asked for: "I need to get an integer from certain positions", which I interpreted as specific offset into the string. Based on the accepted answer I seem to have interpreted that wrong.

Related

XOR two hexadecimal strings(unmasking) in C

I wanted to unmask a hex string using the following algorithm in C
j = i MOD 4 transformed-octet-i = original-octet-i XOR masking-key-octet-j
#include<stdlib.h>
#include<string.h>
int main()
{
char masked[]="951bfdcdc113ebca921fe9dc";
char masking_key[]="e17e8eb9";
char *unmasked;
int length=strlen(masked);
unmasked=malloc(sizeof(char)*(length+1));
int i=0;
for(i=0;i<length;i++)
{
unmasked[i]=masked[i]^masking_key[i%4];
}
printf("%s\n",unmasked);
return 0;
}
The output I am getting is \UT instead of 74657374206d657373616765. It would be really helpful if someone could help me fix the error here.
You need to convert from string format to raw integers before doing the XOR, then convert back before printing it as a string. Otherwise you'll XOR the symbol values, not the raw values.
You can convert the whole string in one go with strtol(data, 0, 16). But one of the common details that makes programmers different from the code monkeys is the ability to code trivial string-integer conversions without the help of library functions. So here is a a simplified code doing just that - be aware of the complete lack of error handling, as this is just quick & dirty code:
#include <stdio.h>
#include <stdlib.h>
char hexlify (char nibble)
{
return "0123456789abcdef"[nibble];
}
char unhexlify (char ch)
{
if(ch>='0' && ch<='9')
return ch - '0';
if(ch>='a' && ch<='f')
return ch - 'a' + 0xA;
return 0;
}
int main (void)
{
char masked[]="951bfdcdc113ebca921fe9dc";
char masking_key[]="e17e8eb9";
char *unmasked;
size_t length = sizeof masked - 1;
unmasked = malloc(length + 1);
for(size_t i=0;i<length;i++)
{
char op1 = unhexlify(masked[i]);
char op2 = unhexlify(masking_key[i%4]);
unmasked[i]= hexlify(op1 ^ op2);
}
unmasked[length]='\0';
printf("%s\n",unmasked);
free(unmasked);
return 0;
}
Output:
74651cb3206d0ab4736108a2
What you're doing here is not xoring the hexadecimal bytes, but xoring the characters representing them.
While the ideal process would be (0x95 ^ 0xe1) + (0xbf ^ 7e) + ..., what you're doing is xoring the ascii values of each character, meaning ('9' ^ 'b') + ('5' ^ '1') + ....
What you need to do is first transform the hexadecimal string to the bytes themselves (bytes.fromhex("951bfdcdc113ebca921fe9dc") in python), and only then XOR them. The way I would do that is with sscanf("%2x", ...).
For example:
#include <stdio.h>
int main()
{
unsigned char a = 0;
scanf("%2hhx", &a);
}

Converting int to char in C

Right now I am trying to convert an int to a char in C programming. After doing research, I found that I should be able to do it like this:
int value = 10;
char result = (char) value;
What I would like is for this to return 'A' (and for 0-9 to return '0'-'9') but this returns a new line character I think.
My whole function looks like this:
char int2char (int radix, int value) {
if (value < 0 || value >= radix) {
return '?';
}
char result = (char) value;
return result;
}
to convert int to char you do not have to do anything
char x;
int y;
/* do something */
x = y;
only one int to char value as the printable (usually ASCII) digit like in your example:
const char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
int inttochar(int val, int base)
{
return digits[val % base];
}
if you want to convert to the string (char *) then you need to use any of the stansdard functions like sprintf, itoa, ltoa, utoa, ultoa .... or write one yourself:
char *reverse(char *str);
const char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
char *convert(int number, char *buff, int base)
{
char *result = (buff == NULL || base > strlen(digits) || base < 2) ? NULL : buff;
char sign = 0;
if (number < 0)
{
sign = '-';
}
if (result != NULL)
{
do
{
*buff++ = digits[abs(number % (base ))];
number /= base;
} while (number);
if(sign) *buff++ = sign;
if (!*result) *buff++ = '0';
*buff = 0;
reverse(result);
}
return result;
}
A portable way of doing this would be to define a
const char* foo = "0123456789ABC...";
where ... are the rest of the characters that you want to consider.
Then and foo[value] will evaluate to a particular char. For example foo[0] will be '0', and foo[10] will be 'A'.
If you assume a particular encoding (such as the common but by no means ubiquitous ASCII) then your code is not strictly portable.
Characters use an encoding (typically ASCII) to map numbers to a particular character. The codes for the characters '0' to '9' are consecutive, so for values less than 10 you add the value to the character constant '0'. For values 10 or more, you add the value minus 10 to the character constant 'A':
char result;
if (value >= 10) {
result = 'A' + value - 10;
} else {
result = '0' + value;
}
Converting Int to Char
I take it that OP wants more that just a 1 digit conversion as radix was supplied.
To convert an int into a string, (not just 1 char) there is the sprintf(buf, "%d", value) approach.
To do so to any radix, string management becomes an issue as well as dealing the corner case of INT_MIN
The following C99 solution returns a char* whose lifetime is valid to the end of the block. It does so by providing a compound literal via the macro.
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
// Maximum buffer size needed
#define ITOA_BASE_N (sizeof(unsigned)*CHAR_BIT + 2)
char *itoa_base(char *s, int x, int base) {
s += ITOA_BASE_N - 1;
*s = '\0';
if (base >= 2 && base <= 36) {
int x0 = x;
do {
*(--s) = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[abs(x % base)];
x /= base;
} while (x);
if (x0 < 0) {
*(--s) = '-';
}
}
return s;
}
#define TO_BASE(x,b) itoa_base((char [ITOA_BASE_N]){0} , (x), (b))
Sample usage and tests
void test(int x) {
printf("base10:% 11d base2:%35s base36:%7s ", x, TO_BASE(x, 2), TO_BASE(x, 36));
printf("%ld\n", strtol(TO_BASE(x, 36), NULL, 36));
}
int main(void) {
test(0);
test(-1);
test(42);
test(INT_MAX);
test(-INT_MAX);
test(INT_MIN);
}
Output
base10: 0 base2: 0 base36: 0 0
base10: -1 base2: -1 base36: -1 -1
base10: 42 base2: 101010 base36: 16 42
base10: 2147483647 base2: 1111111111111111111111111111111 base36: ZIK0ZJ 2147483647
base10:-2147483647 base2: -1111111111111111111111111111111 base36:-ZIK0ZJ -2147483647
base10:-2147483648 base2: -10000000000000000000000000000000 base36:-ZIK0ZK -2147483648
Ref How to use compound literals to fprintf() multiple formatted numbers with arbitrary bases?
Check out the ascii table
The values stored in a char are interpreted as the characters corresponding to that table. The value of 10 is a newline
So characters in C are based on ASCII (or UTF-8 which is backwards-compatible with ascii codes). This means that under the hood, "A" is actually the number "65" (except in binary rather than decimal). All a "char" is in C is an integer with enough bytes to represent every ASCII character. If you want to convert an int to a char, you'll need to instruct the computer to interpret the bytes of an int as ASCII values - and it's been a while since I've done C, but I believe the compiler will complain since char holds fewer bytes than int. This means we need a function, as you've written. Thus,
if(value < 10) return '0'+value;
return 'A'+value-10;
will be what you want to return from your function. Keep your bounds checks with "radix" as you've done, imho that is good practice in C.
1. Converting int to char by type casting
Source File charConvertByCasting.c
#include <stdio.h>
int main(){
int i = 66; // ~~Type Casting Syntax~~
printf("%c", (char) i); // (type_name) expression
return 0;
}
Executable charConvertByCasting.exe command line output:
C:\Users\boqsc\Desktop\tcc>tcc -run charconvert.c
B
Additional resources:
https://www.tutorialspoint.com/cprogramming/c_type_casting.htm
https://www.tutorialspoint.com/cprogramming/c_data_types.htm
2. Convert int to char by assignment
Source File charConvertByAssignment.c
#include <stdio.h>
int main(){
int i = 66;
char c = i;
printf("%c", c);
return 0;
}
Executable charConvertByAssignment.exe command line output:
C:\Users\boqsc\Desktop\tcc>tcc -run charconvert.c
B
You can do
char a;
a = '0' + 5;
You will get character representation of that number.
Borrowing the idea from the existing answers, i.e. making use of array index.
Here is a "just works" simple demo for "integer to char[]" conversion in base 10, without any of <stdio.h>'s printf family interfaces.
Test:
$ cc -o testint2str testint2str.c && ./testint2str
Result: 234789
Code:
#include <stdio.h>
#include <string.h>
static char digits[] = "0123456789";
void int2str (char *buf, size_t sz, int num);
/*
Test:
cc -o testint2str testint2str.c && ./testint2str
*/
int
main ()
{
int num = 234789;
char buf[1024] = { 0 };
int2str (buf, sizeof buf, num);
printf ("Result: %s\n", buf);
}
void
int2str (char *buf, size_t sz, int num)
{
/*
Convert integer type to char*, in base-10 form.
*/
char *bufp = buf;
int i = 0;
// NOTE-1
void __reverse (char *__buf, int __start, int __end)
{
char __bufclone[__end - __start];
int i = 0;
int __nchars = sizeof __bufclone;
for (i = 0; i < __nchars; i++)
{
__bufclone[i] = __buf[__end - 1 - i];
}
memmove (__buf, __bufclone, __nchars);
}
while (num > 0)
{
bufp[i++] = digits[num % 10]; // NOTE-2
num /= 10;
}
__reverse (buf, 0, i);
// NOTE-3
bufp[i] = '\0';
}
// NOTE-1:
// "Nested function" is GNU's C Extension. Put it outside if not
// compiled by GCC.
// NOTE-2:
// 10 can be replaced by any radix, like 16 for hexidecimal outputs.
//
// NOTE-3:
// Make sure inserting trailing "null-terminator" after all things
// done.
NOTE-1:
"Nested function" is GNU's C Extension. Put it outside if not
compiled by GCC.
NOTE-2:
10 can be replaced by any radix, like 16 for hexidecimal outputs.
NOTE-3:
Make sure inserting trailing "null-terminator" after all things
done.

Data type confusion, need integer from char array

Once again I have the wrong data type. This is an arduino project.
I have a char array. The last 9 characters are rgb, I get them as triplets. So 000255000.
I need to pass those to a function but as integers, like 0, 255, 0. I'm ok if 000 turns into 0, but I need 045 to turn into 45.
I've tried to cast them, like:
blue = (int)message[11];
blue += (int)message[12];
blue += (int)message[13];
That did not work. I could however cast them to strings,which I did, then I tried: Yes, I know this was not a great idea, but it was worth a shot.
char tempBlue[4];
blue.toCharArray(tempGreen, sizeof(tempGreen));
iBlue = atoi(tempGreen);
That also did not work.
I'm lost as to how to do this. I have no idea how ( if you can ) concatenate integers or I would have tried that.
EDIT------
Am I asking the wrong question. Should I be doing this the reverse way around. Concatenate first then to integer? I have them as characters to begin with.
To convert each character to its respective int do the following
int first = message[11] - '0';
int second= message[12] - '0';
int third = message[13] - '0';
To see why this works, you can check here: Why does subtracting '0' in C result in the number that the char is representing?
To concatenate ints, you could use this function
unsigned concatenate(unsigned x, unsigned y) {
unsigned pow = 10;
while(y >= pow)
pow *= 10;
return x * pow + y;
}
I did not write this function, it was written by #TBohne originally here
I'd go with:
char *partMessage = (char*)malloc(4);
partMessage[3] = '\0';
strncpy(partMessage, message + 11, 3);
result = (int)strtol(partMessage, NULL, 10);
free(partMessage);
you could try something like this
#include <stdio.h>
int main()
{
// example
char message[] = { "000255000" };
int r=0, g=0, b=0;
// make sure right number of values have been read
if ( sscanf(message, "%03d%03d%03d", &r, &g, &b ) == 3 )
{
printf( "R:%d, G:%d, B:%d\n", r,g,b );
}
else
{
fprintf(stderr, "failed to parse\n");
}
}
sscanf will skip any white space so even a string like message[] = " 000 255 000 "; will work.
Just do the conversion manually:
int convert_digits(char *cp, int count) {
int result = 0;
for (int i = 0; i < count; i += 1) {
result *= 10;
result += (cp[i] - '0');
}
return result;
}
char *input = "000045255";
int main(int ac, char *av[]) {
printf("r=%d g=%d, b=%d\n",
convert_digits(cp, 3),
convert_digits(cp+3, 3),
convert_digits(cp+6, 3));
}
Convert string to a number and then numerically peal off 3 digits at a time.
const char *s = "000255000";
char *endptr;
unsigned long num = strtoul(s, &endptr, 10);
// add error checking on errno, num, endptr) here if desired.
blue = num%1000;
num /= 1000;
green = num%1000;
num /= 1000;
red = num%1000;
// Could add check to insure r,g,b <= 255.

Algorithm to parse an int from a string in one pass

I'm trying to write a function that parses an integer from a string representation.
My problem is that I don't know how to do this with one pass through the string. If I knew ahead of time that the input contained only characters in the range '0', '1', ..., '9' and that the string was of length n, I could of course calculate
character_1 * 10^(n-1) + character_2 * 10^(n-2) + .... + character_n * 10^0
but I want to deal with the general scenario as I've presented it.
I'm not looking for a library function, but an algorithm to achieve this in "pure C".
Here's the code I started from:
int parse_int (const char * c1, const char * c2, int * i)
{
/*
[c1, c2]: Range of characters in the string
i: Integer whose string representnation will be converted
Returns the number of characters parsed.
Exs. "2342kjsd32" returns 4, since the first 4 characters were parsed.
"hhsd3b23" returns 0
*/
int n = 0;
*i = 0;
while (c1!= c2)
{
char c = *c1;
if (c >= '0' && c <= '9')
{
}
}
return n;
}
Just as some of the comments and answers suggested, maybe a bit clearer: You have to "shift" the result "left" by multiplying it by 10 in every iteration before the addition of the new digit.
Indeed, this should remind us of Horner's method. As you have recognized, the result can be written like a polynomial:
result = c1 * 10^(n-1) + c2 * 10^(n-2) + ... + cn * 10^0
And this equation can be rewritten as this:
result = cn + 10*(... + 10*(c2 + 10*c1))
Which is the form this approach is based on. From the formula you can already see, that you don't need to know the power of 10 the first digit is to be multiplied by, directly from the start.
Here's an example:
#include <stdio.h>
int parse_int(const char * begin, const char * end, int * result) {
int d = 0;
for (*result = 0; begin != end; d++, begin++) {
int digit = *begin - '0';
if (digit >= 0 && digit < 10) {
*result *= 10;
*result += digit;
}
else break;
}
return d;
}
int main() {
char arr[] = "2342kjsd32";
int result;
int ndigits = parse_int(arr, arr+sizeof(arr), &result);
printf("%d digits parsed, got: %d\n", ndigits, result);
return 0;
}
The same can be achieved using sscanf(), for everyone that is fine with using the C standard library (can also handle negative numbers):
#include <stdio.h>
int main() {
char arr[] = "2342kjsd32";
int result, ndigits;
sscanf(arr, "%d%n", &result, &ndigits);
printf("%d digits parsed, got: %d\n", ndigits, result);
return 0;
}
The output is (both implementations):
$ gcc test.c && ./a.out
4 digits parsed, got: 2342
I think this is good solution to count parse character
int parse(char *str)
{
int k = 0;
while(*str)
{
if((*str >= '0') & (*str <= '9'))
break;
str++;
k++;
}
return k;
}
Here's a working version:
#include <stdio.h>
int parse_int (const char * c1, const char * c2, int * i)
{
/*
[c1, c2]: Range of characters in the string
i: Integer whose string representnation will be converted
Returns the number of characters parsed.
Exs. "2342kjsd32" returns 4, since the first 4 characters were parsed.
"hhsd3b23" returns 0
*/
int n = 0;
*i = 0;
for (; c1 != c2; c1++)
{
char c = *c1;
if (c >= '0' && c <= '9')
{
++n;
*i = *i * 10 + c - '0';
}
else
{
break;
}
}
return n;
}
int main()
{
int i;
char const* c1 = "2342kjsd32";
int n = parse_int(c1, c1+10, &i);
printf("n: %d, i: %d\n", n, i);
return 0;
}
Output:
n: 4, i: 2342

how to add char type integer in c

This is the sample code of my program, in which i've to add two string type integer (ex: "23568" and "23674"). So, i was trying with single char addition.
char first ='2';
char second ='1';
i was trying like this..
i=((int)first)+((int)second);
printf("%d",i);
and i'm getting output 99, because, it's adding the ASCII value of both. Anyone please suggest me, what should be the approach to add the char type number in C.
Since your example has two single chars being added together, you can be confident knowing two things
The total will never be more than 18.
You can avoid any conversions via library calls entirely. The standard requires that '0' through '9' be sequential (in fact it is the only character sequence that is mandated by the standard).
Therefore;
char a = '2';
char b = '3';
int i = (int)(a-'0') + (int)(b-'0');
will always work. Even in EBCDIC (and if you don't know what that is, consider yourself lucky).
If your intention is to actually add two numbers of multiple digits each currently in string form ("12345", "54321") then strtol() is your best alternative.
i=(first-'0')+(second-'0');
No need for casting char to int.
if you want to add the number reprensations of the characters, I would use "(first - '0') + (second - '0');"
The question seemed interesting, I though it would be easier than it is, adding "String numbers" is a little bit tricky (even more with the ugly approach I used).
This code will add two strings of any length, they doesn't need to be of the same length as the adding begins from the back. Your provide both strings, a buffer of enough length and you ensure the strings only contains digits:
#include <stdio.h>
#include <string.h>
char * add_string_numbers(char * first, char * second, char * dest, int dest_len)
{
char * res = dest + dest_len - 1;
*res = 0;
if ( ! *first && ! *second )
{
puts("Those numbers are less than nothing");
return 0;
}
int first_len = strlen(first);
int second_len = strlen(second);
if ( ((first_len+2) > dest_len) || ((second_len+2) > dest_len) )
{
puts("Possibly not enough space on destination buffer");
return 0;
}
char *first_back = first+first_len;
char *second_back = second+second_len;
char sum;
char carry = 0;
while ( (first_back > first) || (second_back > second) )
{
sum = ((first_back > first) ? *(--first_back) : '0')
+ ((second_back > second) ? *(--second_back) : '0')
+ carry - '0';
carry = sum > '9';
if ( carry )
{
sum -= 10;
}
if ( sum > '9' )
{
sum = '0';
carry = 1;
}
*(--res) = sum;
}
if ( carry )
{
*(--res) = '1';
}
return res;
}
int main(int argc, char** argv)
{
char * a = "555555555555555555555555555555555555555555555555555555555555555";
char * b = "9999999999999666666666666666666666666666666666666666666666666666666666666666";
char r[100] = {0};
char * res = add_string_numbers(a,b,r,sizeof(r));
printf("%s + %s = %s", a, b, res);
return (0);
}
Well... you are already adding char types, as you noted that's 4910 and 5010 which should give you 9910
If you're asking how to add the reperserented value of two characters i.e. '1' + '2' == 3 you can subtract the base '0':
printf("%d",('2'-'0') + ('1'-'0'));
This gives 3 as an int because:
'0' = ASCII 48<sub>10</sub>
'1' = ASCII 49<sub>10</sub>
'2' = ASCII 50<sub>10</sub>
So you're doing:
printf("%d",(50-48) + (49-48));
If you want to do a longer number, you can use atoi(), but you have to use strings at that point:
int * first = "123";
int * second = "100";
printf("%d", atoi(first) + atoi(second));
>> 223
In fact, you don't need to even type cast the chars for doing this with a single char:
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char* argv[]) {
char f1 = '9';
char f2 = '7';
int v = (f1 - '0') - (f2 - '0');
printf("%d\n", v);
return 0;
}
Will print 2
But beware, it won't work for hexadecimal chars
This will add the corresponding characters of any two given number strings using the ASCII codes.
Given two number strings 'a' and 'b', we can compute the sum of a and b using their ASCII values without type casting or trying to convert them to int data type before addition.
Let
char *a = "13784", *b = "94325";
int max_len, carry = 0, i, j; /*( Note: max_len is the length of the longest string)*/
char sum, *result;
Adding corresponding digits in a and b.
sum = a[i] + (b[i] - 48) + carry; /*(Because 0 starts from 48 in ASCII) */
if (sum >= 57)
result[max_len - j] = sum - 10;
carry = 1;
else
result[max_len - j] = sum;
carry = 0;
/* where (0 < i <= max_len and 0 <= j <= max_len) */
NOTE:
The above solution only takes account of single character addition starting from the right and moving leftward.
if you want to scan number by number, simple atoi function will do it
you can use
atoi() function
#include <stdio.h>
#include <stdlib.h>
void main(){
char f[] = {"1"};
char s[] = {"2"};
int i, k;
i = atoi(f);
k = atoi(s);
printf("%d", i + k);
getchar();
}
Hope I answered you question

Resources