I'm trying to convert a string of binary characters to an integer value.
For example: "100101101001" I would split it into four segments using a for loop then store it in array[4]. However whenever I use the function atoi(), I encounter a problem where it does not convert the character string properly if the string starts with "0".
An example would be "1001" = 1001, but if it is 0110 it would be converted to 110, also with 0001 it would be come only 1.
Here is the code that I made:
for(i = 0; i < strlen(store); i++)
{
bits[counter] = store [i];
counter++;
if(counter == 4)
{
sscanf(bits, "%d", &testing);
printf("%d\n", testing);
counter = 0;
}
}
The atoi() function only converts decimal numbers, in base 10.
You can use strtoul() to convert binary numbers, by specifying a base argument of 2. There is no need to "split" the string, and leading zeroes won't matter of course (as they shouldn't, 000102 is equal to 102):
const char *binary = "00010";
unsigned long value;
char *endp = NULL;
value = strtoul(binary, &endp, 2);
if(endp != NULL && *endp == '\0')
printf("converted binary '%s' to integer %lu\n", binary, value);
atoi() convert from char array to int and not to binary
you can use the following function
int chartobin(char *s, unsigned int *x) {
int len = strlen(s), bit;
*x = 0;
if(len>32 || len<1) return -1;
while(*s) {
bit = (*s++ - '0');
if((bit&(~1U))!=0) return -1;
if (bit) *x += (1<<(len-1));
len--;
}
return 0;
}
Tested and it works
Related
I tried to write a function to convert a string to an int:
int convert(char *str, int *n){
int i;
if (str == NULL) return 0;
for (i = 0; i < strlen(str); i++)
if ((isdigit(*(str+i))) == 0) return 0;
*n = *str;
return 1;
}
So what's wrong with my code?
*n = *str means:
Set the 4 bytes of memory that n points to, to the 1 byte of memory that str points to. This is perfectly fine but it's probably not your intention.
Why are you trying to convert a char* to an int* in the first place? If you literally just need to do a conversion and make the compiler happy, you can just do int *foo = (int*)bar where bar is the char*.
Sorry, I don't have the reputation to make this a comment.
The function definitely does not perform as intended.
Here are some issues:
you should include <ctype.h> for isdigit() to be properly defined.
isdigit(*(str+i)) has undefined behavior if str contains negative char values. You should cast the argument:
isdigit((unsigned char)str[i])
the function returns 0 if there is any non digit character in the string. What about "-1" and "+2"? atoi and strtol are more lenient with non digit characters, they skip initial white space, process an optional sign and subsequent digits, stopping at the first non digit.
the test for (i = 0; i < strlen(str); i++) is very inefficient: strlen may be invoked for each character in the string, with O(N2) time complexity. Use this instead:
for (i = 0; str[i] != '\0'; i++)
*n = *str does not convert the number represented by the digits in str, it merely stores the value of the first character into n, for example '0' will convert to 48 on ASCII systems. You should instead process every digit in the string, multiplying the value converted so far by 10 and adding the value represented by the digit with str[i] - '0'.
Here is a corrected version with your restrictive semantics:
int convert(const char *str, int *n) {
int value = 0;
if (str == NULL)
return 0;
while (*str) {
if (isdigit((unsigned char)*str)) {
value = value * 10 + *str++ - '0';
} else {
return 0;
}
}
*n = value;
return 1;
}
conversion of char* pointer to int*
#include
main()
{
char c ,*cc;
int i, *ii;
float f,*ff;
c = 'A'; /* ascii value of A gets
stored in c */
i=25;
f=3.14;
cc =&c;
ii=&i;
ff=&f;
printf("\n Address contained
in cc =%u",cc);
printf("\n Address contained
in ii =%u",ii);
printf(:\n Address contained
in ff=%u",ff);
printf(\n value of c= %c",
*cc);
printf(\n value of i=%d",
**ii);
printf(\n value of f=%f",
**ff);
}
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.
I'm facing some issues while I use toascii() it converts any int to ascii, but not int < 10, it returens \x1 or \x2 and so but not the ascii symbol which it should represent. so, any help please.
My code be like:
char* PostUnpack()
{
char* InStr = "04214FABF666DCE7";
int Len = strlen(InStr);
int Count, OutCount = 0;
int IntToHex;
char HexToChr[3] = "";
char TempCnv;
char RetStr[20] = "" ;
for(Count = 0; Count < Len; Count++)
{
strncpy(HexToChr,&InStr[Count],2);
IntToHex = (int) strtol(HexToChr, NULL, 16);
TempCnv = IntToHex;
toascii(TempCnv);
RetStr[OutCount] = TempCnv;
strncpy(HexToChr, "", strlen(HexToChr));
Count++;
OutCount++;
}
return RetStr;
actually in debug it be like:
\x4!O«öfÜç
while it should be :
!O«öfÜç
because I don't want to print the out put, but I use the return value to be used by some encryption method, and now when I pass this incorrect return value it make an incorrect encryption.
As already pointed out, one of the issues may be that toascii(), although working as designed, is not be producing it's converted value in the way you expect. You must use the return value of the function to get the converted value. For example, as you have called it:
toascii(TempCnv);//the converted value is returned, and you are not capturing it.
^^^^
use either a direct assignment statement to capture the value like this:
char c = toascii(0x51); //example value should produce ASCII character 3
Or you can use the string function sprintf() to place the converted value into a variable:
char c = 0;
sprintf(c, "%c", toascii(0x51));
Also, the range of printable ASCII characters is 0x20 - 0x7E. There is a paper that discusses the problems that are encountered when attempting to work with non-printable characters here
heres one that works
char * conv(char * str)
{
int l = strlen(str);
char buff[3];
buff[2] = 0;
int oidx = 0;
char *out = malloc(l/2 + 1);
int i;
for( i = 0; i < l; )
{
buff[0]= str[i++];
buff[1] = str[i++];
long x = strtol(buff, 0,16);
out[oidx++] = x;
}
out[oidx] = 0;
return strdup(out);
}
int main(void) {
char* InStr = "04214FABF666DCE7";
char* ans = conv(InStr);
free(ans);
}
does not deal with odd length input. Note the allocation of return buffer and freeing by caller. And no check of malloc
It seems the point of toascii() is to limit a value to using at most 7 bits, i.e. toascii(x) is equivalent to x &= 127. This might not be what you expect.
See the documentation for details.
I'm trying to parse a char string into an INT.
If I had...
unsigned char color[] = "255"
And wanted to parse this into an INT. How would I go about doing this?
I tried...
unsigned char *split;
split = strtok(color," ,.-");
while(split != NULL)
{
split = strok(NULL, " ,.-);
}
This just gives me the value 255 for split now.
I feel like I need something like...
int y = split - '0'; //but this makes an INT pointer without a cast
To convert a string to integer, call strtol:
char color[] = "255";
long n;
char *end = NULL;
n = strtol(color, &end, 10);
if (*end == '\0') {
// convert was successful
// n is the result
}
If you want to convert without calling strtol you can scan the color array and compare each char against '0' to get the corresponding numeric value, then add the result properly multiplied by a power of 10, i.e.
int i = 0, strlen = 0, result = 0;
while (color[i++]) strlen++;
for (i = 0; i<strlen; i++)
{
result += (color[i] - '0')*pow(10,strlen-1-i);
}
I've just recently been required to work with C—I normally work with Python and a bit of Java—and I've been running into some issues.
I created a function that converts a base-10 unsigned int into a character array that represents the equivalent hex. Now I need to be able to set a variable with type uint32_t to this 'hex'; what can I do to make sure this char[] is treated as an actual hex value?
The code is below:
int DecToHex(long int conversion, char * regParams[])
{
int hold[8];
for (int index = 0; conversion > 0; index++)
{
hold[index] = conversion % 16;
conversion = conversion / 16;
}
int j = 0;
for (int i = 7; i > -1; i--)
{
if (hold[i] < 10 && hold[i] >= 0)
{
regParams[j] = '0' + hold[i];
}
else if (hold[i] > 9 && hold[i] < 16)
{
regParams[j] = '7' + hold[i];
}
else
{
j--;
}
j++;
}
return 0;
}
You should just use snprintf:
int x = 0xDA8F;
char buf[9];
snprintf(buf, sizeof(buf), "%X", x); // Use %x for lowercase hex digits
To convert a hex representation of a number to an int, use strtol (the third argument to it lets you specify the base), or, since you want to assign it to an unsigned data type, strtoul.
The code would look something like this:
char* HexStr = "8ADF4B";
uint32_t Num = strtoul(HexStr, NULL, 16);
printf("%X\n", Num); // Outputs 8ADF4B