C Extract Infix (char array) and cast to int - c

Given a string/char array e.g :
99+(88-77)*(66/(55-44)+33)
How do I extract the numbers and operators?
I would like to store them into two stacks a and b each containing number and operators only.
I am not sure on the logic, I was thinking of scanning each char in the char array, adding the char (number) into another char, until it meets an operator. Then I go to the char(number) and concatenate the string.
Is there a better way to do this, preferabbly without external libraries?

As pointed out in comments, you can try using strtol for scanning integers from input string. I tried the suggested approach and it seemed to work for me for the provided test case. I haven't tested this for corner cases, but this should give you better idea of what users in comments are saying:
int main() {
char input[30] = "99+(88-77)*(66/(55-44)+33)";
// Initialize Stack Indices
operandStackIndex = 0;
operatorStackIndex = 0;
// Our markers for strtol()
char *pStart = input;
char *pEnd;
long ret;
while ((ret = convertStringToLong(pStart, &pEnd, 10)) > 0) {
operandStack[operandStackIndex++] = ret;
pStart = pEnd;
while (isOperator(*pStart)) { // Check whether character it '+','-','/','(',')','*'..
operatorStack[operatorStackIndex++] = *pStart;
pStart++;
}
}
printf("Operand Stack:\n");
for (int i = operandStackIndex - 1; i >= 0; i--)
printf("%d\n", operandStack[i]);
printf("Operator Stack:\n");
for (int i = operatorStackIndex - 1; i >= 0; i--)
printf("%c\n", operatorStack[i]);
}
Here is simple implementation for convertStringToLong method(alternative to strtol):
long convertStringToLong(char* pStart, char** pEnd, int base) {
long num = 0;
while (isDigit(*pStart)) {
num = num * base + (*pStart - '0');
pStart++;
}
*pEnd = pStart;
return num;
}
When I ran this, I was able to see expected output:
Operand Stack:
33
44
55
66
77
88
99
Operator Stack:
)
+
)
-
(
/
(
*
)
-
(
+

Related

Adding 2 binary strings

I'm passing almost all leetCode tests with this, but not understanding why the output is wrong ("/0") when the input is:
a = "10100000100100110110010000010101111011011001101110111111111101000000101111001110001111100001101"
b = "110101001011101110001111100110001010100001101011101010000011011011001011101111001100000011011110011"
Anyone has an idea to what is not working ?
Thanks
#include <stdio.h>
#include <stdlib.h>
char * sumBinary(long int binary1, long int binary2, char * result);
char * addBinary(char * a, char * b)
{
char * result;
long int a_int;
long int b_int;
a_int = atoi(a);
b_int = atoi(b);
result = malloc(sizeof(*result) * 1000);
if (!result)
return (NULL);
sumBinary(a_int, b_int, result);
return (result);
}
char * sumBinary(long int binary1, long int binary2, char * result)
{
int i;
int t;
int rem;
int sum[1000];
i = 0;
t = 0;
rem = 0;
if ((binary1 == 0) && (binary2 == 0))
{
result[0] = '0';
result[1] = '\0';
}
else
{
while (binary1 != 0 || binary2 != 0)
{
sum[i++] = (binary1 %10 + binary2 % 10 + rem) % 2;
rem = (binary1 %10 + binary2 % 10 + rem) / 2;
binary1 = binary1 / 10;
binary2 = binary2 / 10;
}
if (rem != 0)
sum[i++] = rem;
--i;
while (i >= 0)
{
result[t] = sum[i] + '0';
t++;
i--;
}
result[t] = '\0';
}
return (result);
}
For a start, you should be using atol(3), not atoi(3) if you're using long int. But that's not the main issue here.
atol(3) and atoi(3) expect strings containing decimal numbers, not binary, so that's not going to work well for you. You would need strtol(3), which you can tell to expect a string in ASCII binary. But again, this is not the main issue.
You don't give the question text, but I'm guessing they want you to add two arbitrarily-long ASCII-binary strings, resulting in an ASCII-binary string.
I imagine their expectation, given it's arbitrarily-long, is that you would be working entirely in the string domain. So you'd allocate for a string whose length is two greater than the longer of the two you get as parameters (+1 for the terminal NUL, the other +1 for a potential overflow digit).
Then you start from the end, working back to the start, adding the corresponding digits of the parameter strings, placing the results into the result string starting from its end (allowing for that terminal NUL), adding as if you were doing it by hand.
Don't forget to add a leading zero to the result string, if you don't overflow into that position.
Note that I'm not going to write the code for you. This is either a learning exercise or a test: either way, you need to do the coding so you can learn from it.

How output a numbers with write() (only #include <unistd.h> allowed) [duplicate]

It is possible to convert integer to string in C without sprintf?
There's a nonstandard function:
char *string = itoa(numberToConvert, 10); // assuming you want a base-10 representation
Edit: it seems you want some algorithm to do this. Here's how in base-10:
#include <stdio.h>
#define STRINGIFY(x) #x
#define INTMIN_STR STRINGIFY(INT_MIN)
int main() {
int anInteger = -13765; // or whatever
if (anInteger == INT_MIN) { // handle corner case
puts(INTMIN_STR);
return 0;
}
int flag = 0;
char str[128] = { 0 }; // large enough for an int even on 64-bit
int i = 126;
if (anInteger < 0) {
flag = 1;
anInteger = -anInteger;
}
while (anInteger != 0) { 
str[i--] = (anInteger % 10) + '0';
anInteger /= 10;
}
if (flag) str[i--] = '-';
printf("The number was: %s\n", str + i + 1);
return 0;
}
Here's an example of how it might work. Given a buffer and a size, we'll keep dividing by 10 and fill the buffer with digits. We'll return -1 if there is not enough space in the buffer.
int
integer_to_string(char *buf, size_t bufsize, int n)
{
char *start;
// Handle negative numbers.
//
if (n < 0)
{
if (!bufsize)
return -1;
*buf++ = '-';
bufsize--;
}
// Remember the start of the string... This will come into play
// at the end.
//
start = buf;
do
{
// Handle the current digit.
//
int digit;
if (!bufsize)
return -1;
digit = n % 10;
if (digit < 0)
digit *= -1;
*buf++ = digit + '0';
bufsize--;
n /= 10;
} while (n);
// Terminate the string.
//
if (!bufsize)
return -1;
*buf = 0;
// We wrote the string backwards, i.e. with least significant digits first.
// Now reverse the string.
//
--buf;
while (start < buf)
{
char a = *start;
*start = *buf;
*buf = a;
++start;
--buf;
}
return 0;
}
Unfortunately none of the answers above can really work out in a clean way in a situation where you need to concoct a string of alphanumeric characters.There are really weird cases I've seen, especially in interviews and at work.
The only bad part of the code is that you need to know the bounds of the integer so you can allocate "string" properly.
In spite of C being hailed predictable, it can have weird behaviour in a large system if you get lost in the coding.
The solution below returns a string of the integer representation with a null terminating character. This does not rely on any outer functions and works on negative integers as well!!
#include <stdio.h>
#include <stdlib.h>
void IntegertoString(char * string, int number) {
if(number == 0) { string[0] = '0'; return; };
int divide = 0;
int modResult;
int length = 0;
int isNegative = 0;
int copyOfNumber;
int offset = 0;
copyOfNumber = number;
if( number < 0 ) {
isNegative = 1;
number = 0 - number;
length++;
}
while(copyOfNumber != 0)
{
length++;
copyOfNumber /= 10;
}
for(divide = 0; divide < length; divide++) {
modResult = number % 10;
number = number / 10;
string[length - (divide + 1)] = modResult + '0';
}
if(isNegative) {
string[0] = '-';
}
string[length] = '\0';
}
int main(void) {
char string[10];
int number = -131230;
IntegertoString(string, number);
printf("%s\n", string);
return 0;
}
You can use itoa where available. If it is not available on your platform, the following implementation may be of interest:
https://web.archive.org/web/20130722203238/https://www.student.cs.uwaterloo.ca/~cs350/common/os161-src-html/atoi_8c-source.html
Usage:
char *numberAsString = itoa(integerValue);
UPDATE
Based on the R..'s comments, it may be worth modifying an existing itoa implementation to accept a result buffer from the caller, rather than having itoa allocate and return a buffer.
Such an implementation should accept both a buffer and the length of the buffer, taking care not to write past the end of the caller-provided buffer.
int i = 24344; /*integer*/
char *str = itoa(i);
/*allocates required memory and
then converts integer to string and the address of first byte of memory is returned to str pointer.*/

Why is this modular arithmetic incorrect in my rotate string function?

I am writing a rotate string function in C. The intended behavior is that the strings chars will be rotated using a modulus of the string length, and a key. The function seems to work in the forward direction, but if I specify a negative key, I want the string to rotate in the opposite direction, and this is where the bug exists. For completeness/testing purposes, I will supply the entire program, but below that I will highlight the problem area and explain what I've done to try to debug so far:
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
char *rotate_str(char *mutable_str, int key);
int main(void) {
char str[] = "This is a test.";
char *output = rotate_str(str, -2);
printf("%s\n", output);
return EXIT_SUCCESS;
}
//Bug - negative rotate doesn't work properly - test with -2
char *rotate_str(char *mutable_str, int key) {
assert(mutable_str);
size_t len = strlen(mutable_str);
ssize_t i;
char *output = malloc(len + 1);
assert(output);
ssize_t rotated_index = 0;
for (i = 0; i < len; ++i) {
rotated_index = (i + key) % len; // Get the new index position
output[rotated_index] = mutable_str[i];
}
output[len] = '\0';
return output;
}
The trouble spot is:
for (i = 0; i < len; ++i) {
rotated_index = (i + key) % len; // Get the new index position
output[rotated_index] = mutable_str[i];
}
On the first iteration, i = 0, key = -2, and len = 15. When I compute -2 + 0 % 15 using a calculator (Google in this case), I get 13. However, my C program is making rotated_index = 14 as per my debugger output. So this itself is already a concern.
When I do a positive 2 as key, I get output: t.This is a tes, which is what I'd expect. But when I do the -2 as key, I get output: is is a test. but the expected output is is is a test.Th
Your issue has to do with using the modulo operator with negative numbers.
To start with, you are using size_t which is an unsigned type, but you are trying to put negative numbers into the unsigned type. There is a better explanation why this is an issue here: https://stackoverflow.com/a/39337256/13341069
Handle the key < (len * -1).
char* rotate_str(char *mutable_str, int key)
{
assert(mutable_str);
int len = strlen(mutable_str);
int i;
char *output = (char *)malloc(len + 1);
assert(output);
int remainder;
int rotated_index = 0;
for (i = 0; i < len; ++i)
{
remainder = (i + key) % len; // Get the new index position. range is (-len to +len)
rotated_index = (remainder + len) % len; // Add len to shift value range to [0, +len).
output[rotated_index] = mutable_str[i];
}
output[len] = '\0';
return output;
}

In-place run length decoding?

Given a run length encoded string, say "A3B1C2D1E1", decode the string in-place.
The answer for the encoded string is "AAABCCDE". Assume that the encoded array is large enough to accommodate the decoded string, i.e. you may assume that the array size = MAX[length(encodedstirng),length(decodedstring)].
This does not seem trivial, since merely decoding A3 as 'AAA' will lead to over-writing 'B' of the original string.
Also, one cannot assume that the decoded string is always larger than the encoded string.
Eg: Encoded string - 'A1B1', Decoded string is 'AB'. Any thoughts?
And it will always be a letter-digit pair, i.e. you will not be asked to converted 0515 to 0000055555
If we don't already know, we should scan through first, adding up the digits, in order to calculate the length of the decoded string.
It will always be a letter-digit pair, hence you can delete the 1s from the string without any confusion.
A3B1C2D1E1
becomes
A3BC2DE
Here is some code, in C++, to remove the 1s from the string (O(n) complexity).
// remove 1s
int i = 0; // read from here
int j = 0; // write to here
while(i < str.length) {
assert(j <= i); // optional check
if(str[i] != '1') {
str[j] = str[i];
++ j;
}
++ i;
}
str.resize(j); // to discard the extra space now that we've got our shorter string
Now, this string is guaranteed to be shorter than, or the same length as, the final decoded string. We can't make that claim about the original string, but we can make it about this modified string.
(An optional, trivial, step now is to replace every 2 with the previous letter. A3BCCDE, but we don't need to do that).
Now we can start working from the end. We have already calculated the length of the decoded string, and hence we know exactly where the final character will be. We can simply copy the characters from the end of our short string to their final location.
During this copy process from right-to-left, if we come across a digit, we must make multiple copies of the letter that is just to the left of the digit. You might be worried that this might risk overwriting too much data. But we proved earlier that our encoded string, or any substring thereof, will never be longer than its corresponding decoded string; this means that there will always be enough space.
The following solution is O(n) and in-place. The algorithm should not access memory it shouldn't, both read and write. I did some debugging, and it appears correct to the sample tests I fed it.
High level overview:
Determine the encoded length.
Determine the decoded length by reading all the numbers and summing them up.
End of buffer is MAX(decoded length, encoded length).
Decode the string by starting from the end of the string. Write from the end of the buffer.
Since the decoded length might be greater than the encoded length, the decoded string might not start at the start of the buffer. If needed, correct for this by shifting the string over to the start.
int isDigit (char c) {
return '0' <= c && c <= '9';
}
unsigned int toDigit (char c) {
return c - '0';
}
unsigned int intLen (char * str) {
unsigned int n = 0;
while (isDigit(*str++)) {
++n;
}
return n;
}
unsigned int forwardParseInt (char ** pStr) {
unsigned int n = 0;
char * pChar = *pStr;
while (isDigit(*pChar)) {
n = 10 * n + toDigit(*pChar);
++pChar;
}
*pStr = pChar;
return n;
}
unsigned int backwardParseInt (char ** pStr, char * beginStr) {
unsigned int len, n;
char * pChar = *pStr;
while (pChar != beginStr && isDigit(*pChar)) {
--pChar;
}
++pChar;
len = intLen(pChar);
n = forwardParseInt(&pChar);
*pStr = pChar - 1 - len;
return n;
}
unsigned int encodedSize (char * encoded) {
int encodedLen = 0;
while (*encoded++ != '\0') {
++encodedLen;
}
return encodedLen;
}
unsigned int decodedSize (char * encoded) {
int decodedLen = 0;
while (*encoded++ != '\0') {
decodedLen += forwardParseInt(&encoded);
}
return decodedLen;
}
void shift (char * str, int n) {
do {
str[n] = *str;
} while (*str++ != '\0');
}
unsigned int max (unsigned int x, unsigned int y) {
return x > y ? x : y;
}
void decode (char * encodedBegin) {
int shiftAmount;
unsigned int eSize = encodedSize(encodedBegin);
unsigned int dSize = decodedSize(encodedBegin);
int writeOverflowed = 0;
char * read = encodedBegin + eSize - 1;
char * write = encodedBegin + max(eSize, dSize);
*write-- = '\0';
while (read != encodedBegin) {
unsigned int i;
unsigned int n = backwardParseInt(&read, encodedBegin);
char c = *read;
for (i = 0; i < n; ++i) {
*write = c;
if (write != encodedBegin) {
write--;
}
else {
writeOverflowed = 1;
}
}
if (read != encodedBegin) {
read--;
}
}
if (!writeOverflowed) {
write++;
}
shiftAmount = encodedBegin - write;
if (write != encodedBegin) {
shift(write, shiftAmount);
}
return;
}
int main (int argc, char ** argv) {
//char buff[256] = { "!!!A33B1C2D1E1\0!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" };
char buff[256] = { "!!!A2B12C1\0!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" };
//char buff[256] = { "!!!A1B1C1\0!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" };
char * str = buff + 3;
//char buff[256] = { "A1B1" };
//char * str = buff;
decode(str);
return 0;
}
This is a very vague question, though it's not particularly difficult if you think about it. As you say, decoding A3 as AAA and just writing it in place will overwrite the chars B and 1, so why not just move those farther along the array first?
For instance, once you've read A3, you know that you need to make space for one extra character, if it was A4 you'd need two, and so on. To achieve this you'd find the end of the string in the array (do this upfront and store it's index).
Then loop though, moving the characters to their new slots:
To start: A|3|B|1|C|2|||||||
Have a variable called end storing the index 5, i.e. the last, non-blank, entry.
You'd read in the first pair, using a variable called cursor to store your current position - so after reading in the A and the 3 it would be set to 1 (the slot with the 3).
Pseudocode for the move:
var n = array[cursor] - 2; // n = 1, the 3 from A3, and then minus 2 to allow for the pair.
for(i = end; i > cursor; i++)
{
array[i + n] = array[i];
}
This would leave you with:
A|3|A|3|B|1|C|2|||||
Now the A is there once already, so now you want to write n + 1 A's starting at the index stored in cursor:
for(i = cursor; i < cursor + n + 1; i++)
{
array[i] = array[cursor - 1];
}
// increment the cursor afterwards!
cursor += n + 1;
Giving:
A|A|A|A|B|1|C|2|||||
Then you're pointing at the start of the next pair of values, ready to go again. I realise there are some holes in this answer, though that is intentional as it's an interview question! For instance, in the edge cases you specified A1B1, you'll need a different loop to move subsequent characters backwards rather than forwards.
Another O(n^2) solution follows.
Given that there is no limit on the complexity of the answer, this simple solution seems to work perfectly.
while ( there is an expandable element ):
expand that element
adjust (shift) all of the elements on the right side of the expanded element
Where:
Free space size is the number of empty elements left in the array.
An expandable element is an element that:
expanded size - encoded size <= free space size
The point is that in the process of reaching from the run-length code to the expanded string, at each step, there is at least
one element that can be expanded (easy to prove).

How to convert an arbitrary large integer from base 10 to base 16?

The program requires an input of an arbitrary large unsigned integer which is expressed as one string in base 10. The outputs is another string that expresses the integer in base 16.
For example, the input is "1234567890987654321234567890987654321234567890987654321",
and the output shall be "CE3B5A137DD015278E09864703E4FF9952FF6B62C1CB1"
The faster the algorithm the better.
It will be very easy if the input is limited within 32-bit or 64-bit integer; for example, the following code can do the conversion:
#define MAX_BUFFER 16
char hex[] = "0123456789ABCDEF";
char* dec2hex(unsigned input) {
char buff[MAX_BUFFER];
int i = 0, j = 0;
char* output;
if (input == 0) {
buff[0] = hex[0];
i = 1;
} else {
while (input) {
buff[i++] = hex[input % 16];
input = input / 16;
}
}
output = malloc((i + 1) * sizeof(char));
if (!output)
return NULL;
while (i > 0) {
output[j++] = buff[--i];
}
output[j] = '\0';
return output;
}
The real challenging part is the "arbitrary large" unsigned integer. I have googled but most of them are talking about the conversion within 32-bit or 64-bit. No luck is found.
Can anyone give any hit or any link that can be read on?
Thanks in advance.
Edit This is an interview question I encountered recently. Can anyone briefly explain how to solve this problem? I know there is a gmp library and I utilized it before; however as an interview question it requires not using external library.
Allocate an array of integers, number of elements is equal to the length of the input string. Initialize the array to all 0s.
This array of integers will store values in base 16.
Add the decimal digits from the input string to the end of the array. Mulitply existing values by 10 add carryover, store new value in array, new carryover value is newvalue div 16.
carryover = digit;
for (i = (nElements-1); i >= 0; i--)
{
newVal = array[index] * 10) + carryover;
array[index] = newval % 16;
carryover = newval / 16;
}
print array, start at 0th entry and skip leading 0s.
Here's some code that will work. No doubt there are probably a few optimizations that could be made. But this should suffice as a quick and dirty solution:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "sys/types.h"
char HexChar [16] = { '0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
static int * initHexArray (char * pDecStr, int * pnElements);
static void addDecValue (int * pMyArray, int nElements, int value);
static void printHexArray (int * pHexArray, int nElements);
static void
addDecValue (int * pHexArray, int nElements, int value)
{
int carryover = value;
int tmp = 0;
int i;
/* start at the bottom of the array and work towards the top
*
* multiply the existing array value by 10, then add new value.
* carry over remainder as you work back towards the top of the array
*/
for (i = (nElements-1); (i >= 0); i--)
{
tmp = (pHexArray[i] * 10) + carryover;
pHexArray[i] = tmp % 16;
carryover = tmp / 16;
}
}
static int *
initHexArray (char * pDecStr, int * pnElements)
{
int * pArray = NULL;
int lenDecStr = strlen (pDecStr);
int i;
/* allocate an array of integer values to store intermediate results
* only need as many as the input string as going from base 10 to
* base 16 will never result in a larger number of digits, but for values
* less than "16" will use the same number
*/
pArray = (int *) calloc (lenDecStr, sizeof (int));
for (i = 0; i < lenDecStr; i++)
{
addDecValue (pArray, lenDecStr, pDecStr[i] - '0');
}
*pnElements = lenDecStr;
return (pArray);
}
static void
printHexArray (int * pHexArray, int nElements)
{
int start = 0;
int i;
/* skip all the leading 0s */
while ((pHexArray[start] == 0) && (start < (nElements-1)))
{
start++;
}
for (i = start; i < nElements; i++)
{
printf ("%c", HexChar[pHexArray[i]]);
}
printf ("\n");
}
int
main (int argc, char * argv[])
{
int i;
int * pMyArray = NULL;
int nElements;
if (argc < 2)
{
printf ("Usage: %s decimalString\n", argv[0]);
return (-1);
}
pMyArray = initHexArray (argv[1], &nElements);
printHexArray (pMyArray, nElements);
if (pMyArray != NULL)
free (pMyArray);
return (0);
}
I have written an article which describes a simple solution in Python which can be used to transfrom a series of numbers from and to arbitrary number bases. I've originally implemented the solution in C, and I didn't want a dependency to an external library. I think you should be able to rewrite the very easy Python code in C or whatever you like.
Here is the Python code:
import math
import string
def incNumberByValue(digits, base, value):
# The initial overflow is the 'value' to add to the number.
overflow = value
# Traverse list of digits in reverse order.
for i in reversed(xrange(len(digits))):
# If there is no overflow we can stop overflow propagation to next higher digit(s).
if not overflow:
return
sum = digits[i] + overflow
digits[i] = sum % base
overflow = sum / base
def multNumberByValue(digits, base, value):
overflow = 0
# Traverse list of digits in reverse order.
for i in reversed(xrange(len(digits))):
tmp = (digits[i] * value) + overflow
digits[i] = tmp % base
overflow = tmp / base
def convertNumber(srcDigits, srcBase, destDigits, destBase):
for srcDigit in srcDigits:
multNumberByValue(destDigits, destBase, srcBase)
incNumberByValue(destDigits, destBase, srcDigit)
def withoutLeadingZeros(digits):
for i in xrange(len(digits)):
if digits[i] != 0:
break
return digits[i:]
def convertNumberExt(srcDigits, srcBase, destBase):
# Generate a list of zero's which is long enough to hold the destination number.
destDigits = [0] * int(math.ceil(len(srcDigits)*math.log(srcBase)/math.log(destBase)))
# Do conversion.
convertNumber(srcDigits, srcBase, destDigits, destBase)
# Return result (without leading zeros).
return withoutLeadingZeros(destDigits)
# Example: Convert base 10 to base 16
base10 = [int(c) for c in '1234567890987654321234567890987654321234567890987654321']
base16 = convertNumberExt(base10, 10, 16)
# Output list of base 16 digits as HEX string.
hexDigits = '0123456789ABCDEF'
string.join((hexDigits[n] for n in base16), '')
The real challenging part is the "arbitrary large" unsigned integer.
Have you tried using GNU MP Bignum library?
Unix dc is able to do base conversions on arbitrary large integers. Open BSD source code is available here.
Here's a BigInt library:
http://www.codeproject.com/KB/cs/BigInt.aspx?msg=3038072#xx3038072xx
No idea if it works, but it's the first one I found with Google. It appears to have functions to parse and format big integers, so they may support different bases too.
Edit: Ahh, you're using C, my mistake. But you may be able to pick up ideas from the code, or someone using .NET may have the same question, so I'll leave this here.
You can try this arbitrary length input C99 base_convert (between 2 and 62) function :
#include <stdlib.h>
#include <string.h>
static char *base_convert(const char * str, const int base_in, const int base_out) {
static const char *alphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
size_t a, b, c = 1, d;
char *s = malloc(c + 1);
strcpy(s, "0");
for (; *str; ++str) {
for (a = (char*)memchr(alphabet, *str, base_out) - alphabet, b = c; b;) {
d = ((char *) memchr(alphabet, s[--b], base_out) - alphabet) * base_in + a;
s[b] = alphabet[d % base_out];
a = d / base_out;
}
for (; a; s = realloc(s, ++c + 1), memmove(s + 1, s, c), *s = alphabet[a % base_out], a /= base_out);
}
return s;
}
Try it Online - Example usage :
#include <stdio.h>
int main() {
char * res = base_convert("12345678909876543212345678909876"
"54321234567890987654321", 10, 16);
puts(res);
free(res);
// print CE3B5A137DD015278E09864703E4FF9952FF6B62C1CB1
}
Example output :
'11100100100011101011001001110110001101001001100010100001111011110011000010'
from base 2 to base 58 is 'BaseConvert62'.
'NdN2mbALtnCHH' from base 60 to base 59 is 'StackOverflow'.
Tested with your example and Fibonacci(1500000).
Thank You.
Python:
>>> from string import upper
>>> input = "1234567890987654321234567890987654321234567890987654321"
>>> output = upper(hex(int(input)))[2:-1]
>>> print output
CE3B5A137DD015278E09864703E4FF9952FF6B62C1CB1
Here is the above-mentioned algorithm implemented in javascript:
function addDecValue(hexArray, value) {
let carryover = value;
for (let i = (hexArray.length - 1); i >= 0; i--) {
let rawDigit = ((hexArray[i] || 0) * 10) + carryover;
hexArray[i] = rawDigit % 16;
carryover = Math.floor(rawDigit / 16);
}
}
function toHexArray(decimalString) {
let hexArray = new Array(decimalString.length);
for (let i = 0; i < decimalString.length; i++) {
addDecValue(hexArray, Number(decimalString.charAt(i)));
}
return hexArray;
}
function toHexString(hexArray) {
const hexDigits = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'];
let result = '';
for (let i = 0; i < hexArray.length; i++) {
if (result === '' && hexArray[i] === 0) continue;
result += hexDigits[hexArray[i]];
}
return result
}
toHexString(toHexArray('1234567890987654321234567890987654321234567890987654321'));

Resources