I'm trying to learn c and am confused why my hex to int conversion function returns a value that is off by one.
Note: 0XAAAA == 46390
#include <stdio.h>
#include <math.h>
unsigned int hex_to_int(char hex[4]);
int main()
{
char hex[4] = "AAAA";
unsigned int result = hex_to_int(hex);
printf("%d 0X%X\n", result, result);
return 0;
}
unsigned int hex_to_int(char input[4])
{
unsigned int sum, i, exponent;
for(i = 0, exponent = 3; i < 4; i++, exponent--) {
unsigned int n = (int)input[i] - 55;
n *= pow(16, exponent);
sum += n;
}
return sum;
}
Output:
46391 0XAAAB
Update: I now realize "- 55" is ridiculous, I was going off memory from seeing this:
if (input[i] >= '0' && input[i] <= '9')
val = input[i] - 48;
else if (input[i] >= 'a' && input[i] <= 'f')
val = input[i] - 87;
else if (input[i] >= 'A' && input[i] <= 'F')
val = input[i] - 55;
You have several bugs such as the string not getting null terminated, and the ASCII to decimal conversion being nonsense (value 55?), you don't initialize sum and so on. Just do this instead:
#include <stdio.h>
#include <stdlib.h>
int main()
{
char x[] = "AAAA";
unsigned int sum = strtoul(x, NULL, 16);
printf("%d 0X%X\n", sum, sum);
return 0;
}
EDIT
If you insist on doing this manually:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
unsigned int hexstr_to_uint(const char* str);
int main()
{
char x[] = "AAAA";
unsigned int sum = hexstr_to_uint (x);
printf("%d 0X%X\n", sum, sum);
return 0;
}
unsigned int hexstr_to_uint(const char* str)
{
unsigned int sum = 0;
for(; *str != '\0'; str++)
{
sum *= 16;
if(isdigit(*str))
{
sum += *str - '0';
}
else
{
char digit = toupper(*str);
_Static_assert('Z'-'A'==25, "Trash systems not supported.");
if(digit >= 'A' && digit <= 'F')
{
sum += digit - 'A' + 0xA;
}
}
}
return sum;
}
You're just making up logic, there isn't a single value you can subtract from a hexadecimal digit character to convert it into the corresponding number.
If you want to be portable, all that C requires is that the symbols 0 through 9 are consecutive in their encoding. There's no such guarantee for the letters A through F.
Also involving pow() which is a double-precision floating point function in this low-level integer work, is a bit jarring. The typical way to do this is by multiplication or bitwise shifting.
If you're hell-bent on doing the conversion yourself, I usually do something like this:
unsigned int hex2int(const char *a)
{
unsigned int v = 0;
while(isxdigit((unsigned int) *a))
{
v *= 16;
if(isdigit((unsigned int) *a))
v += *a - '0';
else
{
const char highs[] = "abcdef";
const char * const h = strchr(highs, tolower(*a));
v += 10 + (unsigned int) (h - highs);
}
++a;
}
return v;
}
The above is a bit verbose, you can for instance fold the decimal digits into the string used for the letters too, I just tried to be clear. The above should work for any valid C character set encoding, not just ASCII (and it's less passive-aggressive than #Lundin's code, hih :).
Related
I tried to write a solution from exercise 2-3. After compilation, it returns random numbers on output. I don't really understand where this issue is coming from.
Any help appreciated.
StackOverflow keeps asking for more details. The purpose of the program is listed in the code bellow.
More delails.
Purpose of the code:
Write the function htoi(s), which converts a string of hexa-
decimal digits (including an optional 0x or 0X) into its
equivalent integer value. The allowable digits are 0 through 9,
a through f, and A through F.
/*
* Write the function htoi(s), which converts a string of hexa-
* decimal digits (including an optional 0x or 0X) into its
* equivalent integer value. The allowable digits are 0 through 9,
* a through f, and A through F.
*/
#include <stdio.h>
#include <math.h>
int hti(char s)
{
const char hexlist[] = "aAbBcCdDeEfF";
int answ = 0;
int i;
for (i=0; s != hexlist[i] && hexlist[i] != '\0'; i++)
;
if (hexlist[i] == '\0')
answ = 0;
else
answ = 10 + (i/2);
return answ;
}
unsigned int htoi(const char s[])
{
int answ;
int power = 0;
signed int i = 0;
int viable = 0;
int hexit;
if (s[i] == '0')
{
i++;
if (s[i] == 'x' || s[i] == 'X')
i++;
}
const int stop = i;
for (i; s[i] != '\0'; i++)
;
i--;
while (viable == 0 && i >= stop)
{
if (s[i] >= '0' && s[i] <= '9')
{
answ = answ + ((s[i] - '0') * pow(16, power));
}
else
{
hexit = hti(s[i]);
if (hexit == 0)
viable = 1;
else
{
hexit = hexit * (pow(16, power));
answ += hexit;
}
}
i--;
power++;
}
if (viable == 1)
return 0;
else
return answ;
}
int main()
{
char test[] = "AC";
int i = htoi(test);
printf("%d\n", i);
return 0;
}
answ is not initialized in htoi. Initialize it to zero.
I am attempting the htoi(char*) function from The C Programming Language by K&R (Excercise 2-3, pg. 43).
The function is meant to convert a hexadecimal string to base 10.
I believe I have it working. This is my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
enum {hexbase = 16};
typedef enum{false, true} bool;
unsigned int htoi(char* s);
bool hasHexPrefix(char* s);
int main(int argc, char** argv) {
if(argc <= 1) {
printf("Error: Not enough arguments.\n");
return EXIT_FAILURE;
}else {
for(int i = 1; i < argc; i++) {
unsigned int numericVal = htoi(argv[i]);
printf("%s => %u\n",argv[i],numericVal);
}
}
}
unsigned int htoi(char* s) {
unsigned int output = 0;
unsigned int len = (unsigned int)(strlen(s));
unsigned short int firstIndex = hasHexPrefix(s) ? 2 : 0;
/* start from the end of the str (least significant digit) and move to front */
for(int i = len-1; i >= firstIndex; i--) {
int currentChar = s[i];
unsigned int correspondingNumericVal = 0;
if(currentChar >= '0' && currentChar <= '9') {
correspondingNumericVal = currentChar - '0';
}else if(currentChar >= 'a' && currentChar <= 'f') {
correspondingNumericVal = (currentChar - 'a') + 10;
}else if(currentChar >= 'A' && currentChar <= 'F') {
correspondingNumericVal = (currentChar - 'A') + 10;
}else {
printf("Error. Invalid hex digit: %c.\n",currentChar);
}
/* 16^(digitNumber) */
correspondingNumericVal *= pow(hexbase,(len-1)-i);
output += correspondingNumericVal;
}
return output;
}
bool hasHexPrefix(char* s) {
if(s[0] == '0')
if(s[1] == 'x' || s[1] == 'X')
return true;
return false;
}
My issue is with the following line from the htoi(char*) function:
unsigned short int firstIndex = hasHexPrefix(s) ? 2 : 0;
When I remove short to make firstIndex into an unsigned int rather than an unsigned short int, I get an infinite loop.
So when I start from the back of s in htoi(char* s), i >= firstIndex never evaluates to be false.
Why does this happen? Am I missing something trivial or have I done something terribly wrong to cause this undefined behavior?
When firstIndex is unsigned int, in i >= firstIndex then i is converted to unsigned int because of the usual arithmetic conversions. So if i is negative it becomes a large integer in the comparison expression. When firstIndex is unsigned short int in i >= firstIndex, firstIndex is promoted to int and two signed integers are compared.
You can change:
for(int i = len-1; i >= firstIndex; i--)
to
for(int i = len-1; i >= (int) firstIndex; i--)
to have the same behavior in both cases.
I'm having the literal value that should be stored on an unsigned char[64] array. How can I convert such values to it's hex equivalent?
int main() {
unsigned char arry[1] = { 0xaa }
char* str = "fe"; //I want to store 0xfe on arry[0]
arry[0] = 0xfe; // this works, but I have to type it
arry[0] = 0x + str; //obviously fails
return 0;
}
Any pointers?
arr[0] = strtol(str,NULL,16); // If one entry is big enough to hold it.
For each character c, the value is:
if ('0' <= c && c <= '9') return c - '0';
if ('a' <= c && c <= 'f') return c - 'a' + 10;
if ('A' <= c && c <= 'F') return c - 'A' + 10;
// else error, invalid digit character
Now just iterate over the string from left to right, adding up the digit values, and multiplying the result by 16 each time.
(This is implemented for you by the standard library in the strto*l functions with base 16.)
Use function strtol() to convert a string to a long in a specific base: http://www.cplusplus.com/reference/cstdlib/strtol/
"Parses the C-string str interpreting its content as an integral number of the specified base, which is returned as a long int value. If endptr is not a null pointer, the function also sets the value of endptr to point to the first character after the number."
Example:
#include <stdio.h> /* printf */
#include <stdlib.h> /* strtol */
int main ()
{
char szNumbers[] = "2001 60c0c0 -1101110100110100100000 0x6fffff";
char * pEnd;
long int li1, li2, li3, li4;
li1 = strtol (szNumbers,&pEnd,10);
li2 = strtol (pEnd,&pEnd,16);
li3 = strtol (pEnd,&pEnd,2);
li4 = strtol (pEnd,NULL,0);
printf ("The decimal equivalents are: %ld, %ld, %ld and %ld.\n", li1, li2, li3, li4);
return 0;
}
Put together an arbitrary length solution to and from.
Sadly the String to X is verbose: pesky dealing with non hex string, odd length, too big, etc.
#include <string.h>
#include <stdio.h>
// S assumed to be long enough.
// X is little endian
void BigXToString(const unsigned char *X, size_t Length, char *S) {
size_t i;
for (i = Length; i-- > 0; ) {
sprintf(S, "%02X", X[i]);
S += 2;
}
}
int BigStringToX(const char *S, unsigned char X[], size_t Length) {
size_t i;
size_t ls = strlen(S);
if (ls > (Length * 2)) {
return 1; //fail, too big
}
int flag = ls & 1;
size_t Unused = Length - (ls/2) - flag;
memset(&X[Length - Unused], 0, Unused); // 0 fill unused
char little[3];
little[2] = '\0';
for (i = Length - Unused; i-- > 0;) {
little[0] = *S++;
little[1] = flag ? '\0' : *S++;
flag = 0;
char *endptr;
X[i] = (unsigned char) strtol(little, &endptr, 16);
if (*endptr) return 1; // non-hex found
if (*S == '\0') break;
}
return 0;
}
int main() {
unsigned char X[64];
char S[64 * 2 + 2];
char T[64 * 2 + 2];
strcpy(S, "12345");
BigStringToX(S, X, sizeof(X));
BigXToString(X, sizeof(X), T);
printf("'%s'\n", T);
return 0;
}
I'm trying to convert an integer 10 into the binary number 1010.
This code attempts it, but I get a segfault on the strcat():
int int_to_bin(int k)
{
char *bin;
bin = (char *)malloc(sizeof(char));
while(k>0) {
strcat(bin, k%2);
k = k/2;
bin = (char *)realloc(bin, sizeof(char) * (sizeof(bin)+1));
}
bin[sizeof(bin)-1] = '\0';
return atoi(bin);
}
How do I convert an integer to binary in C?
If you want to transform a number into another number (not number to string of characters), and you can do with a small range (0 to 1023 for implementations with 32-bit integers), you don't need to add char* to the solution
unsigned int_to_int(unsigned k) {
if (k == 0) return 0;
if (k == 1) return 1; /* optional */
return (k % 2) + 10 * int_to_int(k / 2);
}
HalosGhost suggested to compact the code into a single line
unsigned int int_to_int(unsigned int k) {
return (k == 0 || k == 1 ? k : ((k % 2) + 10 * int_to_int(k / 2)));
}
You need to initialise bin, e.g.
bin = malloc(1);
bin[0] = '\0';
or use calloc:
bin = calloc(1, 1);
You also have a bug here:
bin = (char *)realloc(bin, sizeof(char) * (sizeof(bin)+1));
this needs to be:
bin = (char *)realloc(bin, sizeof(char) * (strlen(bin)+1));
(i.e. use strlen, not sizeof).
And you should increase the size before calling strcat.
And you're not freeing bin, so you have a memory leak.
And you need to convert 0, 1 to '0', '1'.
And you can't strcat a char to a string.
So apart from that, it's close, but the code should probably be more like this (warning, untested !):
int int_to_bin(int k)
{
char *bin;
int tmp;
bin = calloc(1, 1);
while (k > 0)
{
bin = realloc(bin, strlen(bin) + 2);
bin[strlen(bin) - 1] = (k % 2) + '0';
bin[strlen(bin)] = '\0';
k = k / 2;
}
tmp = atoi(bin);
free(bin);
return tmp;
}
Just use itoa to convert to a string, then use atoi to convert back to decimal.
unsigned int_to_int(unsigned int k) {
char buffer[65]; /* any number higher than sizeof(unsigned int)*bits_per_byte(8) */
return atoi( itoa(k, buffer, 2) );
}
The working solution for Integer number to binary conversion is below.
int main()
{
int num=241; //Assuming 16 bit integer
for(int i=15; i>=0; i--) cout<<((num >> i) & 1);
cout<<endl;
for(int i=0; i<16; i++) cout<<((num >> i) & 1);
cout<<endl;
return 0;
}
You can capture the cout<< part based on your own requirement.
Well, I had the same trouble ... so I found this thread
I think the answer from user:"pmg" does not work always.
unsigned int int_to_int(unsigned int k) {
return (k == 0 || k == 1 ? k : ((k % 2) + 10 * int_to_int(k / 2)));
}
Reason: the binary representation is stored as an integer. That is quite limited.
Imagine converting a decimal to binary:
dec 255 -> hex 0xFF -> bin 0b1111_1111
dec 1023 -> hex 0x3FF -> bin 0b11_1111_1111
and you have to store this binary representation as it were a decimal number.
I think the solution from Andy Finkenstadt is the closest to what you need
unsigned int_to_int(unsigned int k) {
char buffer[65]; // any number higher than sizeof(unsigned int)*bits_per_byte(8)
return itoa( atoi(k, buffer, 2) );
}
but still this does not work for large numbers.
No suprise, since you probably don't really need to convert the string back to decimal. It makes less sense. If you need a binary number usually you need for a text somewhere, so leave it in string format.
simply use itoa()
char buffer[65];
itoa(k, buffer, 2);
You can use function this function to return char* with string representation of the integer:
char* itob(int i) {
static char bits[8] = {'0','0','0','0','0','0','0','0'};
int bits_index = 7;
while ( i > 0 ) {
bits[bits_index--] = (i & 1) + '0';
i = ( i >> 1);
}
return bits;
}
It's not a perfect implementation, but if you test with a simple printf("%s", itob(170)), you'll get 01010101 as I recall 170 was. Add atoi(itob(170)) and you'll get the integer but it's definitely not 170 in integer value.
You could use this function to get array of bits from integer.
int* num_to_bit(int a, int *len){
int arrayLen=0,i=1;
while (i<a){
arrayLen++;
i*=2;
}
*len=arrayLen;
int *bits;
bits=(int*)malloc(arrayLen*sizeof(int));
arrayLen--;
while(a>0){
bits[arrayLen--]=a&1;
a>>=1;
}
return bits;
}
void intToBin(int digit) {
int b;
int k = 0;
char *bits;
bits= (char *) malloc(sizeof(char));
printf("intToBin\n");
while (digit) {
b = digit % 2;
digit = digit / 2;
bits[k] = b;
k++;
printf("%d", b);
}
printf("\n");
for (int i = k - 1; i >= 0; i--) {
printf("%d", bits[i]);
}
}
You can convert decimal to bin, hexa to decimal, hexa to bin, vice-versa etc by following this example.
CONVERTING DECIMAL TO BIN
int convert_to_bin(int number){
int binary = 0, counter = 0;
while(number > 0){
int remainder = number % 2;
number /= 2;
binary += pow(10, counter) * remainder;
counter++;
}
}
Then you can print binary equivalent like this:
printf("08%d", convert_to_bin(13)); //shows leading zeros
Result in string
The following function converts an integer to binary in a string (n is the number of bits):
// Convert an integer to binary (in a string)
void int2bin(unsigned integer, char* binary, int n=8)
{
for (int i=0;i<n;i++)
binary[i] = (integer & (int)1<<(n-i-1)) ? '1' : '0';
binary[n]='\0';
}
Test online on repl.it.
Source : AnsWiki.
Result in string with memory allocation
The following function converts an integer to binary in a string and allocate memory for the string (n is the number of bits):
// Convert an integer to binary (in a string)
char* int2bin(unsigned integer, int n=8)
{
char* binary = (char*)malloc(n+1);
for (int i=0;i<n;i++)
binary[i] = (integer & (int)1<<(n-i-1)) ? '1' : '0';
binary[n]='\0';
return binary;
}
This option allows you to write something like printf ("%s", int2bin(78)); but be careful, memory allocated for the string must be free later.
Test online on repl.it.
Source : AnsWiki.
Result in unsigned int
The following function converts an integer to binary in another integer (8 bits maximum):
// Convert an integer to binary (in an unsigned)
unsigned int int_to_int(unsigned int k) {
return (k == 0 || k == 1 ? k : ((k % 2) + 10 * int_to_int(k / 2)));
}
Test online on repl.it
Display result
The following function displays the binary conversion
// Convert an integer to binary and display the result
void int2bin(unsigned integer, int n=8)
{
for (int i=0;i<n;i++)
putchar ( (integer & (int)1<<(n-i-1)) ? '1' : '0' );
}
Test online on repl.it.
Source : AnsWiki.
You can add the functions to the standard library and use it whenever you need.
Here is the code in C++
#include <stdio.h>
int power(int x, int y) //calculates x^y.
{
int product = 1;
for (int i = 0; i < y; i++)
{
product = product * x;
}
return (product);
}
int gpow_bin(int a) //highest power of 2 less/equal to than number itself.
{
int i, z, t;
for (i = 0;; i++)
{
t = power(2, i);
z = a / t;
if (z == 0)
{
break;
}
}
return (i - 1);
}
void bin_write(int x)
{
//printf("%d", 1);
int current_power = gpow_bin(x);
int left = x - power(2, current_power);
int lower_power = gpow_bin(left);
for (int i = 1; i < current_power - lower_power; i++)
{
printf("0");
}
if (left != 0)
{
printf("%d", 1);
bin_write(left);
}
}
void main()
{
//printf("%d", gpow_bin(67));
int user_input;
printf("Give the input:: ");
scanf("%d", &user_input);
printf("%d", 1);
bin_write(user_input);
}
#define BIT_WIDTH 32
char *IntToBin(unsigned n, char *buffer) {
char *ptr = buffer + BIT_WIDTH;
do {
*(--ptr) = (n & 1) + '0';
n >>= 1;
} while(n);
return ptr;
}
#define TEST 1
#if TEST
#include <stdio.h>
int main() {
int n;
char buff[BIT_WIDTH + 1];
buff[BIT_WIDTH] = '\0';
while(scanf("%d", &n) == 1)
puts(IntToBin(n, buff));
return 0;
}
#endif
short a;
short b;
short c;
short d;
short e;
short f;
short g;
short h;
int i;
char j[256];
printf("BINARY CONVERTER\n\n\n");
//uses <stdlib.h>
while(1)
{
a=0;
b=0;
c=0;
d=0;
e=0;
f=0;
g=0;
h=0;
i=0;
gets(j);
i=atoi(j);
if(i>255){
printf("int i must not pass the value 255.\n");
i=0;
}
if(i>=128){
a=1;
i=i-128;}
if(i>=64){
b=1;
i=i-64;}
if(i>=32){
c=1;
i=i-32;}
if(i>=16){
d=1;
i=i-16;}
if(i>=8){
e=1;
i=i-8;}
if(i>=4){
f=1;
i=i-4;}
if(i>=2){
g=1;
i=i-2;}
if(i>=1){
h=1;
i=i-1;}
printf("\n%d%d%d%d%d%d%d%d\n\n",a,b,c,d,e,f,g,h);
}
I recently read a sample job interview question:
Write a function to convert an integer
to a string. Assume you do not have
access to library functions i.e.,
itoa(), etc...
How would you go about this?
fast stab at it: (edited to handle negative numbers)
int n = INT_MIN;
char buffer[50];
int i = 0;
bool isNeg = n<0;
unsigned int n1 = isNeg ? -n : n;
while(n1!=0)
{
buffer[i++] = n1%10+'0';
n1=n1/10;
}
if(isNeg)
buffer[i++] = '-';
buffer[i] = '\0';
for(int t = 0; t < i/2; t++)
{
buffer[t] ^= buffer[i-t-1];
buffer[i-t-1] ^= buffer[t];
buffer[t] ^= buffer[i-t-1];
}
if(n == 0)
{
buffer[0] = '0';
buffer[1] = '\0';
}
printf(buffer);
A look on the web for itoa implementation will give you good examples. Here is one, avoiding to reverse the string at the end. It relies on a static buffer, so take care if you reuse it for different values.
char* itoa(int val, int base){
static char buf[32] = {0};
int i = 30;
for(; val && i ; --i, val /= base)
buf[i] = "0123456789abcdef"[val % base];
return &buf[i+1];
}
The algorithm is easy to see in English.
Given an integer, e.g. 123
divide by 10 => 123/10. Yielding, result = 12 and remainder = 3
add 30h to 3 and push on stack (adding 30h will convert 3 to ASCII representation)
repeat step 1 until result < 10
add 30h to result and store on stack
the stack contains the number in order of | 1 | 2 | 3 | ...
I would keep in mind that all of the digit characters are in increasing order within the ASCII character set and do not have other characters between them.
I would also use the / and the% operators repeatedly.
How I would go about getting the memory for the string would depend on information you have not given.
Assuming it is in decimal, then like this:
int num = ...;
char res[MaxDigitCount];
int len = 0;
for(; num > 0; ++len)
{
res[len] = num%10+'0';
num/=10;
}
res[len] = 0; //null-terminating
//now we need to reverse res
for(int i = 0; i < len/2; ++i)
{
char c = res[i]; res[i] = res[len-i-1]; res[len-i-1] = c;
}
An implementation of itoa() function seems like an easy task but actually you have to take care of many aspects that are related on your exact needs. I guess that in the interview you are expected to give some details about your way to the solution rather than copying a solution that can be found in Google (http://en.wikipedia.org/wiki/Itoa)
Here are some questions you may want to ask yourself or the interviewer:
Where should the string be located (malloced? passed by the user? static variable?)
Should I support signed numbers?
Should i support floating point?
Should I support other bases rather then 10?
Do we need any input checking?
Is the output string limited in legth?
And so on.
Convert integer to string without access to libraries
Convert the least significant digit to a character first and then proceed to more significant digits.
Normally I'd shift the resulting string into place, yet recursion allows skipping that step with some tight code.
Using neg_a in myitoa_helper() avoids undefined behavior with INT_MIN.
// Return character one past end of character digits.
static char *myitoa_helper(char *dest, int neg_a) {
if (neg_a <= -10) {
dest = myitoa_helper(dest, neg_a / 10);
}
*dest = (char) ('0' - neg_a % 10);
return dest + 1;
}
char *myitoa(char *dest, int a) {
if (a >= 0) {
*myitoa_helper(dest, -a) = '\0';
} else {
*dest = '-';
*myitoa_helper(dest + 1, a) = '\0';
}
return dest;
}
void myitoa_test(int a) {
char s[100];
memset(s, 'x', sizeof s);
printf("%11d <%s>\n", a, myitoa(s, a));
}
Test code & output
#include "limits.h"
#include "stdio.h"
int main(void) {
const int a[] = {INT_MIN, INT_MIN + 1, -42, -1, 0, 1, 2, 9, 10, 99, 100,
INT_MAX - 1, INT_MAX};
for (unsigned i = 0; i < sizeof a / sizeof a[0]; i++) {
myitoa_test(a[i]);
}
return 0;
}
-2147483648 <-2147483648>
-2147483647 <-2147483647>
-42 <-42>
-1 <-1>
0 <0>
1 <1>
2 <2>
9 <9>
10 <10>
99 <99>
100 <100>
2147483646 <2147483646>
2147483647 <2147483647>
The faster the better?
unsigned countDigits(long long x)
{
int i = 1;
while ((x /= 10) && ++i);
return i;
}
unsigned getNumDigits(long long x)
{
x < 0 ? x = -x : 0;
return
x < 10 ? 1 :
x < 100 ? 2 :
x < 1000 ? 3 :
x < 10000 ? 4 :
x < 100000 ? 5 :
x < 1000000 ? 6 :
x < 10000000 ? 7 :
x < 100000000 ? 8 :
x < 1000000000 ? 9 :
x < 10000000000 ? 10 : countDigits(x);
}
#define tochar(x) '0' + x
void tostr(char* dest, long long x)
{
unsigned i = getNumDigits(x);
char negative = x < 0;
if (negative && (*dest = '-') & (x = -x) & i++);
*(dest + i) = 0;
while ((i > negative) && (*(dest + (--i)) = tochar(((x) % 10))) | (x /= 10));
}
If you want to debug, You can split the conditions (instructions) into
lines of code inside the while scopes {}.
I came across this question so I decided to drop by the code I usually use for this:
char *SignedIntToStr(char *Dest, signed int Number, register unsigned char Base) {
if (Base < 2 || Base > 36) {
return (char *)0;
}
register unsigned char Digits = 1;
register unsigned int CurrentPlaceValue = 1;
for (register unsigned int T = Number/Base; T; T /= Base) {
CurrentPlaceValue *= Base;
Digits++;
}
if (!Dest) {
Dest = malloc(Digits+(Number < 0)+1);
}
char *const RDest = Dest;
if (Number < 0) {
Number = -Number;
*Dest = '-';
Dest++;
}
for (register unsigned char i = 0; i < Digits; i++) {
register unsigned char Digit = (Number/CurrentPlaceValue);
Dest[i] = (Digit < 10? '0' : 87)+Digit;
Number %= CurrentPlaceValue;
CurrentPlaceValue /= Base;
}
Dest[Digits] = '\0';
return RDest;
}
#include <stdio.h>
int main(int argc, char *argv[]) {
char String[32];
puts(SignedIntToStr(String, -100, 16));
return 0;
}
This will automatically allocate memory if NULL is passed into Dest. Otherwise it will write to Dest.
Here's a simple approach, but I suspect if you turn this in as-is without understanding and paraphrasing it, your teacher will know you just copied off the net:
char *pru(unsigned x, char *eob)
{
do { *--eob = x%10; } while (x/=10);
return eob;
}
char *pri(int x, char *eob)
{
eob = fmtu(x<0?-x:x, eob);
if (x<0) *--eob='-';
return eob;
}
Various improvements are possible, especially if you want to efficiently support larger-than-word integer sizes up to intmax_t. I'll leave it to you to figure out the way these functions are intended to be called.
Slightly longer than the solution:
static char*
itoa(int n, char s[])
{
int i, sign;
if ((sign = n) < 0)
n = -n;
i = 0;
do
{
s[i++] = n % 10 + '0';
} while ((n /= 10) > 0);
if (sign < 0)
s[i++] = '-';
s[i] = '\0';
reverse(s);
return s;
}
Reverse:
int strlen(const char* str)
{
int i = 0;
while (str != '\0')
{
i++;
str++;
}
return i;
}
static void
reverse(char s[])
{
int i, j;
char c;
for (i = 0, j = strlen(s)-1; i<j; i++, j--) {
c = s[i];
s[i] = s[j];
s[j] = c;
}
}
And although the decision davolno long here are some useful features for beginners. I hope you will be helpful.
This is the shortest function I can think of that:
Correctly handles all signed 32-bit integers including 0, MIN_INT32, MAX_INT32.
Returns a value that can be printed immediatelly, e.g.: printf("%s\n", GetDigits(-123))
Please comment for improvements:
static const char LARGEST_NEGATIVE[] = "-2147483648";
static char* GetDigits(int32_t x) {
char* buffer = (char*) calloc(sizeof(LARGEST_NEGATIVE), 1);
int negative = x < 0;
if (negative) {
if (x + (1 << 31) == 0) { // if x is the largest negative number
memcpy(buffer, LARGEST_NEGATIVE, sizeof(LARGEST_NEGATIVE));
return buffer;
}
x *= -1;
}
// storing digits in reversed order
int length = 0;
do {
buffer[length++] = x % 10 + '0';
x /= 10;
} while (x > 0);
if (negative) {
buffer[length++] = '-'; // appending minus
}
// reversing digits
for (int i = 0; i < length / 2; i++) {
char temp = buffer[i];
buffer[i] = buffer[length-1 - i];
buffer[length-1 - i] = temp;
}
return buffer;
}
//Fixed the answer from [10]
#include <iostream>
void CovertIntToString(unsigned int n1)
{
unsigned int n = INT_MIN;
char buffer[50];
int i = 0;
n = n1;
bool isNeg = n<0;
n1 = isNeg ? -n1 : n1;
while(n1!=0)
{
buffer[i++] = n1%10+'0';
n1=n1/10;
}
if(isNeg)
buffer[i++] = '-';
buffer[i] = '\0';
// Now we must reverse the string
for(int t = 0; t < i/2; t++)
{
buffer[t] ^= buffer[i-t-1];
buffer[i-t-1] ^= buffer[t];
buffer[t] ^= buffer[i-t-1];
}
if(n == 0)
{
buffer[0] = '0';
buffer[1] = '\0';
}
printf("%s", buffer);
}
int main() {
unsigned int x = 4156;
CovertIntToString(x);
return 0;
}
This function converts each digits of number into a char and chars add together
in one stack forming a string. Finally, string is formed from integer.
string convertToString(int num){
string str="";
for(; num>0;){
str+=(num%10+'0');
num/=10;
}
return str;
}