I'm brand new to C and i'm working on a method that converts an ascii to an integer. So bascially if i have ABCD (base 16) ill get 43981 (base 10).. Just a short walk through of what i have. I take one digit at i time from the string then that number needs to be translated so i call my chartoint method. Then i think i need to * the pervious result by the base before i add the new number. I am also confused on the printf method. Here is my method so far.
void ascii2int(char *ascii, int base){
int totalstring = 0;
if(2<= base && base <= 16){
for (int i = 0; i < strlen(ascii); i++) {
// Extract a character
char c = ascii[i];
// Run the character through char2int
int digit = char2int(c);
totalstring= digit * base;
printf("%d/n",totalstring);
}
}
}
char2int
int char2int(char digit){
int converted = 0;
if(digit >= '0' && digit <= '9'){
converted = digit - '0';
}
else if( digit >= 'A' && digit <= 'F'){
converted = digit - 'A' + 10;
}
else{
converted = -1;}
return converted;
}
Assuming that function char2int is implemented correctly...
Change this:
totalstring = digit * base;
To this:
totalstring *= base; // totalstring = totalstring * base
totalstring += digit; // totalstring = totalstring + digit
Or to this:
totalstring = totalstring * base + digit;
In addition, call printf outside the for loop (and change that /n to \n).
Solution :
void ascii2int(char *ascii, int base){
//int digit = 0;
int totalstring = 0;
if(2<= base && base <= 16){
for (int i = 0; i < strlen(ascii); i++) {
// Extract a character
char c = ascii[i];
// Run the character through char2int
int digit = char2int(c);
totalstring = totalstring * base + digit;
}
printf("%d", totalstring);
}
}
Related
I have this function which receives the number 894867 (nbr) and the length 16 (i). When I run this code, it writes =A793 instead of what it should write DA793.
void ft_transformers(int nbr, int i) {
char num[100];
int t;
int temp;
int j;
temp = 0;
t = 0;
while (nbr != 0) {
temp = nbr % i;
if (num[t] < 10) {
num[t] = temp + 48;
} else {
num[t] = temp + 55;
}
nbr /= i;
t++;
}
j = t;
while (j >= 0) {
ft_putchar(num[j]);
j--;
}
}
There are multiple problems:
Instead of if (num[t] < 10), you should be testing if (temp < 10)
instead of hardcoding ASCII values such as 48 and 55, you should use character constants and expressions '0' and 'A' - 10
the final loop should decrement j before accessing the character in the array.
the behavior is undefined if i is 0, 1 or -1.
Here is a modified version:
void ft_transformers(int nbr, int base) {
char num[100];
int t;
int j;
if (base < 2 || base > 36)
base = 10;
t = 0;
while (nbr != 0) {
int temp = nbr % base;
if (temp < 10) {
num[t] = '0' + temp;
} else {
num[t] = 'A' + (temp - 10);
}
nbr /= base;
t++;
}
j = t;
while (j > 0) {
j--;
ft_putchar(num[j]);
}
}
Note also these shortcomings:
the function will not output anything if the initial value of nbr is zero.
the function will not output digits if nbr is negative.
Here is an improved version:
void ft_transformers(int nbr, int base) {
char num[100];
int t;
int j;
int isneg;
if (base < 2 || base > 36)
base = 10;
isneg = 0;
t = 0;
for (;;) {
int temp = nbr % base;
if (temp < 0) {
isneg = 1;
temp = -temp;
}
if (temp < 10) {
num[t] = '0' + temp;
} else {
num[t] = 'A' + (temp - 10);
}
t++;
nbr /= base;
if (nbr == 0)
break;
}
if (isneg) {
ft_putchar('-');
}
j = t;
while (j > 0) {
j--;
ft_putchar(num[j]);
}
}
Your code has two errors:
The condition num[t] < 10 is wrong. num[t] is uninitialized at that point. It should be temp < 10.
The initialization of the second loop j = t; is wrong. t++; is executed at the end of the first loop and nothing is written to num[t] after that before the second loop. It should be j = t - 1;.
Also using magic numbers like 48 and 55 should be avoided. They should be '0' and 'A' - 10 to make it more clear. (unless your code has chance to be used in environments where character sets that are not compatible to ASCII are used)
There are at least three drawbacks in the function.
For starters instead of the while loop you have to use do-while loop. Otherwise if nbr initially is equal to 0 the function will have undefined behavior.
Secondly, in this if statement
if (num[t] < 10) {
you have to use the variable temp instead of num[t]
if ( temp < 10) {
After the while loop the variable t points to after the last digit of the number. So in the first iteration of this loop
j = t;
while (j >= 0) {
ft_putchar(num[j]);
j--;
}
there will be outputted an indeterminate value.
T least you should write
j = t;
while (j != 0) {
ft_putchar(num[--j]);
}
Pay also attention to that your function ignores the sign of the original number.
And it is a bad idea to use magic numbers like for example 48 or 55.
The function can be declared the following way as it is shown in the demonstration program be.low.
#include <stdio.h>
void ft_transformers( int nbr, int base )
{
if ( base < 2 || base > 36 )
{
printf( "%d\n", nbr );
}
else
{
char num[8 * sizeof( int )];
int sign = nbr < 0;
size_t i = 0;
do
{
int digit = nbr % base;
if ( sign ) digit = -digit;
if ( digit < 10 )
{
digit += '0';
}
else
{
digit = digit - 10 + 'A';
}
num[i++] = digit;
} while ( nbr /= base );
if ( sign ) putchar( '-' );
while ( i != 0 ) putchar( num[--i] );
putchar( '\n' );
}
}
int main( void )
{
int nbr = 0;
ft_transformers( nbr, 16 );
nbr = 894867;
ft_transformers( nbr, 16 );
nbr = -894867;
ft_transformers( nbr, 16 );
}
The program output is
0
DA793
-DA793
In this declaration of the character array
char num[8 * sizeof( int )];
instead of the number 8 (the number of bits in a character) you can use the constant CHAR_BIT like
char num[CHAR_BIT * sizeof( int )];
To do so you need to include the header <limits.h>.
Hello I am trying to convert a hex value into the decimal form but for some reason the result I'm getting each time is negative and completely incorrect. Additionally I would like to take that decimal number and then convert it into it binary value. I have created func's for both but have run into the problem of "too few arguments" when calling my bin() func. If somebody could point me in the right direction and explain what I am doing wrong I would sincerely appreciate it.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define arraysize 20
int decimal() {
int i = 0, val, len;
char hex1[arraysize];
long long dec = 0, base = 1;
len = strlen(hex1);
for (i = len--;i >= 0; i--) {
if (hex1[1] >= '0' && hex1[i] <= '9') {
dec += (hex1[i] - 48) * base;
base *= 16;
}
else if (hex1[i] >= 'A' && hex1[i] <= 'F') {
dec += (hex1[i] - 55) * base;
base *= 16;
}
else if (hex1[i] >= 'a' && hex1[i] <= 'f') {
dec += (hex1[i] - 87) * base;
base *= 16;
}
}
printf("Your decimal value is: %lld\n",dec);
return 0;
}
int bin(long long dec) {
int a[10], i;
for (i = 0; dec > 0; i++) {
a[i] = dec % 2;
dec = dec / 2;
}
printf("\nThe binary value is: ");
for (i = i - 1; i >= 0; i--) {
printf("%d", a[i]);
}
return 0;
}
int main() {
char hex1[arraysize];
printf("Enter your HEX value: ");
fflush(stdin);
fgets(hex1, arraysize, stdin);
decimal(hex1);
bin();
}
There are multiple problems in your code:
hex1 should be passed as an argument to decimal(). As posted, your code has undefined behavior because hex1 is an uninitialized local array.
i = len-- initializes i to the value of len, hence one position too far. Use i = len - 1 instead.
if (hex1[1] >= '0' && hex1[i] <= '9') uses hex[1] instead of hex[i]
you should use expressions with character constants '0', ('A' - 10) and ('a' - 10) instead of hard coded magical values 48, 55 and 87.
the array a is too short in function bin(). You should give it a length of at least 64.
the argument in bin() should have unsigned long long type.
fflush(stdin); has undefined behavior.
Here is a modified version:
#include <stdio.h>
unsigned long long decimal(const char *hex) {
unsigned long long dec = 0;
int i, c;
for (i = 0; (c = hex[i]) != '\0'; i++) {
if (c >= '0' && c <= '9') {
dec = dec * 16 + (c - '0');
} else
if (c >= 'A' && c <= 'F') {
dec = dec * 16 + (c - 'A' + 10);
} else
if (c >= 'a' && c <= 'f') {
dec = dec * 16 + (c - 'a' + 10);
}
}
return dec;
}
void bin(unsigned long long dec) {
char a[65];
int i;
a[64] = '\0';
for (i = 63;; i--) {
a[i] = '0' + dec % 2;
dec = dec / 2;
if (dec == 0)
break;
}
printf("The binary value is: %s\n", a);
}
int main() {
char hex1[20];
printf("Enter your HEX value: ");
if (fgets(hex1, sizeof hex1, stdin)) {
unsigned long long dec = decimal(hex1);
printf("Your decimal value is: %llu\n", dec);
bin(dec);
}
return 0;
}
The "too few arguments" error means exactly what it says: you are calling the bin() function with no arguments. In your function definition, you defined bin() as taking a long long dec argument. When you call bin(), you must give it an argument, like
bin(7);
You have made the opposite mistake in the line above:
decimal(hex1);
You defined decimal() as taking no arguments, yet you called it with a char[] argument. In your decimal function you can remove the line where you declare an array of chars, and instead make that an argument of the function:
int decimal(char* hex1) {
int i = 0, val, len;
long long dec = 0, base = 1;
. . .
You may want to further research the semantics of passing an array as an argument to a function.
Try this and replace char hex1[arraysize]="FFFFFFFFFFFFFFFF"; as needed:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define arraysize 20
#define bin_arraysize 64
unsigned long long decimal(char* hex1) {
long long dec = 0, base = 1;
int len = strlen(hex1);
for(int i = len-1;i >=0; i--) {
if(hex1[i] >= '0' && hex1[i] <= '9') {
dec += (hex1[i] - 48) * base;
base *= 16;
}
else if(hex1[i] >= 'A' && hex1[i] <= 'F') {
dec += (hex1[i] - 55) * base;
base *= 16;
}
else if(hex1[i] >= 'a' && hex1[i] <= 'f') {
dec += (hex1[i] - 87) * base;
base *= 16;
}
}
printf("Your decimal value is: %llu\n",dec);
return dec;
}
void bin(unsigned long long dec) {
int a[bin_arraysize], i;
for(i = 0; dec > 0; i++) {
a[i] = dec%2;
dec = dec/2;
}
printf("\nThe binary value is: ");
for(i = i - 1; i >= 0; i--) {
printf("%d", a[i]);
}
return;
}
int main() {
char hex1[arraysize]="FFFFFFFFFFFFFFFF";
unsigned long long dec=decimal(hex1);
bin(dec);
}
#include<stdio.h>
#include<string.h>
void baseconversion(char s[20], int, int);
main()
{
char s[20];
int base1, base2;
printf("Enter the number and base:");
scanf("%s%d", s, &base1);
printf("Enter the base to be converted:");
scanf("%d", &base2);
baseconversion(s, base1, base2);
}
void baseconversion(char s[20], int b1, int b2)
{
int count = 0, r, digit, i, n = 0, b = 1;
for(i = strlen(s) - 1; i >= 0; i--)
{
if(s[i] >= 'A' && s[i] <= 'Z')
{
digit = s[i] - '0' - 7;
}
else
{
digit = s[i] - '0';
}
n = digit * b + n;
b = b * b1;
}
while(n != 0)
{
r = n % b2;
digit = '0' + r;
if(digit > '9')
{
digit += 7;
}
s[count] = digit;
count++;
n = n / b2;
}
for(i = count - 1; i >= 0; i--)
{
printf("%c", s[i]);
}
printf("\n");
}
I know this code converts chars to integers, but I've never seen it before, never used C.
If someone could explain a bit of what's going on with the conversions I'd appreciate it, thank you.
I understand that at some point the digits get reversed.
It does it through two steps, the first one is converting the number into its decimal form, in this part:
for(i = strlen(s) - 1; i >= 0; i--) //Start from right to left
{
if(s[i] >= 'A' && s[i] <= 'Z')
digit = s[i] - '0' - 7; //Get the integer equivalent to the letter
else
digit = s[i] - '0'; //Get the integer equivalent to the numerical character
n = digit * b + n; //Add the value of this character at this position
b = b * b1; //The value of the next character will be higher b times
}
Then it transforms the result to the desired base, in this part:
while(n != 0)
{
r = n % b2; //The remaining will be the rightmost value for the new base
digit = '0' + r; //Get the integer for the new digit
if(digit > '9')
digit += 7; //Here the digit will be a letter
s[count] = digit;
count++;
n = n / b2; //Remove the rightmost digit to get the next one
}
I have an assignment where I need to print an integer in C without using printf, putchar, etc. No header files allowed to be included. No function calls except for anything I wrote. I have one function my_char I am using (maybe its wrong) but it prints out a character. I currently have the following code which is printing the number out backwards. Not looking for an answer. Just looking for some direction, some help, maybe I'm looking at it completely wrong.
void my_int(int num)
{
unsigned int i;
unsigned int j;
char c;
if (num < 0)
{
my_char('-');
num = -num;
}
do
{
j = num % 10;
c = j + '0';
my_char(c);
num = num/10;
}while(num >0);
}
Instead of calling my_char() in the loop instead "print" the chars to a buffer and then loop through the buffer in reverse to print it out.
Turns out you can't use arrays. In which case you can figure out the max power of 10 (ie log10) with the loop. Then use this to work backwards from the first digit.
unsigned int findMaxPowOf10(unsigned int num) {
unsigned int rval = 1;
while(num) {
rval *= 10;
num /= 10;
}
return rval;
}
unsigned int pow10 = findMaxPowOf10(num);
while(pow10) {
unsigned int digit = num / pow10;
my_char(digit + '0');
num -= digit * pow10;
pow10 /= 10;
}
One option might be to do this recursively, so the number gets printed out in the right order.
In this case, instead of a do/while loop, you'd have a construction more like this, with a base case of num=0.
if(num==0)
return;
j = num % 10;
c = j + '0';
my_int(num/10);
my_char(c);
Edit: Noticed that you aren't allowed to use recursion. It's a bit ugly, but you could check for the digits in the number, and then loop backwards across the number.
To find the number of digits,
int digitDivide = 1;
int tempNum = num;
while(tempNum>0){
tempNum= tempNum/10;
digitDivide=digitDivide*10;
}
and then use that to loop through the number as follows:
digitDivide = digitDivide/10;
while(digitDivide>0){
tempNum = (num/digitDivide)%10;
c = j + '0';
my_char(c);
digitDivide=digitDivide/10;
}
You can convert an int to char * , char * and display this char* :
char *put_int(int nb)
{
char *str;
str = malloc(sizeof(char) * 4);
if (str == NULL)
return (0);
str[0] = (nb / 100) + '0';
str[1] = ((nb - ((nb / 100 * 100 )) / 10) + '0');
str[2] = ((nb % 10) + '0');
return (str);
}
void put_str(char *str)
{
while (*str)
write(1, str++,1);
}
int main(void)
{
put_str(put_int(42));
return (0);
}
How do I convert a binary string like "010011101" to an int, and how do I convert an int, like 5, to a string "101" in C?
The strtol function in the standard library takes a "base" parameter, which in this case would be 2.
int fromBinary(const char *s) {
return (int) strtol(s, NULL, 2);
}
(first C code I've written in about 8 years :-)
If it is a homework problem they probably want you to implement strtol, you would have a loop something like this:
char* start = &binaryCharArray[0];
int total = 0;
while (*start)
{
total *= 2;
if (*start++ == '1') total += 1;
}
If you wanted to get fancy you could use these in the loop:
total <<= 1;
if (*start++ == '1') total^=1;
I guess it really depends on some questions about your strings/program. If, for example, you knew your number wouldn't be bigger than 255 (IE you were only using 8 bits or 8 0s/1s), you could create a function where you hand it 8 bits from your string, traverse it and add to a sum that you returned everytime you hit a 1. IE if you hit the bit for 2^7 add 128 and the next bit you hit was 2^4 add 16.
This is my quick and dirty idea. I think more and Google for ya while at school. :D
For the 2nd part of the question, i.e. "how do I convert an int, like 5, to a string "101" in C?", try something like:
void
ltostr( unsigned long x, char * s, size_t n )
{
assert( s );
assert( n > 0 );
memset( s, 0, n );
int pos = n - 2;
while( x && (pos >= 0) )
{
s[ pos-- ] = (x & 0x1) ? '1' : '0'; // Check LSb of x
x >>= 1;
}
}
You can use the following coding
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main (void)
{
int nRC = 0;
int nCurVal = 1;
int sum = 0;
char inputArray[9];
memset(inputArray,0,9);
scanf("%s", inputArray);
// now walk the array:
int nPos = strlen(inputArray)-1;
while(nPos >= 0)
{
if( inputArray[nPos] == '1')
{
sum += nCurVal;
}
--nPos;
nCurVal *= 2;
}
printf( "%s converted to decimal is %d\n", inputArray, sum);
return nRC;
}
Use like this:
char c[20];
int s=23;
itoa(s,c,2);
puts(c);
Output:
10111
To answer the second part of the question.
char* get_binary_string(uint16_t data, unsigned char sixteen_bit)
{
char* ret = NULL;
if(sixteen_bit) ret = (char*)malloc(sizeof(char) * 17);
else ret = (char*)malloc(sizeof(char) * 9);
if(ret == NULL) return NULL;
if(sixteen_bit){
for(int8_t i = 15; i >= 0; i--){
*(ret + i) = (char)((data & 1) + '0');
data >>= 1;
}
*(ret + 16) = '\0';
return ret;
}else{
for(int8_t i = 7; i >= 0; i--){
*(ret + i) = (char)((data & 1) + '0');
data >>= 1;
}
*(ret + 8) = '\0';
return ret;
}
return ret;
}
To answer the first part of your question, here is a neat little function I created to convert Binary char strings to integers.
// Function used to change binary character strings to integers
int binToDec(char binCode[])
{
while (binCode != NULL)
{
int base = strlen(binCode) - 1; // the base of 2 to be multiplied, we start of -1 because we dont account for the last bit here
int sum = 0;
for (int i = 0; i < strlen(binCode) - 1; i++) // we do not account for the last bit of the binary code here....
{
int decimal = 1;
if (binCode[i] == '1')
{
for (int j = 0; j < base; j++) // we want to just multiply the number of true bits (not including the 1)
{
decimal = decimal * 2;
}
base = base - 1; // subtract base by 1 since we are moving down the string by 1
}
else // we encounter a zero
{
base = base - 1; // subtract a base multiple every time we encounter a zero...
continue; // carry on with the code
}
sum += decimal;
// starting from the left (higher power) to the end (lowest power or 1)
}
for (int j = strlen(binCode) - 1; j < strlen(binCode) + 1; j++)
{ // accounting for the endian bit that is always 1
if (binCode[j] == '1')
{
sum += 1; // add 1 to the sum total
}
}
return sum; // return the sum as an int
}
return 0;
}