Converting Ascii to binary in C - c

So here is my code
void ascToBinary(int character, int *ones)
{
if(character == 1)
{
printf("1");
*ones+=1;
return;
}
else
{
if((character%2) == 0)
{
printf("0");
character = character/2;
}
else
{
printf("1");
character = character/2;
*ones+=1;
}
binaryPrinter(character, ones);
}
}
Can anyone try to help me out on where something is wrong here. It compiles fine and does some ascii letters correct. If you try an 'e' though it will print out '1010011' instead of the correct binary.
All help appreciated Thanks Guys.

You print the results in the wrong order. The correct output is '1100101'. You can flip it like this:
void ascToBinary(int character, int *ones)
{
if(character == 1)
{
printf("1");
*ones+=1;
return;
}
else
{
char out;
if((character%2) == 0)
{
out = '0';
character = character/2;
}
else
{
out = '1';
character = character/2;
*ones+=1;
}
ascToBinary(character, ones);
putchar (out);
}
}

You're printing the bits of the character in reverse, since you start printing with the least significant bit.
Therefore the expected value for your function, when called on e is 1010011 which is exactly what you get.

Converting an Integer to binary:
Version 1 - Will print out the binary result
void to_bin(int value)
{
char base_range[] = "01";
if (value >= 2) {
to_bin(value / 2);
}
printf("%c", base_range[value % 2]);
}
Version 2 - Will return a string with binary result
void to_bin_str(int value, char *res, int *p)
{
char base_range[] = "01";
if (value >= 2) {
to_bin_str(value / 2, res, p);
}
res[(*p)++] = base_range[value % 2];
}
char* convert(int value)
{
char* result = (char*)malloc(sizeof(char) * 32);
int i = 0;
to_bin_str(value, result, &i);
result[i] = '\0';
return (result);
}
Version 3 - Will convert to any base from 2 to 16, handles negatives for base 10
void to_base(int value, int base, char *res, int *p)
{
char base_range[] = "0123456789ABCDEF";
if (value >= base || value <= -base) {
to_base(value / base, base, res, p);
}
res[(*p)++] = base_range[abs(value % base)];
}
char* convert(int value, int base)
{
char *result = (char*)malloc(sizeof(char) * 32);
int i = 0;
if (base < 2 || base > 16)
return (NULL);
if (base == 10 && value < 0)
result[i++] = '-';
to_base(value, base, result, &i);
result[i] = '\0';
return (result);
}

Related

addition, subtraction, and comparison of large numbers of any base between 2 and 36

