Converting a multidigital integer from a char array into an integer - c

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.

Related

A c program to convert from octal to decimal

I'm trying to figure what is wrong with my code as it always skips only to the printf("not an octal number part"); and only outputs that although has many of the other computations before it, i'm trying to debug it but can't seem to find the error. this is the summer of the problem below, also we are not allowed to use pointers yet.
A C program to input an octal number in the form of a line of characters and store the input characters in an array. Convert the octal number to a decimal integer and display the decimal integer on the standard output using printf.
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
#define MAX_SIZE 100
int main() {
char my_strg[MAX_SIZE];
int c;
int res = 0;
int i = 0;
while ( (c = getchar()) != '\n') {
my_strg[i] = c;
i++;
}
int k = 0;
for(k = strlen(my_strg)-1; k >= 0; k--) {
if((my_strg[k] >= '0') && (my_strg[k] <= '7')) {
res += (pow(8, k) * (my_strg[k]-'0'));
} else if(my_strg[k] == '-') {
res *= -1;
} else {
printf("not an octal number");
break;
}
k++;
}
printf("%d\n", res);
}
You haven't null-terminated my_strg. This means that the beginning of the array contains the input, but the rest of it contains gibberish. It may also be a good idea to do bounds checking so that you don't get a buffer overflow.
while (((c = getchar()) != '\n') && (i < MAX_SIZE-1)) {
my_strg[i] = c;
my_strg[i+1] = '\0';
i++;
}
very simple function. Needs more error checking.
Note 'a' != 'A'. The base can be as big as number of chars in the digits table
static const char digits[] = "0123456789abcdefghijklmnopqrstuwxyzABCDEFGHIJKLMNOPQRTSTUWXYZ";
long long ALMOST_anybase(const char *str, int base, int *errCode)
{
long long result = 0;
int sign = 1;
if(errCode) *errCode = 0;
if(str)
{
if(*str == '-') {sign = -1; str++;}
while(*str)
{
if(*str == '-')
{
if(errCode) *errCode = 3;
break;
}
else
{
char *ch;
if((ch = strchr(digits, *str)))
{
if(ch - digits >= base)
{
if(errCode) *errCode = 2;
break;
}
result *= base;
result += (ch - digits);
}
else
{
if(errCode) *errCode = 1;
break;
}
}
str++;
}
}
return result * sign;
}
int main(void)
{
int errCode;
long long result;
result = ALMOST_anybase("-4-4", 10, &errCode);
if(errCode)
{
printf("Wrong input string ErrCode = %d\n", errCode);
}
else
{
printf("result = %lld\n", result);
}
}

Convert chars from pointer to integer num

if the user enter a string,than is save every part of it with strtok, and one of the part was numbers, how i can convert this numbers to integer?
my goal is to get this string : "matrix 3 3 ", and to verify that the user didnt enter double or float, just integer num. I tried to do casting but it is didnt work
thx!
There are different possible ways, but concerning
my goal is [...] to verify that the user didnt enter double or float, just integer num.
you probably aim for full input validation. In that case, you must use strtol().
#include <stdlib.h>
#include <limits.h>
int main(void)
{
const char *str = "42"; // in your code, some result from strtok
char *endptr;
long num = strtol(str, &endptr, 10);
if (endptr == str || *endptr)
{
// not parsed successfully
return 1; // error and out ... do whatever is suitable
}
if (num > INT_MAX || num < INT_MIN)
{
// value was outside int range
return 1;
}
int x = (int)num;
return 0;
}
If you actually want a long, for checking the range, set errno to 0 before calling strtol() and check for errno == ERANGE afterwards. (include errno.h for this)
For the sake of completeness, in response to your comment, of course you can do it all manually, but it's tedious and error prone and less efficient, so I'd never recommend that. See here an example for parsing unsigned integers from strings, with error checking:
#include <stdio.h>
#include <string.h>
// write result to *result, return 0 on error, 1 on success:
int parseuint(unsigned int *result, const char *str)
{
if (!str || !*str) return 0;
size_t len = strlen(str);
unsigned char bcd[len];
for (size_t i = 0; i < len; ++i)
{
if (str[i] < '0' || str[i] > '9') return 0;
bcd[i] = str[i] - '0';
}
size_t scanstart = 0;
*result = 0;
unsigned int mask = 1;
while (scanstart < len)
{
if (!mask) return 0;
if (bcd[len-1] & 1) *result |= mask;
mask <<=1;
for (size_t i = len-1; i > scanstart; --i)
{
bcd[i] >>= 1;
if (bcd[i-1] & 1) bcd[i] |= 8;
}
bcd[scanstart] >>= 1;
while (scanstart < len && !bcd[scanstart]) ++scanstart;
for (size_t i = scanstart; i < len; ++i)
{
if (bcd[i] > 7) bcd[i] -= 3;
}
}
return 1;
}
int main(void)
{
unsigned int a;
if (parseuint(&a, "4258"))
{
printf("parsed: %u\n", a);
}
else
{
puts("error parsing 4258");
}
if (parseuint(&a, "13.7"))
{
printf("parsed: %u\n", a);
}
else
{
puts("error parsing 13.7");
}
if (parseuint(&a, "12345678901234567890"))
{
printf("parsed: %u\n", a);
}
else
{
puts("error parsing 12345678901234567890");
}
}

