C programming : String calculation Using ASCII code [closed] - c

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
If I get the numbers in character string like this and store them in array x[100] and y[100],
x[100] '1' '0' '0' '0' '\0'
y[100] '9' '9' '\0'
The added result should be stored as string, too.
result[100] '1' '0' '9' '9' '\0'
I have tried to use ASCII code to solve this problem, for example:
char number[2] = {'1','2'};
char result;
result = (number[0] - '0') + (number[1] - '0') + '0';
But I am having trouble adjusting digits of x[100] and y[100].
I really need your help :(

You may insist on avoiding the library functions to convert strings to numbers and vice versa, as mentioned by #sjsam.
If you think about it, numbers really start at the LSD (least significant digit, not acid), or on the right side. So start your loop at the last character of each array before the closing \0 and iterate backwards. It won't be trivial, but that's how atoi() works too.
It's rather unfortunate that the Romans started writing from left to right, but that's the root cause of this problem. Otherwise integration of right-to-left Arabic numbers would have been much easier.
Discussing the idiocy of Roman numerals is out of the scope of this answer, let's suffice it to say that their lack of zero prevented any of their programs to finish with a successful exit status, which in turn led to the collapse of the Roman Empire.

Instead of adding byte by byte you may use the functions atoi to convert a string to integer and once you calculate the sum, you may use itoa/snprintf to convert the sum(integer) to its string representation.
See an example below :
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(void)
{
char buffer[100];
int no1,no2,no3;
char number1[] = {'1','0','0','0','\0'};
char number2[] = {'9','0','0','\0'};
/* Converting strings to respective integers */
no1=atoi(number1);
no2=atoi(number2);
no3=no1+no2;
/* Convert integer to a null terminated string
* You could also use itoa(no3,buffer,10);
*/
snprintf(buffer,99,"%d",no3);
printf("no1 : %d\n",no1);
printf("no2 : %d\n",no2);
printf("no3 : %s\n",buffer); // printing the string
return 0;
}
itoa is not supported by some compilers, so the best bet is to use snprintf.
Output
Here buffer is a null terminated array
{'1','9','0','0','\0'}
which we have printed using the %s format specifier.
References
itoa manaul.
snprintf manual.
Note
I have set the buffer size to 100 for this example. However, the maximum value of number of bytes that buffer can hold is the depends upon the maximum value an integer(signed in your case) can contain in your system. (Thanks #BLUEPIXY for reminding this stuff. :) )

Sum ASCII numbers while avoiding converting to binary/decimal:
#include <stdio.h>
#include <string.h>
#include <libc.h>
char *sum(char *x, char *y) {
size_t x_idx = strlen(x);
size_t y_idx = strlen(y);
size_t z_idx = MAX(x_idx, y_idx) + 1;
char *z = malloc(z_idx + 1);
char carry = '0';
while (x_idx > 0 || y_idx > 0 || carry == '1') {
char digit = carry;
if (x_idx > 0 && y_idx > 0) {
digit = (x[--x_idx] + y[--y_idx] + carry) % '0' + '0';
} else if (x_idx > 0) {
digit = (x[--x_idx] + carry) % '0' + '0';
} else if (y_idx > 0) {
digit = (y[--y_idx] + carry) % '0' + '0';
}
carry = (digit > '9') ? '1' : '0';
if (carry == '1') {
digit -= 10;
}
z[--z_idx] = digit;
}
while (z_idx > 0) {
z[--z_idx] = ' '; // pad for now; for production, shift array
}
return z;
}
int main(int argc, char* argv[]) {
char *x = argv[1];
char *y = argv[2];
char *z = sum(x, y);
printf("%s + %s = %s\n", x, y, z);
free(z);
}
USAGE
> ./a.out 1000 99
1000 + 99 = 1099
>
> ./a.out 999 999
999 + 999 = 1998
>

#include <stdio.h>
#include <string.h>
int main(void) {
char x[100] = "1000";
char y[100] = "99";
char result[100+1] = " ";
int x_i = strlen(x)-1;
int y_i = strlen(y)-1;
int r_i = 1 + ((x_i > y_i) ? x_i + 1 : y_i + 1);
int carray = 0, sum;
result[r_i] = 0;
while(--r_i>0){
if(x_i >= 0 && y_i >= 0)
sum = x[x_i--] - '0' + y[y_i--] - '0' + carray;
//else if(x_i < 0 && y_i < 0)
// sum = carray;
else if(y_i < 0)// && x_i >= 0){
sum = x[x_i--] - '0' + carray;
else// if (x_i < 0 && y_i >= 0){
sum = y[y_i--] - '0' + carray;
carray = sum > 9;
result[r_i] = sum % 10 + '0';
}
if(carray)
result[0] = '1';
printf("%s\n", result);
return 0;
}

Here's some code that should give you a good idea.
This begins to handle carrying, but doesn't cover all cases.
It should be a good start.
#include <stdio.h>
#include <string.h>
int main(void) {
char y[100] = "1032";
char x[100] = "2399";
int carry = 0;
char* b = (strlen(x) > strlen(y))? x : y;
char* s = (strlen(x) <= strlen(y))? x : y;
for(int i=strlen(s)-1, j=strlen(b)-1; i>=0; --i,--j)
{
b[j] = (b[j]+s[i]+carry-'0');
carry = 0;
if (b[j] > '9')
{
b[j] = (b[j]-'0')%10+'0';
carry = 1;
}
}
puts(b);
return 0;
}

Related

How to convert a sum of money to Indian currency format(Indian number format)? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
I wanted to build a C program to convert any number to Indian Currency Format. It can take inputs with negative sign, leading zeros and Decimal point + Mantissa and it will format the input to take care of the leading zeros and add the commas according to Indian number foramt. For example, numbers in Indian Number Format are represented as:
1
10
100
1,000
10,000
1,00,000
10,00,000
1,00,00,000
10,00,00,000
the input and related output would be like:
Minus sign: "-12345" -> "-12,345"
Decimal Point: "-12345.123" -> "-12,345.123"
Leading Zero's: 000000.123 → "0.123" or "-000123456.1234" -> "-1,23,456.1234"
If anyone would like to optimise this code in terms of time and space complexity, make it more concise and clean then do share your code.
Indian numbers are represented in decimal with groups of digits separated by commas. The last group has 3 digits and all more significant digits are grouped in pairs.
Here is a simple solution:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *convertToInrFormat(const char *s) {
const char *src = s + strspn(s, " \t\r\n"); /* skip spaces */
int len = strspn(src, "0123456789"); /* count number of digits */
int destlen = len + (len > 3 ? len / 2 - 1 : len == 0);
char *dest = malloc(destlen + 1);
if (dest != NULL) {
int i = 0, j = 0;
while (i < len) {
dest[j++] = src[i++];
if (i + 2 < len && ((i ^ len) & 1))
dest[j++] = ',';
}
if (len == 0) {
dest[j++] = '0';
}
dest[j] = '\0';
}
return dest;
}
int main(int argc, char *argv[]) {
for (int i = 1; i < argc; i++) {
char *input = argv[i];
char *output = convertToInrFormat(input);
printf("%s -> %s\n", input, output);
free(output);
}
return 0;
}
The basic logic of adding the commas is to first copy the sign character if it exists to the second array and then remove it from the original number array. Then if the number of digits in the Exponent part is odd then 1 digit is copied to the second array and removed to make the length even. then for every odd value of the index 'i' a comma is added.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *convertToInrFormat(char *lp_number, int lv_l)
{
char *lp_fnumber = '\0';
char *lp_p = '\0';
int lv_index = 0;
int lv_nsize = 0;
int lv_zerocount = 0;
int sign_count = 0;
int expo_count = 0;
int lv_i = 0;
int lv_j = 0;
if (lp_number[0] == '-') // The 0th position of the char array is checked for negative sign, if found sign_count is incremented.
{
sign_count++;
}
lv_zerocount = strspn(lp_number + sign_count, "0"); // the no. of Leading Zeros is calculated ignoring the negative sign if present.
if (lp_number[sign_count + lv_zerocount] == '.') //if the exponent part consists of only 0's then the zerocount is reduced by 1 to leave behind 1 zero in the exponent part.
{
lv_zerocount = lv_zerocount - 1;
}
if (lv_zerocount > 0) //the zeros are removed by being overwritten
{
memmove(lp_number + sign_count, lp_number + lv_zerocount + sign_count, strlen(lp_number));
}
while (lp_number[sign_count] != '.' && lp_number[sign_count] != '\0') //the count of remaining exponents is taken
{
expo_count++;
sign_count++;
}
lv_l = strlen(lp_number); // New string length
if (expo_count > 3) //inserting the commas
{
lv_nsize = lv_l + (expo_count / 2 - 1) + 1;
lp_fnumber = (char *)malloc(lv_nsize);
if (lp_fnumber != NULL)
{
if (lp_number[0] == '-')
{
lp_fnumber[0] = lp_number[0];
lv_j++;
memmove(lp_number, lp_number + 1, strlen(lp_number));
lv_l--;
if (expo_count % 2 != 0)
{
lp_fnumber[1] = lp_number[0];
lv_j++;
memmove(lp_number, lp_number + 1, strlen(lp_number));
expo_count--;
}
}
else if (expo_count % 2 != 0)
{
lp_fnumber[0] = lp_number[0];
lv_j = lv_j + 1;
memmove(lp_number, lp_number + 1, strlen(lp_number));
expo_count--;
}
lp_p = strchr(lp_number, '.');
if (lp_p != NULL)
{
lv_index = lp_p - lp_number;
}
while (lv_i < expo_count)
{
lp_fnumber[lv_j++] = lp_number[lv_i++];
if (lv_i + 2 < expo_count && lv_i % 2 != 0) //Alt logic:((lv_i ^ lv_l) & 1) here for every odd value of i index a comma is added.
lp_fnumber[lv_j++] = ',';
}
if (lv_index != 0)
{
while (lp_number[lv_index] != '\0')
{
lp_fnumber[lv_j++] = lp_number[lv_index++];
}
}
lp_fnumber[lv_j] = '\0';
}
return lp_fnumber;
}
else
{
return lp_number;
}
}
int main()
{
char lp_number[255];
int lv_l;
char *formated_number;
printf("Enter the lp_number\n");
fgets(lp_number, 255, stdin);
lv_l = strlen(lp_number);
formated_number = convertToInrFormat(lp_number, lv_l);
puts(formated_number);
}

C string to int without any libraries

I'm trying to write my first kernel module so I'm not able to include libraries for atoi, strtol, etc. How can I convert a string to int without these built-in functions? I tried:
int num;
num = string[0] - '0';
which works for the first character, but if I remove the [0] to try and convert the full string it gives me a warning: assignment makes integer from pointer without a cast. So what do I do?
When creating your own string to int function, make sure you check and protect against overflow. For example:
/* an atoi replacement performing the conversion in a single
pass and incorporating 'err' to indicate a failed conversion.
passing NULL as error causes it to be ignored */
int strtoi (const char *s, unsigned char *err)
{
char *p = (char *)s;
int nmax = (1ULL << 31) - 1; /* INT_MAX */
int nmin = -nmax - 1; /* INT_MIN */
long long sum = 0;
char sign = *p;
if (*p == '-' || *p == '+') p++;
while (*p >= '0' && *p <= '9') {
sum = sum * 10 - (*p - '0');
if (sum < nmin || (sign != '-' && -sum > nmax)) goto error;
p++;
}
if (sign != '-') sum = -sum;
return (int)sum;
error:
fprintf (stderr, "strtoi() error: invalid conversion for type int.\n");
if (err) *err = 1;
return 0;
}
You can't remove the [0]. That means that you are subtracting '0' from the pointer string, which is meaningless. You still need to dereference it:
num = string[i] - '0';
A string is an array of characters, represented by an address (a.k.a pointer).
An pointer has an value that might look something like 0xa1de2bdf. This value tells me where the start of the array is.
You cannot subtract a pointer type with a character type (e.g 0xa1de2bdf - 'b' does not really make sense).
To convert a string to a number, you could try this:
//Find the length of the string
int len = 0;
while (str[len] != '\0') {
len++;
}
//Loop through the string
int num = 0, i = 0, digit;
for (i=0; i<len; i++) {
//Extract the digit
digit = ing[i] - '0';
//Multiply the digit with its correct position (ones, tens, hundreds, etc.)
num += digit * pow(10, (len-1)-i);
}
Of course if you are not allowed to use math.h library, you could write your own pow(a,b) function which gives you the value of a^b.
int mypowfunc(int a, int b) {
int i=0, ans=1;
//multiply the value a for b number of times
for (i=0; i<b; i++) {
ans *= a;
}
return ans;
}
I have written the code above in a way that is simple to understand. It assumes that your string has a null character ('\0') right behind the last useful character (which is good practice).
Also, you might want to check that the string is actually a valid string with only digits (e.g '0', '1', '2', etc.). You could do this by including an if... else.. statement while looping through the string.
In modern kernels you want to use kstrto*:
http://lxr.free-electrons.com/source/include/linux/kernel.h#L274
274 /**
275 * kstrtoul - convert a string to an unsigned long
276 * #s: The start of the string. The string must be null-terminated, and may also
277 * include a single newline before its terminating null. The first character
278 * may also be a plus sign, but not a minus sign.
279 * #base: The number base to use. The maximum supported base is 16. If base is
280 * given as 0, then the base of the string is automatically detected with the
281 * conventional semantics - If it begins with 0x the number will be parsed as a
282 * hexadecimal (case insensitive), if it otherwise begins with 0, it will be
283 * parsed as an octal number. Otherwise it will be parsed as a decimal.
284 * #res: Where to write the result of the conversion on success.
285 *
286 * Returns 0 on success, -ERANGE on overflow and -EINVAL on parsing error.
287 * Used as a replacement for the obsolete simple_strtoull. Return code must
288 * be checked.
289 */
This function skips leading and trailing whitespace, handles one optional + / - sign, and returns 0 on invalid input,
// Convert standard null-terminated string to an integer
// - Skips leading whitespaces.
// - Skips trailing whitespaces.
// - Allows for one, optional +/- sign at the front.
// - Returns zero if any non-+/-, non-numeric, non-space character is encountered.
// - Returns zero if digits are separated by spaces (eg "123 45")
// - Range is checked against Overflow/Underflow (INT_MAX / INT_MIN), and returns 0.
int StrToInt(const char* s)
{
int minInt = 1 << (sizeof(int)*CHAR_BIT-1);
int maxInt = -(minInt+1);
char* w;
do { // Skip any leading whitespace
for(w=" \t\n\v\f\r"; *w && *s != *w; ++w) ;
if (*s == *w) ++s; else break;
} while(*s);
int sign = 1;
if ('-' == *s) sign = -1;
if ('+' == *s || '-' == *s) ++s;
long long i=0;
while('0' <= *s && *s <= '9')
{
i = 10*i + *s++ - '0';
if (sign*i < minInt || maxInt < sign*i)
{
i = 0;
break;
}
}
while (*s) // Skip any trailing whitespace
{
for(w=" \t\n\v\f\r"; *w && *s != *w; ++w) ;
if (*w && *s == *w) ++s; else break;
}
return (int)(!*s*sign*i);
}
" not able to include libraries" --> Unclear if code is allowed access to INT_MAX, INT_MIN. There is no way to determine the minimum/maximum signed integer in a completely portable fashion without using the language provided macros like INT_MAX, INT_MIN.
Use INT_MAX, INT_MIN is available. Else we could guess the char width is 8. We could guess there are no padding bits. We could guess that integers are 2's complement. With these reasonable assumptions, minimum and maximum are defined below.
Note: Shifting into the sign bit is undefined behavior (UB), so don't do that.
Let us add another restriction: make a solution that works for any signed integer from signed char to intmax_t. This disallows code from using a wider type, as there may not be a wider type.
typedef int Austin_int;
#define Austin_INT_MAXMID ( ((Austin_int)1) << (sizeof(Austin_int)*8 - 2) )
#define Austin_INT_MAX (Austin_INT_MAXMID - 1 + Austin_INT_MAXMID)
#define Austin_INT_MIN (-Austin_INT_MAX - 1)
int Austin_isspace(int ch) {
const char *ws = " \t\n\r\f\v";
while (*ws) {
if (*ws == ch) return 1;
ws++;
}
return 0;
}
// *endptr points to where parsing stopped
// *errorptr indicates overflow
Austin_int Austin_strtoi(const char *s, char **endptr, int *errorptr) {
int error = 0;
while (Austin_isspace(*s)) {
s++;
}
char sign = *s;
if (*s == '-' || *s == '+') {
s++;
}
Austin_int sum = 0;
while (*s >= '0' && *s <= '9') {
int ch = *s - '0';
if (sum <= Austin_INT_MIN / 10 &&
(sum < Austin_INT_MIN / 10 || -ch < Austin_INT_MIN % 10)) {
sum = Austin_INT_MIN;
error = 1;
} else {
sum = sum * 10 - ch;
}
s++;
}
if (sign != '-') {
if (sum < -Austin_INT_MAX) {
sum = Austin_INT_MAX;
error = 1;
} else {
sum = -sum;
}
}
if (endptr) {
*endptr = (char *) s;
}
if (errorptr) {
*errorptr = error;
}
return sum;
}
The above depends on C99 or later in the Austin_INT_MIN Austin_INT_MIN % 10 part.
This is the cleanest and safest way I could come up with
int str_to_int(const char * str, size_t n, int * int_value) {
int i;
int cvalue;
int value_muliplier = 1;
int res_value = 0;
int neg = 1; // -1 for negative and 1 for whole.
size_t str_len; // String length.
int end_at = 0; // Where loop should end.
if (str == NULL || int_value == NULL || n <= 0)
return -1;
// Get string length
str_len = strnlen(str, n);
if (str_len <= 0)
return -1;
// Is negative.
if (str[0] == '-') {
neg = -1;
end_at = 1; // If negative 0 item in 'str' is skipped.
}
// Do the math.
for (i = str_len - 1; i >= end_at; i--) {
cvalue = char_to_int(str[i]);
// Character not a number.
if (cvalue == -1)
return -1;
// Do the same math that is down below.
res_value += cvalue * value_muliplier;
value_muliplier *= 10;
}
/*
* "436"
* res_value = (6 * 1) + (3 * 10) + (4 * 100)
*/
*int_value = (res_value * neg);
return 0;
}
int char_to_int(char c) {
int cvalue = (int)c;
// Not a number.
// 48 to 57 is 0 to 9 in ascii.
if (cvalue < 48 || cvalue > 57)
return -1;
return cvalue - 48; // 48 is the value of zero in ascii.
}

atoi implementation in C

I can't understand the following atoi implementation code, specifically this line:
k = (k << 3) + (k << 1) + (*p) - '0';
Here is the code:
int my_atoi(char *p) {
int k = 0;
while (*p) {
k = (k << 3) + (k << 1) + (*p) - '0';
p++;
}
return k;
}
Can someone explain it to me ?
Another question: what should be the algorithm of atof implementation ?
<< is bit shift, (k<<3)+(k<<1) is k*10, written by someone who thought he was more clever than a compiler (well, he was wrong...)
(*p) - '0' is subtracting the value of character 0 from the character pointed by p, effectively converting the character to a number.
I hope you can figure out the rest... just remember how the decimal system works.
Here is a specification for the standard function atoi. Sorry for not quoting the standard, but this will work just as fine (from: http://www.cplusplus.com/reference/clibrary/cstdlib/atoi/ )
The function first discards as many whitespace characters (as in
isspace) as necessary until the first non-whitespace character is
found. Then, starting from this character, takes an optional initial
plus or minus sign followed by as many base-10 digits as possible, and
interprets them as a numerical value.
The string can contain additional characters after those that form the
integral number, which are ignored and have no effect on the behavior
of this function.
If the first sequence of non-whitespace characters in str is not a
valid integral number, or if no such sequence exists because either
str is empty or it contains only whitespace characters, no conversion
is performed and zero is returned.
k = (k << 3) + (k << 1);
means
k = k * 2³ + k * 2¹ = k * 8 + k * 2 = k * 10
Does that help?
The *p - '0' term adds the value of the next digit; this works because C requires that the digit characters have consecutive values, so that '1' == '0' + 1, '2' == '0' + 2, etc.
As for your second question (atof), that should be its own question, and it's the subject for a thesis, not something simple to answer...
#include <stdio.h>
#include <errno.h>
#include <limits.h>
double atof(const char *string);
int debug=1;
int main(int argc, char **argv)
{
char *str1="3.14159",*str2="3",*str3="0.707106",*str4="-5.2";
double f1,f2,f3,f4;
if (debug) printf("convert %s, %s, %s, %s\n",str1,str2,str3,str4);
f1=atof(str1);
f2=atof(str2);
f3=atof(str3);
f4=atof(str4);
if (debug) printf("converted values=%f, %f, %f, %f\n",f1,f2,f3,f4);
if (argc > 1)
{
printf("string %s is floating point %f\n",argv[1],atof(argv[1]));
}
}
double atof(const char *string)
{
double result=0.0;
double multiplier=1;
double divisor=1.0;
int integer_portion=0;
if (!string) return result;
integer_portion=atoi(string);
result = (double)integer_portion;
if (debug) printf("so far %s looks like %f\n",string,result);
/* capture whether string is negative, don't use "result" as it could be 0 */
if (*string == '-')
{
result *= -1; /* won't care if it was 0 in integer portion */
multiplier = -1;
}
while (*string && (*string != '.'))
{
string++;
}
if (debug) printf("fractional part=%s\n",string);
// if we haven't hit end of string, go past the decimal point
if (*string)
{
string++;
if (debug) printf("first char after decimal=%c\n",*string);
}
while (*string)
{
if (*string < '0' || *string > '9') return result;
divisor *= 10.0;
result += (double)(*string - '0')/divisor;
if (debug) printf("result so far=%f\n",result);
string++;
}
return result*multiplier;
}
Interestingly, the man page for atoi doesn't indicate setting of errno so if you're talking any number > (2^31)-1, you're out of luck and similarly for numbers less than -2^31 (assuming 32-bit int). You'll get back an answer but it won't be what you want. Here's one that could take a range of -((2^31)-1) to (2^31)-1, and return INT_MIN (-(2^31)) if in error. errno could then be checked to see if it overflowed.
#include <stdio.h>
#include <errno.h> /* for errno */
#include <limits.h> /* for INT_MIN */
#include <string.h> /* for strerror */
extern int errno;
int debug=0;
int atoi(const char *c)
{
int previous_result=0, result=0;
int multiplier=1;
if (debug) printf("converting %s to integer\n",c?c:"");
if (c && *c == '-')
{
multiplier = -1;
c++;
}
else
{
multiplier = 1;
}
if (debug) printf("multiplier = %d\n",multiplier);
while (*c)
{
if (*c < '0' || *c > '9')
{
return result * multiplier;
}
result *= 10;
if (result < previous_result)
{
if (debug) printf("number overflowed - return INT_MIN, errno=%d\n",errno);
errno = EOVERFLOW;
return(INT_MIN);
}
else
{
previous_result *= 10;
}
if (debug) printf("%c\n",*c);
result += *c - '0';
if (result < previous_result)
{
if (debug) printf("number overflowed - return MIN_INT\n");
errno = EOVERFLOW;
return(INT_MIN);
}
else
{
previous_result += *c - '0';
}
c++;
}
return(result * multiplier);
}
int main(int argc,char **argv)
{
int result;
printf("INT_MIN=%d will be output when number too high or too low, and errno set\n",INT_MIN);
printf("string=%s, int=%d\n","563",atoi("563"));
printf("string=%s, int=%d\n","-563",atoi("-563"));
printf("string=%s, int=%d\n","-5a3",atoi("-5a3"));
if (argc > 1)
{
result=atoi(argv[1]);
printf("atoi(%s)=%d %s",argv[1],result,(result==INT_MIN)?", errno=":"",errno,strerror(errno));
if (errno) printf("%d - %s\n",errno,strerror(errno));
else printf("\n");
}
return(errno);
}
Here is my implementation(tested successfully with cases containing and starting with letters, +, - and zero's).
I tried to reverse-engineer atoi function in Visual Studio. If the input string only contained numerical characters, it could be implemented in one loop. but it gets complicated because you should take care of -,+ and letters.
int atoi(char *s)
{
int c=1, a=0, sign, start, end, base=1;
//Determine if the number is negative or positive
if (s[0] == '-')
sign = -1;
else if (s[0] <= '9' && s[0] >= '0')
sign = 1;
else if (s[0] == '+')
sign = 2;
//No further processing if it starts with a letter
else
return 0;
//Scanning the string to find the position of the last consecutive number
while (s[c] != '\n' && s[c] <= '9' && s[c] >= '0')
c++;
//Index of the last consecutive number from beginning
start = c - 1;
//Based on sign, index of the 1st number is set
if (sign==-1)
end = 1;
else if (sign==1)
end = 0;
//When it starts with +, it is actually positive but with a different index
//for the 1st number
else
{
end = 1;
sign = 1;
}
//This the main loop of algorithm which generates the absolute value of the
//number from consecutive numerical characters.
for (int i = start; i >=end ; i--)
{
a += (s[i]-'0') * base;
base *= 10;
}
//The correct sign of generated absolute value is applied
return sign*a;
}
about atoi() hint code from here:
and based on the atoi(), my implementation of atof():
[have same limitation of original code, doesn't check length, etc]
double atof(const char* s)
{
double value_h = 0;
double value_l = 0;
double sign = 1;
if (*s == '+' || *s == '-')
{
if (*s == '-') sign = -1;
++s;
}
while (*s >= 0x30 && *s <= 0x39)
{
value_h *= 10;
value_h += (double)(*s - 0x30);
++s;
}
// 0x2E == '.'
if (*s == 0x2E)
{
double divider = 1;
++s;
while (*s >= 0x30 && *s <= 0x39)
{
divider *= 10;
value_l *= 10;
value_l += (double)(*s - 0x30);
++s;
}
return (value_h + value_l/divider) * sign;
}
else
{
return value_h * sign;
}
}

Data types conversion (unsigned long long to char)

Can anyone tell me what is wrong with the following code?
__inline__
char* ut_byte_to_long (ulint nb) {
char* a = malloc(sizeof(nb));
int i = 0;
for (i=0;i<sizeof(nb);i++) {
a[i] = (nb>>(i*8)) & 0xFF;
}
return a;
}
This string is then concatenated as part of a larger one using strcat. The string prints fine but for the integers which are represented as character symbols. I'm using %s and fprintf to check the result.
Thanks a lot.
EDIT
I took one of the comments below (I was adding the terminating \0 separately, before calling fprintf, but after strcat. Modifying my initial function...
__inline__
char* ut_byte_to_long (ulint nb) {
char* a = malloc(sizeof(nb) + 1);
int i = 0;
for (i=0;i<sizeof(nb);i++) {
a[i] = (nb>>(i*8)) & 0xFF;
}
a[nb] = '\0' ;
return a;
}
This sample code still isn't printing out a number...
char* tmp;
tmp = ut_byte_to_long(start->id);
fprintf(stderr, "Value of node is %s \n ", tmp);
strcat is expecting a null byte terminating the string.
Change your malloc size to sizeof(nb) + 1 and append '\0' to the end.
You have two problems.
The first is that the character array a contains numbers, such as 2, instead of ASCII codes representing those numbers, such as '2' (=50 on ASCII, might be different in other systems). Try modifying your code to
a[i] = (nb>>(i*8)) & 0xFF + '0';
The second problem is that the result of the above computation can be anything between 0 and 255, or in other words, a number which requires more than one digit to print.
If you want to print hexadecimal numbers (0-9, A-F), two digits per such computation will be enough, and you can write something like
a[2*i + 0] = int2hex( (nb>>(i*8)) & 0x0F ); //right hexa digit
a[2*i + 1] = int2hex( (nb>>(i*8+4)) & 0x0F ); //left hexa digit
where
char int2hex(int n) {
if (n <= 9 && n >= 0)
return n + '0';
else
return (n-10) + 'A';
}
if you dont want to use sprintf(target_string,"%lu",source_int) or the non standard itoa(), here is a version of the function that transform a long to a string :
__inline__
char* ut_byte_to_long (ulint nb) {
char* a = (char*) malloc(22*sizeof(char));
int i=21;
int j;
do
{
i--;
a[i] = nb % 10 + '0';
nb = nb/10;
}while (nb > 0);
// the number is stored from a[i] to a[21]
//shifting the string to a[0] : a[21-i]
for(j = 0 ; j < 21 && i < 21 ; j++ , i++)
{
a[j] = a[i];
}
a[j] = '\0';
return a;
}
I assumed that an unsigned long contain less than 21 digits. (biggest number is 18,446,744,073,709,551,615 which equals 2^64 − 1 : 20 digits)

storing more than 2 power 31 on a 32-bit system

I have to write a program that can calculate the powers of 2 power 2010 and to find the sum of the digits. eg:
if `2 power 12 => gives 4096 . So 4+0+9+6 = 19 .
Now i need to find the same for 2 power 2010.
Please help me to understand.
Here's something to get you started:
char buf[2010]; // 2^2010 < 10^2010 by a huge margin, so buffer size is safe
snprintf(buf, sizeof buf, "%.0Lf", 0x1p2010L);
You have to either use a library that supplies unlimited integer length types (see http://en.wikipedia.org/wiki/Bignum ), or implement a solution that does not need them (e.g. use a digit array and implement the power calculation on the array yourself, which in your case can be as simple as addition in a loop). Since this is homework, probably the latter.
Knowing 2^32, how would you calculate 2^33 with pen and paper?
2^32 is 4294967296
4294967296
* 2
----------
8589934592
8589934592 is 2^33; sum of digits is 8+5+8+9+...+9+2 (62)
Just be aware that 2^2011 is a number with more than 600 digits: not that many to do by computer
GMP is perhaps the best, fastest free multi-architecture library for this. It provides a solid foundation for such calculations, including not only addition, but parsing from strings, multiplication, division, scientific operations, etc.
For literature on the algorithms themselves, I highly recommend The Art of Computer Programming, Volume 2: Seminumerical Algorithms by Donald Knuth. This book is considered by many to be the best single reference for the topic. This book explains from the ground up how such arithmetic can take place on a machine that can only do 32-bit arithmetic.
If you want to implement this calculation from scratch without using any tools, the following code block requires requires only the following additional methods to be supplied:
unsigned int divModByTen(unsigned int *num, unsigned int length);
bool isZero(unsigned int *num, unsigned int length);
divModByTen should divide replace num in memory with the value of num / 10, and return the remainder. The implementation will take some effort, unless a library is used. isZero just checks if the number is all zero's in memory. Once we have these, we can use the following code sample:
unsigned int div10;
int decimalDigitSum;
unsigned int hugeNumber[64];
memset(twoPow2010, 0, sizeof(twoPow2010));
twoPow2010[63] = 0x4000000;
// at this point, twoPow2010 is 2^2010 encoded in binary stored in memory
decimalDigitSum = 0;
while (!izZero(hugeNumber, 64)) {
mod10 = divModByTen(&hugeNumber[0], 64);
decimalDigitSum += mod10;
}
printf("Digit Sum:%d", decimalDigitSum);
This takes only a few lines of code in Delphi... :)
So in c must be the same or shorter.
function PowerOf2(exp: integer): string;
var
n : integer;
Digit : integer;
begin
result := '1';
while exp <> 0 do
begin
Digit := 0;
for n := Length(result) downto 1 do
begin
Digit := (ord(result[n]) - ord('0')) * 2 + Digit div 10;
result[n] := char(Digit mod 10 + ord('0'))
end;
if Digit > 9 then
result := '1' + result;
dec(exp);
end;
end;
-----EDIT-----
This is 1-to-1 c# version.
string PowerOf2(int exp)
{
int n, digit;
StringBuilder result = new StringBuilder("1");
while (exp != 0)
{
digit = 0;
for (n = result.Length; n >= 1; n--)
{
digit = (result[n-1] - '0') * 2 + digit / 10;
result[n-1] = Convert.ToChar(digit % 10 + '0');
}
if (digit > 9)
{
result = new StringBuilder("1" + result.ToString());
}
exp--;
}
return result.ToString();
}
int Sum(string s)
{
int sum = 0;
for (int i = 0; i < s.Length; i++)
{
sum += s[i] - '0';
}
return sum;
}
for (int i = 1; i < 20; i++)
{
string s1s = PowerOf2(i);
int sum = Sum(s1s);
Console.WriteLine(s1s + " --> " + sum);
}
Here's how you can calculate and print 22010:
#include <stdio.h>
#include <string.h>
void AddNumbers(char* dst, const char* src)
{
char ddigit;
char carry = 0;
while ((ddigit = *dst) != '\0')
{
char sdigit = '0';
if (*src != '\0')
{
sdigit = *src++;
}
ddigit += sdigit - '0' + carry;
if (ddigit > '9')
{
ddigit -= 10;
carry = 1;
}
else
{
carry = 0;
}
*dst++ = ddigit;
}
}
void ReverseString(char* s)
{
size_t i, n = strlen(s);
for (i = 0; i < n / 2; i++)
{
char t = s[i];
s[i] = s[n - 1 - i];
s[n - 1 - i] = t;
}
}
int main(void)
{
char result[607], tmp[sizeof(result)];
int i;
memset (result, '0', sizeof(result));
result[0] = '1';
result[sizeof(result) - 1] = '\0';
for (i = 0; i < 2010; i++)
{
memcpy(tmp, result, sizeof(result));
AddNumbers(result, tmp);
}
ReverseString(result);
printf("%s\n", result);
return 0;
}
You can now sum up the individual digits.

Resources