I need to put some additional code for subtraction and comparison.
and i put (bool larger) for comparison.
When i run this and input 1 '<' 2 to compare, it says "Invalid operation: < ".
and also for the 1 = 1, it says "Invalid operation: = ".
but the result need to be "Result: false" and "Result: True"
I have no idea about it. I know the code is long but not so complicated. Please get me some hint if you can.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "bignum_math.h"
/*
* Returns true if the given char is a digit from 0 to 9
*/
bool is_digit(char c) {
return c >= '0' && c <= '9';
}
/*
* Returns true if lower alphabetic character
*/
bool is_lower_alphabetic(char c) {
return c >= 'a' && c <= 'z';
}
/*
* Returns true if upper alphabetic character
*/
bool is_upper_alphabetic(char c) {
return c >= 'A' && c <= 'Z';
}
/*
* Convert a string to an integer
* returns 0 if it cannot be converted.
*/
int string_to_integer(char* input) {
int result = 0;
int length = strlen(input);
int num_digits = length;
int sign = 1;
int i = 0;
int factor = 1;
if (input[0] == '-') {
num_digits--;
sign = -1;
}
for (i = 0; i < num_digits; i++, length--) {
if (!is_digit(input[length-1])) {
return 0;
}
if (i > 0) factor*=10;
result += (input[length-1] - '0') * factor;
}
return sign * result;
}
/*
* Returns true if the given base is valid.
* that is: integers between 2 and 36
*/
bool valid_base(int base) {
if(!(base >= 2 && base <= 36)) {
return false;
}
return true;
}
/*
* TODO
* Returns true if the given string (char array) is a valid input,
* that is: digits 0-9, letters A-Z, a-z
* and it should not violate the given base and should not handle negative numbers
*/
bool valid_input(char* input, int base) {
/*
* check for valid base and if negative
*/
if (!valid_base(base) || input[0]=='-') {
return false;
}
else {
int len = strlen(input);
int i;
for (i =0; i< len; i++){
/*
* check if the input string is a digit/letter
*/
if (!(is_digit(input[i]) || is_lower_alphabetic(input[i]) || is_upper_alphabetic(input[i]))){
return false;
}
/*
* if the int excesses the base?
*/
else if (is_digit(input[i])){
if (input[i]-'0'>=base){ //convert char to int and compare with the base
return false;
}
}
/*
*or if the letter excesses the base?
*/
else if (is_lower_alphabetic(input[i])){
if (input[i]-'a'+10 >=base){
return false;
}
}
else if (is_upper_alphabetic(input[i])){
if (input[i] - 'A' + 10 >=base) {
return false;
}
}
}
return true;
}
}
/*
* converts from an array of characters (string) to an array of integers
*/
int* string_to_integer_array(char* str) {
int* result;
int i, str_offset = 0;
result = malloc((strlen(str) + 1) * sizeof(int));
result[strlen(str)] = -1;
for(i = str_offset; str[i] != '\0'; i++) {
if(is_digit(str[i])) {
result[i - str_offset] = str[i] - '0';
} else if (is_lower_alphabetic(str[i])) {
result[i - str_offset] = str[i] - 'a' + 10;
} else if (is_upper_alphabetic(str[i])) {
result[i - str_offset] = str[i] - 'A' + 10;
} else {
printf("I don't know how got to this point!\n");
}
}
return result;
}
/*
* finds the length of a bignum...
* simply traverses the bignum until a negative number is found.
*/
int bignum_length(int* num) {
int len = 0;
while(num[len] >= 0) { len++; }
return len;
}
/*
* TODO
* Prints out a bignum using digits and upper-case characters
* Current behavior: prints integers
* Expected behavior: prints characters
*/
void bignum_print(int* num) {
int i;
if(num == NULL) { return; }
/* Handle negative numbers as you want
* let the last digit be -2 if negative
* */
i = bignum_length(num);
if (num[i]==-2){
printf("-");
}
/* Then, print each digit */
for(i = 0; num[i] >= 0; i++) {
if (num[i]<=9){
printf("%d", num[i]);
}
else if (num[i]>9){
char digit = num[i]+'A'-10;
printf("%c", digit);
}
}
printf("\n");
}
/*
* Helper for reversing the result that we built backward.
* see add(...) below
*/
void reverse(int* num) {
int i, len = bignum_length(num);
for(i = 0; i < len/2; i++) {
int temp = num[i];
num[i] = num[len-i-1];
num[len-i-1] = temp;
}
}
/*
* used to add two numbers with the same sign
* GIVEN FOR GUIDANCE
*/
int* add(int* input1, int* input2, int base) {
int len1 = bignum_length(input1);
int len2 = bignum_length(input2);
int resultlength = ((len1 > len2)? len1 : len2) + 2;
int* result = (int*) malloc (sizeof(int) * resultlength);
int r = 0;
int carry = 0;
int sign = input1[len1];
len1--;
len2--;
while(len1 >= 0 || len2 >= 0) {
int num1 = (len1 >= 0)? input1[len1] : 0;
int num2 = (len2 >= 0)? input2[len2] : 0;
result[r] = (num1 + num2 + carry) % base;
carry = (num1 + num2 + carry) / base;
len1--;
len2--;
r++;
}
if(carry > 0) { result[r] = carry; r++; }
result[r] = sign;
reverse(result);
return result;
}
/*
* helper function for subtract
* determine which number is larger of two positive numbers
*/
bool larger(int* input1, int* input2){
int len1 = bignum_length(input1);
int len2 = bignum_length(input2);
if (len1<=len2){
if (len1<len2){ //if input1 has less digit than input2
return false;
}
int i;
for (i =0; i < len1; i++ ){//they have the same length
if (input1[i]<input2[i]){ //if the same digit in input1 is smaller than that in input2
return false;
}
}
}
return true; //else input1 is indeed larger than/equal input2 (longer or every digit is no less than that in input2
}
/*
* helper function for subtract
* subtract from the larger
*/
int* subtractLarger(int* input1, int* input2, int base){ //input1 is larger or equal than/to input2 and both positive
int len1 = bignum_length(input1);
int len2 = bignum_length(input2);
int resultlength = ((len1 > len2) ? len1 : len2) + 2;
int *result = (int *) malloc(sizeof(int) * resultlength);
int r = 0;
int carry = 0;
int sign = -1;
len1--;
len2--;
while(len1 >= 0 ) {
int num1 = (len1 >= 0)? input1[len1]-carry : 0;
int num2 = (len2 >= 0)? input2[len2] : 0;
if (num1>=num2){
result[r] = (num1-num2);
carry = 0;
}
else {
result[r]= num1+base-num2;
carry = 1;
}
len1--;
len2--;
r++;
}
if (result[r-1]==0){
result[r-1] = sign;
}
else {
result[r] = sign;
}
reverse(result);
return result;
}
/*
* used to subtract two numbers with the same sign
*/
int* subtract (int* input1, int* input2, int base) {
if (larger(input1,input2)){
return subtractLarger(input1, input2, base);
}
else {
int* res = subtractLarger(input2, input1, base); //exchange input1 and input2, note the result is negative
int sign = -2; //negative result
res[bignum_length(res)] = sign;
return res;
}
}
/*
* TODO
* This function is where you will write the code that performs the heavy lifting,
* actually performing the calculations on input1 and input2.
* Return your result as an array of integers.
* HINT: For better code structure, use helper functions.
*/
int* perform_math(int* input1, int* input2, char op, int base) {
/*
* this code initializes result to be large enough to hold all necessary digits.
* if you don't use all of its digits, just put a -1 at the end of the number.
* you may omit this result array and create your own.
*/
int resultlength = bignum_length(input1) + bignum_length(input2) + 2;
int* result = (int*) malloc (sizeof(int) * resultlength);
if(op == '+') {
return add(input1, input2, base);
}
else if (op == '-'){
return subtract(input1, input2, base);
}
}
/*
* Print to "stderr" and exit program
*/
void print_usage(char* name) {
fprintf(stderr, "----------------------------------------------------\n");
fprintf(stderr, "Usage: %s base input1 operation input2\n", name);
fprintf(stderr, "base must be number between 2 and 36, inclusive\n");
fprintf(stderr, "input1 and input2 are arbitrary-length integers\n");
fprintf(stderr, "Two operations are allowed '+' and '-'\n");
fprintf(stderr, "----------------------------------------------------\n");
exit(1);
}
/*
* MAIN: Run the program and tests your functions.
* sample command: ./bignum 4 12 + 13
* Result: 31
*/
int main(int argc, char** argv) {
int input_base;
int* input1;
int* input2;
int* result;
if(argc != 5) {
print_usage(argv[0]);
}
input_base = string_to_integer(argv[1]);
if(!valid_base(input_base)) {
fprintf(stderr, "Invalid base: %s\n", argv[1]);
print_usage(argv[0]);
}
if(!valid_input(argv[2], input_base)) {
fprintf(stderr, "Invalid input1: %s\n", argv[2]);
print_usage(argv[0]);
}
if(!valid_input(argv[4], input_base)) {
fprintf(stderr, "Invalid input2: %s\n", argv[4]);
print_usage(argv[0]);
}
if(argv[3][0] != '-' && argv[3][0] != '+') {
fprintf(stderr, "Invalid operation: %s\n", argv[3]);
print_usage(argv[0]);
}
input1 = string_to_integer_array(argv[2]);
input2 = string_to_integer_array(argv[4]);
result = perform_math(input1, input2, argv[3][0], input_base);
printf("Result: ");
bignum_print(result);
printf("\n");
exit(0);
}
Line 344:
void print_usage(char* name) {
fprintf(stderr, "----------------------------------------------------\n");
fprintf(stderr, "Usage: %s base input1 operation input2\n", name);
fprintf(stderr, "base must be number between 2 and 36, inclusive\n");
fprintf(stderr, "input1 and input2 are arbitrary-length integers\n");
fprintf(stderr, "Two operations are allowed '+' and '-'\n");
fprintf(stderr, "----------------------------------------------------\n");
exit(1);
}
Line 390:
if(argv[3][0] != '-' && argv[3][0] != '+') {
fprintf(stderr, "Invalid operation: %s\n", argv[3]);
print_usage(argv[0]);
}
Now guess why it says "Invalid operation:"...