Getting a 128 bits integer from command line

I'm trying to cast an unsigned long long key to do the Tiny Encryption Algorithm algorithm.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char** argv){
unsigned int key[4] = { 0 };
*key = strtoll(argv[1], NULL, 10);
printf("%s key = %llu\n", argv[0], key);
return 0;
}
Here is my input :
./a.out 9223372036854775700
Here is the output :
./a.out key = 140723741574976
So I'm passing a 128 bit key in argv[1]. Shouldn't it be cast properly in memory into the unsigned int array?
So, I'm trying to figure out why this is the output of my program. Does this have something to do with endianness?
long long is only specified to contain at least 64 bits. You might be better off passing your key as hex and parsing it manually into a byte array
Take a step back, and look at what you are trying to implement. The Tiny Encryption Algorithm does not work on an 128-bit integer, but on a 128-bit key; the key is composed of four 32-bit unsigned integers.
What you actually need, is a way to parse a decimal (or hexadecimal, or some other base) 128-bit unsigned integer from a string to four 32-bit unsigned integer elements.
I suggest writing a multiply-add function, which takes the quad-32-bit value, multiplies it by a 32-bit constant, and adds another 32-bit constant:
#include <stdint.h>
uint32_t muladd128(uint32_t quad[4], const uint32_t mul, const uint32_t add)
{
uint64_t temp = 0;
temp = (uint64_t)quad[3] * (uint64_t)mul + add;
quad[3] = temp;
temp = (uint64_t)quad[2] * (uint64_t)mul + (temp >> 32);
quad[2] = temp;
temp = (uint64_t)quad[1] * (uint64_t)mul + (temp >> 32);
quad[1] = temp;
temp = (uint64_t)quad[0] * (uint64_t)mul + (temp >> 32);
quad[0] = temp;
return temp >> 32;
}
The above uses most significant first word order. It returns nonzero if the result overflows; in fact, it returns the 32-bit overflow itself.
With that, it is very easy to parse a string describing a nonnegative 128-bit integer in binary, octal, decimal, or hexadecimal:
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
static void clear128(uint32_t quad[4])
{
quad[0] = quad[1] = quad[2] = quad[3] = 0;
}
/* muladd128() */
static const char *parse128(uint32_t quad[4], const char *from)
{
if (!from) {
errno = EINVAL;
return NULL;
}
while (*from == '\t' || *from == '\n' || *from == '\v' ||
*from == '\f' || *from == '\r' || *from == ' ')
from++;
if (from[0] == '0' && (from[1] == 'x' || from[1] == 'X') &&
((from[2] >= '0' && from[2] <= '9') ||
(from[2] >= 'A' && from[2] <= 'F') ||
(from[2] >= 'a' && from[2] <= 'f'))) {
/* Hexadecimal */
from += 2;
clear128(quad);
while (1)
if (*from >= '0' && *from <= '9') {
if (muladd128(quad, 16, *from - '0')) {
errno = ERANGE;
return NULL;
}
from++;
} else
if (*from >= 'A' && *from <= 'F') {
if (muladd128(quad, 16, *from - 'A' + 10)) {
errno = ERANGE;
return NULL;
}
from++;
} else
if (*from >= 'a' && *from <= 'f') {
if (muladd128(quad, 16, *from - 'a' + 10)) {
errno = ERANGE;
return NULL;
}
from++;
} else
return from;
}
if (from[0] == '0' && (from[1] == 'b' || from[1] == 'B') &&
(from[2] >= '0' && from[2] <= '1')) {
/* Binary */
from += 2;
clear128(quad);
while (1)
if (*from >= '0' && *from <= '1') {
if (muladd128(quad, 2, *from - '0')) {
errno = ERANGE;
return NULL;
}
from++;
} else
return from;
}
if (from[0] == '0' &&
(from[1] >= '0' && from[1] <= '7')) {
/* Octal */
from += 1;
clear128(quad);
while (1)
if (*from >= '0' && *from <= '7') {
if (muladd128(quad, 8, *from - '0')) {
errno = ERANGE;
return NULL;
}
from++;
} else
return from;
}
if (from[0] >= '0' && from[0] <= '9') {
/* Decimal */
clear128(quad);
while (1)
if (*from >= '0' && *from <= '9') {
if (muladd128(quad, 10, *from - '0')) {
errno = ERANGE;
return NULL;
}
from++;
} else
return from;
}
/* Not a recognized number. */
errno = EINVAL;
return NULL;
}
int main(int argc, char *argv[])
{
uint32_t key[4];
int arg;
for (arg = 1; arg < argc; arg++) {
const char *end = parse128(key, argv[arg]);
if (end) {
if (*end != '\0')
printf("%s: 0x%08x%08x%08x%08x (+ \"%s\")\n", argv[arg], key[0], key[1], key[2], key[3], end);
else
printf("%s: 0x%08x%08x%08x%08x\n", argv[arg], key[0], key[1], key[2], key[3]);
fflush(stdout);
} else {
switch (errno) {
case ERANGE:
fprintf(stderr, "%s: Too large.\n", argv[arg]);
break;
case EINVAL:
fprintf(stderr, "%s: Not a nonnegative integer in binary, octal, decimal, or hexadecimal notation.\n", argv[arg]);
break;
default:
fprintf(stderr, "%s: %s.\n", argv[arg], strerror(errno));
break;
}
}
}
return EXIT_SUCCESS;
}
It is very straightforward to add support for Base64 and Base85, which are sometimes used; or indeed for any base less than 232.
And, if you think about the above, it was all down to being precise about what you need.
Code is attempting to print the address of the array key[0] rather than its value. This is not an endian-ness issue. Enable all compiler warnings to save time.
*key = strtoll(argv[1], NULL, 10); attempts to save a long long (at least 64-bit) into a unsigned int, which is likely only 32.
The string "9223372036854775700" represents a 63 bit number.
First try to use an unsigned long long which is at least a 64-bit number.
int main(int argc, char** argv){
// unsigned int key[4] = { 0 };
unsigned long long key = strtoull(argv[1], NULL, 10);
printf("%s key = %llu\n", argv[0], key);
return 0;
}
C does not specify support for 128-bit integers. User code could be written to cope with that. #C_Elegans idea of using hexadecimal text is good.
As int could be of various sizes, better to use
#include <stdint.h>
// unsigned int key[4];
uint32_t key[4];
A sample code idea
#include <ctype.h>
#include <errno.h>
#include <inttypes.h>
#include <stdint.h>
#include <stdlib.h>
typedef struct {
uint16_t u[8];
} my_uint128_t;
my_uint128_t strtomy_uint128(const char *s, char **endptr, int base) {
my_uint128_t y = {0};
while (isalnum((unsigned char ) *s)) {
char *endptr;
uint32_t sum = (uint32_t) strtoul((char[2]) {*s, '\0'}, &endptr, base);
if (*endptr) {
break;
}
for (int i = 0; i < 8; i++) {
sum += y.u[i] * (uint32_t) base;
y.u[i] = (uint16_t) sum;
sum >>= 16;
}
if (sum) {
errno = ERANGE;
for (int i = 0; i < 8; i++) {
y.u[i] = UINT16_MAX;
}
}
s++;
}
if (endptr) {
*endptr = (char *) s;
}
return y;
}
void uint128_dump(my_uint128_t x) {
for (int i = 8; i > 0; ) {
i--;
printf("%04" PRIX16 "%c", x.u[i], i ? ' ' : '\n');
}
}
int main(void) {
my_uint128_t a = strtomy_uint128("9223372036854775700", 0, 10);
uint128_dump(a);
}
Output
0000 0000 0000 0000 7FFF FFFF FFFF FF94
Why not do it manually? Get a __int128 type variable, go through each digit of your input and insert it in your variable as such:
int main(int argc, char** argv){
__int128 key = 0;
int i;
for (i=0; i<strlen(argv[1]); i++){
key *= 10; // "shift" current value to make space for adding one more decimal
key += argv[1][i] - '0'; // convert ascii character to number
}
printf("%s key = %llu\n", argv[0], key);
return 0;
}
Note that if argv[1] is too long the key will discard its first digits rather than its last. So, maybe that's something you need to take care of too, according to your preferences

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 Ascii to binary in 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);
}

Resources