Converting a multidigital integer from a char array into an integer

I've build a small program which would convert the given char array to an integer:
#include <stdio.h>
int char_to_int(char* value);
int main(int argc, char* argv[])
{
if (argc != 2)
{
printf("Illegal argument count!");
return 1;
}
printf("As char array: %s\n", argv[1]);
printf("As integer: %i", char_to_int(argv[1]));
return 0;
}
int char_to_int(char* value)
{
return *value - '0';
}
The problem is that when I enter a multidigital number the integer only consists of a single digit number, which is logical, but I have no idea on how to rewrite the code. And I also have no idea why only the first char gets converted.
I know this is pretty basic stuff, but I'd like to know how to implement it correctly.
I'd also like to avoid using the ato() function in the STL.
Reworked code with error handling:
#include <stdio.h>
int char_to_int(char* value);
int illegal_conversion = 0;
int main(int argc, char* argv[])
{
if (argc != 2)
{
printf("Illegal argument count!");
return 1;
}
int result = char_to_int(argv[1]);
if (illegal_conversion)
{
printf("Illegal arguments");
return 1;
}
printf("As char array: %s\n", argv[1]);
printf("As integer: %i", result);
return 0;
}
int char_to_int(char* value)
{
int result = 0;
int negative_integer = 0;
while (*value)
{
if (*value == 43)
{
*value++;
continue;
}
else if (*value == 45)
{
*value++;
negative_integer = 1;
continue;
}
else if (*value < 48 || *value > 57)
{
illegal_conversion = 1;
return 1;
}
result *= 10;
result += *value++ - '0';
}
if (negative_integer)
result *= -1;
return result;
}
Because you only return the numerical value of the first digit.
This function converts but without any checks and it works only for the valid non negative decimal numbers, otherwise it is an UB
int char_to_int(char* value)
{
int result = 0;
while(*value)
{
result *= 10;
result += *value++ - '0';
}
return result;
}
or a bit smarter one:
int char_to_int(char* value, int *res)
{
int sign = 0;
int status = 0;
int result = 0;
if (value != NULL && res != NULL)
{
while (*value)
{
switch (*value)
{
case '+':
case '-':
if (sign) status = -1;
sign = *value == '-' ? -1 : 1;
break;
default:
if (!isdigit(*value)) status = -1;
if(!sign) sign = 1;
*result *= 10;
*result += *value - '0';
break;
}
value++;
if (status) break;
}
if(!status)*res = sign * result;
}
return status;
}
Reworked code incurs undefined behavior in a case where it can be avoided.
Example with (2's complement) int
char buf[100];
sprintf(buf, "%d", INT_MIN); // e.g. -2147483648
int y = char_to_int(buf);
The while loop in char_to_int() eventually executes
// before
// result: 214748364
// *value: '8'
result += *value++ - '0';
// after
// `int` overflow, this is undefined behavior
To avoid, rather than accumulate the answer as a positive value and then later negate if '-' found, accumulate the answer as a negative value and then later negate if '-' not found. This is less intuitive, yet avoids UB.
Using unsigned as an extended range is another way, yet that fails on rare machines where INT_MAX == UINT_MAX. I have only encountered such a machine once and that for for its widest integer.
Other improvements noted in comments.
#include <ctype.h>
int char_to_int(const char *value) { // use const
int sign = *value;
if (sign == '-' || sign == '+') {
value++;
}
bool digit_found = false;
int result = 0;
// while (isdigit(*value)) { // avoid this as it is UB when *value < 0, not EOF
while (isdigit((unsigned char) *value)) { // or (*value >= '0' && *value <= '9')
result *= 10;
result -= *value - '0'; // notice the `-=`
value++;
digit_found = true;
}
if (sign != '-') {
result = -result;
}
// Error detection
if (*value != '\0' || !digit_found) {
; //Handle_Invalid_String();
}
return result;
}
Note: overflow detection not included.

How do you return a string array inside a recursive function or copy it?

I have a problem at the add2_recur function. I am trying to add up a single character digit within a string. But I do not know how to return a string to my main function so I can print out the result. I try using function pointer but i only return the first value of the string.
Any suggestion on how to do this would be helpful.
//check if string is valid
int digcheck_helper(char *theno, int start, int length) {
int charToInt = *(theno+start);
if(!((charToInt >= 48) &&(charToInt <= 57)))
return 0;
if(length == 0)
return 1;
return digcheck_helper(theno,start+1,length-1);
}
int digcheck(char *str, int start, int length) {
return digcheck_helper(string,start,length);
}
/**********************
****add recursive function**/
void add2_recur(char *num1, char *num2, int start, int carryDig) {
int singleChar1 = *(num1 + start), singleChar2 = *(num2 + start);
char *str = (char*) malloc(strlen(num1) + 2);
sum = singleChar1 + singleChar - 96;
if(carryDig == 1)
sum = sum + 1;
if(start < strlen(num1)) {
if(sum >= 10) {
sum = sum - 10;
str[start] = sum + 48;
carryDig = 1;
printf("sum of single digit is: %c\n", str[start]);
}
else if( sum < 10) {
str[start] = sum + 48;
carryDig = 0;
printf("sum of single digit is: %c\n", str[start]);
}
add2_recur(num1,num2,start+1,carryDig);
}
else if ((start == strlen(num1)) && (carryDig ==1)){
str[start+1] = 48;
printf("sum of single digit is: %c\n", str[start+1]);
}
}
void add2(char *n1, char *n2) {
add2_recur(n1,n2,0,0)
}
/*******************/
int main() {
char string1[20000], string2[20000], revStr1[20000], revStr2[20000];
int digit_1, digit_2, i;
printf("Enter first number >");
fgets(string1,20000,stdin);
string1[strlen(string1)-1] = '\0';
digit_1 = digcheck(string1,0,strlen(string1)-1);
//Check if string is valid integer
if(digit_1 = 0)
printf("This number is invalid\n");
else{
printf("Enter second number >");
fgets(string2,2000,stdin);
string2[strlen(string2)-1] = '\0';
digit_2 = digcheck(string2,0,strlen(string2-1);
if(digit_2 == 0)
printf("This number is invalid\n");
else
printf("1st num is %s\n2st num is %s\n", string1, string2);
}
// reverse string
for(i=0;i<strlen(string1);i++)
revStr1[i] = string1[(strlen(string1)-1) - i];
for(i=0;i,strlen(string2);i++)
revStr2[i] = string2[(strlen(string2) -1) - i];
// compare string and pass to add2
if(strlen(revStr1) < strlen(revStr2)) {
for(i = strlen(revStr1); i < strlen(revStr2); i++)
revStr1[i] = '0';
add2(revStr1,revStr2);
}
else if(strlen(revStr2) < strlen(revStr1)) {
for(i = strlen(revStr2); i < strlen(revStr1); i++)
revStr2[i] = '0';
add2(revStr1,revStr2);
}
else
add2(revStr1,revStr2);
return 0;
}
In C something like this is typically achieved by not returning the actual string. Instead you can just work with a pointer to a buffer passed to you. Use the actual return value to report status messages instead.
To not spoil the actual task for you, let's define a simple recursive function that will return a string with all non-alphanumerical characters being stripped:
#include <stdio.h>
#include <string.h>
int strip_stuff_rec(const char *input, char *output, unsigned int offset_input, unsigned offset_output) {
// Retrieve the character and move the offset
const char c = input[offset_input++];
if (c == '\0') { // Terminator; we're done!
// Terminate the output string
output[offset_output] = '\0';
return 1; // Signal success
}
// Character is alphanumeric?
if (isalnum(c)) {
// Append the character to our result and move the offset
output[offset_output++] = c;
}
// To have an error case, let's just pretend the string must not include #!
if (c == '#') {
return 0; // Signal an error
}
// Now handle the next position
return strip_stuff_rec(input, output, offset_input, offset_output);
}
int strip_stuff(const char *input, char *output) {
// Reset the output
output[0] = '\0';
// Start the recursive calls
return strip_stuff_rec(input, output, 0, 0);
}
int main(int argc, char **argv) {
// First let's set some input string
const char *input = "Hello World! -- I've had a wonderful day!";
// And we'll need a buffer for our result
char result[256];
// Now call the function and check the return value to determine
// whether it's been successful.
if (strip_stuff(input, result) == 0) {
printf("Some error happened!\n");
}
else {
printf("The stripped string is '%s'.\n", result);
}
}
this function:
void add2(char *n1, char *n2)
{
add2_recur(n1,n2,0,0)
}
this function has a couple of problems.
1) it will not compile because the statement that calls add2-recur()
is missing a trailing ';'
2) this function is not needed as add2_recur can be called directly
3) this is expected to add two numbers together ..
How is it to return the result?
It (probably) should be more like:
void add2(char *n1, char *n2, char *sum)
{
strcpy(sum, add2_recur(n1,n2,0,0) );
}
ok, i fix the code by creating a pointer function and storing the value into the str array by using malloc. I commented out the code. But it still only return the first element of the array to the main function from the heap. How do i get it to return the whole array?
//check if string is valid
int digcheck_helper(char *theno, int start, int length) {
int charToInt = *(theno+start);
if(!((charToInt >= 48) &&(charToInt <= 57)))
return 0;
if(length == 0)
return 1;
return digcheck_helper(theno,start+1,length-1);
}
int digcheck(char *str, int start, int length) {
return digcheck_helper(string,start,length);
}
/**********************
****add recursive function**/
char *add2_recur(char *num1, char *num2, int start, int carryDig) {
int singleChar1 = *(num1 + start), singleChar2 = *(num2 + start);
char *str = (char*) malloc(strlen(num1) + 2), sum;
sum = singleChar1 + singleChar - 96;
if(carryDig == 1)
sum = sum + 1;
if(start < strlen(num1)) {
if(sum >= 10) {
sum = sum - 10;
str[start] = sum + 48; //store value in each element of an array
carryDig = 1;
printf("sum of single digit is: %c\n", str[start]);
}
else if( sum < 10) {
str[start] = sum + 48; //store value in each element of an array
carryDig = 0;
printf("sum of single digit is: %c\n", str[start]);
}
add2_recur(num1,num2,start+1,carryDig);
}
else if ((start == strlen(num1)) && (carryDig ==1)){
str[start+1] = 49; // store value in each element of an array
printf("sum of single digit is: %c\n", str[start+1]);
}
return str;
}
/*******************/
int main() {
char string1[20000], string2[20000], revStr1[20000], revStr2[20000], *addResult;
int digit_1, digit_2, i;
printf("Enter first number >");
fgets(string1,20000,stdin);
string1[strlen(string1)-1] = '\0';
digit_1 = digcheck(string1,0,strlen(string1)-1);
//Check if string is valid integer
if(digit_1 = 0)
printf("This number is invalid\n");
else{
printf("Enter second number >");
fgets(string2,2000,stdin);
string2[strlen(string2)-1] = '\0';
digit_2 = digcheck(string2,0,strlen(string2-1);
if(digit_2 == 0)
printf("This number is invalid\n");
else
printf("1st num is %s\n2st num is %s\n", string1, string2);
}
// reverse string
for(i=0;i<strlen(string1);i++)
revStr1[i] = string1[(strlen(string1)-1) - i];
for(i=0;i,strlen(string2);i++)
revStr2[i] = string2[(strlen(string2) -1) - i];
// compare string and pass to add2
if(strlen(revStr1) < strlen(revStr2)) {
for(i = strlen(revStr1); i < strlen(revStr2); i++)
revStr1[i] = '0';
add2(revStr1,revStr2);
}
else if(strlen(revStr2) < strlen(revStr1)) {
for(i = strlen(revStr2); i < strlen(revStr1); i++)
revStr2[i] = '0';
addResult = add2(revStr1,revStr2);
}
else
addResult = add2(revStr1,revStr2);
// print out
printf("sum is: %s\n", addResult);
return 0;
Since passing the whole array is not very optimal, C usually in most of the expressions convert it to pointer.
One way to pass whole array is by enclosing it in a struct. (Not a good solution though)
typedef struct
{
char s[128];
}MYSTR;

String calculation

I got an excersice to make a string calculator which only has an add function. When digits are not seperated, the digits have te make one whole number. When the input is 11 the program may not do 1 + 1 but has to make it eleven.
When I execute the following program it is printing "Sum = 111" on my screen, does anyone know why it is not printing 11 and maybe has a solution?
int main(void)
{
int sum = Add("11");
if(sum == -1)
{
printf("Can not return a sum");
}
else
{
printf("Sum = %d\n", sum);
}
}
extern int Add(char* numbers)
{
size_t string_length = strlen(numbers);
int Sum = 0;
int index = 0;
char number_string[255];
int number = 0;
if(string_length == 0)
{
Sum = 0;
return Sum;
}
else if(string_length == 1)
{
if(isdigit(numbers[0]))
{
Sum = numbers[0] - '0';
}
else
{
return -1;
}
return Sum;
}
else if(string_length >= 2)
{
for(index; index <= string_length; index++)
{
if(isdigit(numbers[index]))
{
strcat(number_string, &numbers[index]);
}
else if(!isdigit(numbers[index]))
{
Sum += atoi(number_string);
memset(number_string, 0, 255);
}
else
{
return -1;
}
}
return Sum;
}
else
{
return -1;
}
}
you function uses strcat, you can debug and see how it works:
1st iteration - append string "11" (&numbers[0] points to begin of the string) to number_string
2nd iteration - append string "1" (&numbers[1] points to 2nd symbol) to number_string
this is how you get "111"
what you need to do is to convert your string to number without concatenation, like this:
int Add(char* numbers) {
int n = 0;
for (; *numbers; numbers++)
if (isdigit(*numbers))
n = n*10 + (*numbers - '0');
return n;
}
Your strcat cats 11 and then cats 1 to number string, so you the 111. Here is a simple way to do this without any built in functions other than printf.
#include <stdio.h>
int main(int argc, char *argv[])
{
int sum = -1;
printf("%d\n", argc);
if (argc == 2) {
sum = Add(argv[1]);
}
if(sum == -1)
{
printf("Can not return a sum\n");
}
else
{
printf("Sum = %d\n", sum);
}
}
int Add(char* numbers)
{
char *ptr = numbers;
char *end = numbers;
int sum = 0;
while (*end >= '0' && *end <= '9') {
end++;
}
for( ; ptr < end; ptr++) {
sum *= 10;
/* *ptr is always positive */
sum += *ptr - '0';
}
return sum;
}

Converting a long hexadecimal string to a decimal string

I would need to figure out a way to do the following in standard C. Assume we are given a string representing a hexadecimal number with say n digits. We want to convert this to a string representing the same number in decimal. The strings could have an arbitrary number of digits. What's at least easy to deduce is that the decimal string needs <= 2n letters.
Once we reach the size limit for numbers that the machine can handle, then the length of the string becomes quite irrelevant, so a hexadecimal number with 100 digits should be just as easy/hard to convert as one with 1000 digits i.e. the same algorithm should work on both as it has to work in chunks.
Has anyone here thought about this? What's really annoying is that large powers of 2 have nonzero digits down to the first order, so any element in the hexadecimal sequence can affect the last digit in decimal...
I could only find questions where someone wanted a string converted to a number or a number to a string in some base. If someone wonders why I would need this. I'm playing around with arbitrary precision numbers and the most economical format for storing numbers in is base 256, so I need to print numbers given in this form (or equivalently any hexadecimal).
EDIT: So I implemented a conversion function and I'll share it here if anyone else might ever need it. This was very quick an dirty and a better implementation would of course start by replacing the digits buffer in the struct by something that gets dynamically allocated. Since all arithmetic happens in the "add" function it would then be easy to realloc this buffer to something bigger if an addition overflows. The output buffer size is always simple to assign, since any hexadecimal number converts to a decimal number with less or equal to twice the digits.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXLEN 1000
struct number {
unsigned char digits[MAXLEN];
unsigned int num_digits;
};
int add(struct number *, struct number *, struct number *);
int mult(struct number *, struct number *, struct number *);
int power(struct number *, unsigned int, struct number *);
void print_number(struct number *, char *);
void dec(struct number *);
void hex2dec(char *hex, char *outbuf)
{
int n;
char *s;
struct number decrep;
struct number twopow;
struct number digit;
decrep.num_digits = 0;
n = strlen(hex);
s = hex;
while(--n > -1) {
/* weight of digit */
twopow.num_digits = 2;
twopow.digits[0] = 6;
twopow.digits[1] = 1;
power(&twopow, n, &twopow);
/* Extract digit */
if(*s <= '9' && *s >= '0') {
digit.digits[0] = *s - '0';
digit.num_digits = 1;
} else if(*s <= 'f' && *s >= 'a') {
digit.digits[0] = *s - 'a';
digit.digits[1] = 1;
digit.num_digits = 2;
} else if(*s <= 'F' && *s >= 'A') {
digit.digits[0] = *s - 'A';
digit.digits[1] = 1;
digit.num_digits = 2;
}
s++;
mult(&digit, &twopow, &digit);
add(&decrep, &digit, &decrep);
}
/* Convert decimal number to a string */
if(decrep.num_digits == 0) {
*outbuf = '0';
*(++outbuf) = '\0';
return;
}
for(n = decrep.num_digits-1; n >= 0; n--) {
*(outbuf++) = '0' + decrep.digits[n];
}
*outbuf = '\0';
}
int main(void)
{
char buf[1000];
hex2dec("FFEa4334234FABCD", buf);
printf("%s", buf);
return 0;
}
void copy_number(struct number *dst, struct number *src)
{
int i;
for(i = 0; i < src->num_digits; i++) dst->digits[i] = src->digits[i];
dst->num_digits = src->num_digits;
}
int power(struct number *a, unsigned int n, struct number *b)
{
struct number atmp;
/* Are we exponentiating by 0? */
if(n == 0) {
b->num_digits = 1;
b->digits[0] = 1;
return 0;
}
copy_number(&atmp, a);
while(--n > 0) {
mult(&atmp, a, &atmp);
}
copy_number(b, &atmp);
return 0;
}
int mult(struct number *a, struct number *b, struct number *c)
{
struct number btmp;
struct number ctmp;
struct number *t;
/* Are we multiplying by 0? */
if(a->num_digits == 0 || b->num_digits == 0) {
c->num_digits = 0;
return 0;
}
if(a->num_digits < b->num_digits) {
t = a;
a = b;
b = t;
}
copy_number(&btmp, b);
copy_number(&ctmp, a);
while(1) {
/* Are we multiplying by 1? */
if(btmp.num_digits == 1 && btmp.digits[0] == 1) {
break;
}
add(&ctmp, a, &ctmp);
dec(&btmp);
}
copy_number(c, &ctmp);
return 0;
}
int add(struct number *a, struct number *b, struct number *c)
{
int i, j;
int carry;
struct number *t;
if(a->num_digits < b->num_digits) {
t = a;
a = b;
b = t;
}
for(i = 0, carry = 0; i < a->num_digits; i++) {
if(i >= b->num_digits) j = a->digits[i]+carry;
else j = a->digits[i]+b->digits[i]+carry;
if(j > 9) {
j -= 10;
carry = 1;
} else {
carry = 0;
}
c->digits[i]=j;
}
/* Did we overflow? */
if(carry > 0 && i == MAXLEN) return -1;
/* Carry over from last addition? */
if(carry > 0) {
c->digits[i] = carry;
c->num_digits = a->num_digits+1;
} else {
c->num_digits = a->num_digits;
}
return 0;
}
void print_number(struct number *a, char *buf)
{
int i;
if(a->num_digits == 0) {
printf("0");
return;
}
for(i = a->num_digits-1; i >= 0; i--) {
*(buf++) = '0' + a->digits[i];
}
*buf = '\0';
}
void dec(struct number *a)
{
int i;
for(i = 0; i < a->num_digits; i++) {
if(a->digits[i] > 0) {
a->digits[i]--;
break;
}
a->digits[i] = 9;
}
/* Did number of digits get lower */
if(i == a->num_digits -1 && a->digits[i] == 0) {
for(i = a->num_digits - 1; i >= 0; i--) {
if(a->digits[i] != 0) {
a->num_digits = i + 1;
break;
}
}
}
}
Please note there is a bug in this code. As soon as the HEX string contains a 0 !
this snippet :
/* Extract digit */
if(*s <= '9' && *s >= '0') {
digit.digits[0] = *s - '0';
digit.num_digits = 1;
} else if(*s <= 'f' && *s >= 'a') {
gives digits[0] = 0; num_digites = 1;
But later in the mult() function there is the snipet :
if(a->num_digits == 0 || b->num_digits == 0) {
c->num_digits = 0;
return 0;
}
that test 0 by num_digits == 0. So I suggest to replace in the first function the snippet with :
if(*s == '0') {
digit.digits[0] = *s - '0';
digit.num_digits = 0;
}else if(*s <= '9' && *s > '0') {
digit.digits[0] = *s - '0';
digit.num_digits = 1;
} else if(*s <= 'f' && *s >= 'a') {
looks to work fine for me.
You can compare the result on this site : http://www.statman.info/conversions/hexadecimal.php

Resources