I'm doing school project which I'm needed to first receive 2 huge numbers (unlimited size, for the sake of example, lets say over 30 digits), second step is to take the 2 input numbers the create new number of the multiplication of the two, which I'm really breaking a sweat trying to do so.
My code so far:
Type definition to making sure I'm handling the right variables:
typedef char* verylong;
#define MAX_SIZE 100
Input method:
verylong input_long() {
int i, len; //i for loop, len for strlen - using integer for it to avoid invoking the method more than 1 time
verylong number;
char temp_str[MAX_SIZE]; //the input from user - limited to 100
gets(temp_str); //user input
len = strlen(temp_str); //saving the length of the input
number = (char*)calloc(len + 1, sizeof(char)); //allocating memory for the verylong and saving space for \0
for (i = 0; i < len; i++) {
if (temp_str[i] - '0' < 0 || temp_str[i] - '0' > 9) { //the input is not a digit
printf("\nBad input!\n");
return NULL;
}
number[i] = temp_str[i]; //all is good -> add to the verylong number
}
number[i] = '\0'; //setting last spot
return number;
}
My sad attempt of completing my task:
verylong multiply_verylong(verylong vl1, verylong vl2) {
verylong mult;
int cur, i, j, k, lrg, sml, temp_size;
char *temp;
j = 1;
temp = (char*)calloc(lrg + sml + 1, sizeof(char)); //maximum amount of digits
if (strlen(vl1) > strlen(vl2)) {
lrg = strlen(vl1);
sml = strlen(vl2);
}
else {
lrg = strlen(vl2);
sml = strlen(vl1);
}
cur = 0;
for (i = sml-1; i >= 0; i--) {
k = 0;
temp_size = 0;
cur = (vl1[i] - '0')*(vl2[i] - '0');
printf("\ncur=%d", cur);
if (cur > 9)
temp_size = 2;
else
temp_size = 1;
while (k < temp_size) {
if (cur > 9)
temp[j++] = (cur % 10) + '0';
else
temp[j++] = cur + '0';
cur /= 10;
k++;
}
}
mult = (char*)calloc(j + 1, sizeof(char));
for (i = 0; i < j; i++) {
mult[i] = temp[i];
}
mult[i] = '\0';
free(temp);
return mult;
}
Long story short, I know I'm doing mistake at my multiplication method since I'm adding the numbers by simply adding the mult of 2 digits at a time, over that I truly am lost.
Thanks.
My advice would be to break the task into a number of simpler task.
How would you do the multiplication on paper?
123 * 456 -> 1 * (456 * 100) + 2 * (456 * 10) + 3 * (456 * 1)
or written differently
3 * ( 1 * 456)
+ 2 * ( 10 * 456)
+ 1 * (100 * 456)
---------------
SUM TO GET RESULT
or
3 * 456
+ 2 * 4560
+ 1 * 45600
---------------
SUM TO GET RESULT
From this you can identify 3 tasks
Multiplying with powers of 10, i.e. 1, 10, 100, etc. (i.e. add zeros to the end)
Multiplying a string-number with a single digit
Adding two string-numbers.
Write simple functions for each of these steps.
char* mulPowerOf10(char* sn, unsigned power)
{
...
}
char* mulDigit(char* sn, char digit)
{
...
}
char* addNumbers(char* snA, char* snB)
{
...
}
Using these 3 simple functions you can put the real multiplication together. In psedo-code:
char* mulNumbers(char* snA, char* snB)
{
char* result = malloc(2);
strcpy(result, "0");
unsigned power = 0;
for_each_digit D in snA
{
char* t1 = mulPowerOf10(snB, power)
char* t2 = mulDigit(t1, D)
result = addNumbers(result, t2)
++power;
}
free(.. what needs to be freed ..);
return result;
}
Here is a code example.
I found it simpler to store the number as a sequence of digits along with the length in a struct. The number may have leading zeros.
#define MAX_SIZE 1024
typedef struct Number {
int len;
char digits[];
} Number;
// Instantiate a number with room for len digits.
Number *newNumber(int len) {
Number *n = malloc(sizeof(Number)+len);
n->len = len;
memset(n->digits, 0, len);
return n;
}
// inputNumber reads a number from stdin. It return NULL if the input
// is invalid, otherwise it returns a Number containing the given digits.
Number *inputNumber() {
char temp[MAX_SIZE];
if (fgets(temp, sizeof temp, stdin) == NULL)
return NULL; // use fgets because gets is deprecated since C11
// remove trailing \n if any
int len = strlen(temp);
if (len > 0 && temp[len-1] == '\n')
temp[--len] = '\0';
// check input validity
if (len == 0)
return NULL;
for (int i = 0; temp[i] != '\0'; i++)
if (temp[i] < '0' || temp[i] > '9')
return NULL;
Number *n = newNumber(len);
for (int i = 0; temp[i] != '\0'; i++)
n->digits[i] = temp[i] - '0';
return n;
}
To multiply two numbers n1 and n2, we multiply n1 with each digit of n2, and accumulate the result shifted on the left by the position of the n2 digit in the final result.
For instance, to multiply 123*456, we compute 123*4 + 123*5*10 + 123*6*100. Note that *10 and *100 are simply left shifts.
We thus need a function that multiplies a number with a digit, and another function that accumulates a number with a left shift in a result number.
// multiply stores the result of n time digit in result.
// Requires the len of result is the len of n + 1.
void multiplyNumber(Number *n, char digit, Number *result) {
char carry = 0;
for (int i = r->len-1, j = n->len-1; i > 0; i--, j--) {
char x = n->digits[j] * d + carry;
r->digits[i] = x%10;
carry = x/10;
}
r->digits[0] = carry;
}
// accumutateNumber adds n with the left shift s to the number r.
// Requires the len of r is at least len of n + s + 1.
void accumulateNumber(Number *n, int s, Number *r) {
char carry = 0;
for (int i = r->len-1-s, j = n->len-1; j >= 0; i--, j--) {
char x = r->digits[i] + n->digits[j] + carry;
r->digits[i] = x%10;
carry = x/10;
}
r->digits[r->len-1-s-n->len] = carry;
}
Finally, we also need a function to print the number
void printNumber(Number *n) {
int i = 0;
// skip 0 at the front
while (i < n->len && n->digits[i] == 0)
i++;
if (i == n->len) {
printf("0\n");
return;
}
while (i < n->len)
putchar(n->digits[i++] + '0');
putchar('\n');
}
And this is it. We can now write the main function with the input of the numbers, the multiplication of number 1 with each digit of number 2 and accumulate the result with a shift to get the final result.
int main() {
printf("number 1: ");
Number *n1 = inputNumber();
if (n1 == NULL) {
printf("number 1 is invalid\n");
return 1;
}
printf("number 2: ");
Number *n2 = inputNumber();
if (n2 == NULL) {
printf("number 2 is invalid\n");
return 1;
}
Number *r = newNumber(n1->len+n2->len);
Number *tmp = newNumber(n1->len+1);
for (int i = 0; i < n2->len; i++) {
multiplyNumber(n1, n2->digits[n2->len-1-i], tmp);
accumulateNumber(tmp, i, r);
}
printf("result: ");
printNumber(r);
return 0;
}
Here you may have a look at a 'string only' version, multiplying like you would do with a pencil.
It works with 2 loops. The outer loop takes the digits of value2 from the right and multiplies in the inner loop with every digit of value1 from right. The right digit of the multiplication is stored in result, the rest goes in carry for the next inner loop.
At the end of the inner loop, carry is added to result.
After the first outer loop, we have to add previous results to our multiplication.
This is done in if(!first && *lresp) r += toI(*lresp)
The final loop moves the result to the start of the char array.
#include <stdio.h>
#include <stdlib.h>
#define toI(x) ((x)-'0')
#define toC(x) ((x)+'0')
#define max(a,b) ((a)>(b)) ? (a):(b)
char *mul(char *buf1, char *buf2) {
int size, v1, v2, r, carry=0, first=1;
char *startp1, *endp1, *lendp1, *startp2, *endp2;
char *startres, *endres, *resp, *lresp, *result;
for(endp1 = startp1 = buf1; *endp1; endp1++); // start and endpointer 1st value
for(endp2 = startp2 = buf2; *endp2; endp2++); // start and end pointer 2nd value
size = endp2-startp2 + endp1-startp1; // result size
startres = endres = resp = result = malloc(size+10); // some reserve
endres += size+10-1; // result end pointer
for(resp = startres; resp <= endres; resp++) *resp = '\0'; // init result
for(endp1--, endp2--, resp-=2; endp2>=startp2; endp2--, resp--, first=0) {
v2 = toI(*endp2); // current digit of value2
for(lresp = resp, lendp1 = endp1; lendp1 >= startp1; lendp1--, lresp--) {
v1 = toI(*lendp1); // current digit of value1
r = v1 * v2 + carry; // multiply + carry
if(!first && *lresp) r += toI(*lresp); // add result of previous loops
*lresp = toC(r%10); // store last digit
carry = r/10;
}
for( ; carry != 0; carry /= 10)
*lresp-- = toC(carry%10);
}
// we began right with reserve, now move to start of result
for(lresp++; lresp < endres; lresp++, startres++)
*startres=*lresp;
*startres = '\0';
return result;
}
int main() {
char *result = mul("123456789", "12345678");
printf("\n%s\n", result);
free(result);
}
i'm a beginner and my english is not well so sorry first. im trying to sum the numbers in a string (for a14fg5pk145 it returns 14+5+145), and it doesn't work:
"Exception thrown: read access violation.
str was 0x61."
this i my code:
void main()
{
int x, i;
char* pp;
char buffer[SIZE];
printf("Please enter numbers and letters:\n");
gets(buffer);
pp = buffer;
x = SumStr(*pp);
printf("%d", x);
}
int SumStr(char* str)
{
int sum=0, num=0, flag = 0;
while ((*str) != '\0')
{
while (((*str) > '1') && ((*str) < '9'))
{
if (flag == 0)
{
num += (*str);
flag = 1;
}
else if (flag == 1)
num = num * 10 + (*str);
str++;
}
if (flag == 0)
str++;
sum += num;
num = 0;
flag = 0;
}
return sum;
}
First problem with your code which is causing Exception.
x = SumStr(*pp);
it should be
x = SumStr(pp);
Because you should pass address of the string pointer not its first character by attaching asterix.
Second Issue that will not make it work is.
num += (*str);
and
num = num * 10 + (*str);
By (*str) you are actually adding the character ascii value instead of number.
This will solve the problem by changing the ascii value to number.
num += (*str) - '0';
num = num * 10 + (*str) - '0';
This may serve your purpose
#include<stdio.h>
#include<string.h>
int main()
{
int i, sum = 0, store;
char str[] = "a14fg5pk145asdasdad6";
int length = strlen(str);
for(i = 0; i < length; i++) {
store = 0;
while(isdigit(str[i])) {
store = (store * 10) + (str[i] - '0');
i++;
}
sum += store;
}
printf("%d\n", sum);
return 0;
}
output :
170
Pass pp, not *pp, to the function SumStr. *pp has the type char, and the function expects char *. In fact, you do not even need pp at all, just pass the buffer as the parameter.
Also:
Never use gets(). Because it is impossible to tell without knowing the
data in advance how many characters gets() will read, and because
gets() will continue to store characters past the end of the buffer, it
is extremely dangerous to use. It has been used to break computer
security. Use fgets() instead.
For this problem, I am to first take in two strings using fgets. I then need to check if the string is comprised entirely of digits thus making it a number. I was able to do this part recursively, but the next task is if the strings are numbers, I need to sum them up recursively as well. So for example,
the output of the program may look something like this:
First number > 9023905350290349
Second number > 90283056923840923840239480239480234
Sum is 90283056923840923849263385589770583
Again, I need to do this recursively, so I was thinking I could march along the stream of digits and add them together, but I am not so sure how to write this program recursively. Also since the input is in character form, I would also have to convert it to an integer, which I believe I can do by converting the individual characters to the integer ASCII value then subtracting 48 away from it. Any help would be appreciated. Thanks!
You're on the right track. Your recursive approach to checking if the input is a number looks something like the following, right? Notice that you can go ahead and subtract '0' from a character without bothering to convert it to 48 yourself.
int number_length(char *s, int pos) {
int d;
if (s[pos] == '\0') {
return pos;
}
d = s[pos] - '0';
if (d < 0 || d > 9) {
return -1;
}
return number_length(s, pos+1);
}
The above function returns -1 if the input is invalid, and the length of the number otherwise. We can use the length of the input numbers when we start the recursive addition process.
Where should the recursion begin? When we add a pair of numbers, it is convenient to start from the least significant digits.
If we have a pair of char * variables a and b pointing to the numbers, and if we know that a contains a_length digits and b contains b_length digits, then:
The least significant digit of a is at a_length-1.
The least significant digit of b is at b_length-1.
We don't know in advance how long the result is going to be, so let's build up the digits in an int * array starting from position 0. This means that we'll have the result digits in reverse, so we'll print them out starting from the end and going back to 0.
The core of the computation is this:
Given a position a_pos in a and b_pos in b, as well as a carry digit carry, compute the sum of the digits in a and b together with the carry digit.
Update the carry digit.
Add the result digit to the result array and update the length of the array.
In C, we can express the computation as follows:
d = a[a_pos--] + b[b_pos--] - 2*'0' + carry;
carry = (d >= 10 ? 1 : 0);
result[result_pos++] = d%10;
The expression a[a_pos--] + b[b_pos--] becomes invalid once a_pos or b_pos has become negative. In other words, we must deal with situations where we have run out of digits in one or both numbers. We must take care to:
Handle cases where we've already processed the most significant digit of a but not b, or b but not a.
When we've reached the end of both a and b, remember to check the carry digit: if it's 1, add it to the result and increment the length of the result.
Below is a complete implementation in ANSI C.
#include <stdio.h>
#include <string.h>
#define BUFFER_SIZE 8192
char a[BUFFER_SIZE], b[BUFFER_SIZE];
int result[BUFFER_SIZE];
int number_length(char *s, int pos) {
int d;
if (s[pos] == '\0') {
return pos;
}
d = s[pos] - '0';
if (d < 0 || d > 9) {
return -1;
}
return number_length(s, pos+1);
}
int add(char *a, int a_pos, char *b, int b_pos,
int *result, int result_pos, int carry) {
int d;
if (a_pos < 0 && b_pos < 0) {
if (carry == 1) {
result[result_pos++] = 1;
}
return result_pos;
}
if (a_pos < 0) {
result[result_pos++] = b[b_pos--] - '0' + carry;
carry = 0;
} else if (b_pos < 0) {
result[result_pos++] = a[a_pos--] - '0' + carry;
carry = 0;
} else {
d = a[a_pos--] + b[b_pos--] - 2*'0' + carry;
carry = (d >= 10 ? 1 : 0);
result[result_pos++] = d%10;
}
return add(a, a_pos, b, b_pos, result, result_pos, carry);
}
int main() {
int a_length, b_length, i, result_length;
printf("First number > ");
scanf("%s", a);
if ((a_length = number_length(a, 0)) == -1) {
printf("%s is not a number.\n", a);
return 0;
}
printf("Second number > ");
scanf("%s", b);
if ((b_length = number_length(b, 0)) == -1) {
printf("%s is not a number.\n", b);
return 0;
}
result_length = add(a, a_length-1, b, b_length-1, result, 0, 0);
for (i = result_length-1; i >= 0; --i) {
printf("%d", result[i]);
}
printf("\n");
return 0;
}
UPDATE: the comment below made me realize that I've obviously misunderstood the question. My previous solution of course wouldn't have worked with huge numbers like the ones in the OP's question. I've updated my answer accordingly as "right to left" approach. The only problem is that the resulting string can have a leading zero...
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void add_helper(const char *s1, const char *s2, int s1_pos, int s2_pos,
char *result, int pos, int carry) {
int d1 = 0;
int d2 = 0;
if (s1_pos >= 0) {
d1 = s1[s1_pos] - '0';
s1_pos--;
}
if (s2_pos >= 0) {
d2 = s2[s2_pos] - '0';
s2_pos--;
}
int d = d1 + d2 + carry;
carry = d > 9 ? 1 : 0;
result[pos] = '0' + (d % 10);
pos--;
if (s1_pos >= 0 || s2_pos >= 0)
add_helper(s1, s2, s1_pos, s2_pos, result, pos, carry);
else if (pos >= 0)
result[pos] = '0' + carry;
}
char *add_recurse(const char *s1, const char *s2) {
size_t s1_len = strlen(s1);
size_t s2_len = strlen(s2);
size_t result_len = (s1_len > s2_len ? s1_len : s2_len) + 1;
char *result = calloc(result_len, 1);
add_helper(s1, s2, s1_len-1, s2_len-1, result, result_len - 1, 0);
return result;
}
int main(int argc, char **argv)
{
char *num_str1 = "9023905350290349";
char *num_str2 = "90283056923840923840239480239480234";
printf("sum is %s\n", add_recurse(num_str1, num_str2));
}
Note that there is no error handling whatsoever and I assume the preconditions, that the input strings are valid strings consisting of only digits, which you said you have already checked it.
ADDED SINGLE PASS VERSION (for Jean-Baptiste Yunès, who considers the usage of 'strlen' a little bit cheating...):
int add_helper2(const char *s1, const char *s2, int acc1, int acc2,
int *s1_pos, int *s2_pos, int *pos, char **result) {
int carry = 0;
int d1 = 0;
int d2 = 0;
if (s1[acc1] || s2[acc2]) {
int t1 = (s1[acc1] != 0);
int t2 = (s2[acc2] != 0);
carry = add_helper2(s1, s2, acc1+t1, acc2+t2, s1_pos,
s2_pos, pos, result);
} else {
size_t result_len = (acc1 > acc2 ? acc1 : acc2) + 1;
*result = calloc(result_len, 1);
*s1_pos = acc1 - 1;
*s2_pos = acc2 - 1;
*pos = result_len - 1;
return 0;
}
if (*s1_pos >= 0) {
d1 = s1[*s1_pos] - '0';
*s1_pos -= 1;
}
if (*s2_pos >= 0) {
d2 = s2[*s2_pos] - '0';
*s2_pos -= 1;
}
int d = d1 + d2 + carry;
carry = d > 9 ? 1 : 0;
(*result)[*pos] = '0' + (d % 10);
*pos -= 1;
return carry;
}
char *add_recurse2(const char *s1, const char *s2) {
char *result;
int s1_pos, s2_pos, pos;
int carry = add_helper2(s1, s2, 0, 0, &s1_pos, &s2_pos, &pos, &result);
result[0] = '0' + carry;
return result;
}
Make it in a single recursive descent is not so easy, but this can make it :
char n1[] = "9023905350290349";
char n2[] = "90283056923840923840239480239480234";
char n3[1000];
char addchar(char c,char d,int r) {
return ((c-'0')+(d-'0')+r)%10 + '0';
}
int overflow(char c,char d,int r) {
return ((c-'0')+(d-'0')+r)/10;
}
int d;
int add(int i) {
if (d==0 && n1[i]!=0 && n2[i]!=0) {
int r= add(i+1);
if (d<0) {
n3[i+1] = addchar((i+d<0)?'0':n1[i+d],n2[i],r);
r = overflow((i+d<0)?'0':n1[i+d],n2[i],r);
}
if (d>0) {
n3[i+1] = addchar(n1[i],(i-d<0)?'0':n2[i-d],r);
r = overflow(n1[i],(i-d<0)?'0':n2[i-d],r);
}
if (d==0) {
n3[i+1] = addchar(n1[i],n2[i],r);
r = overflow(n1[i],n2[i],r);
}
if (i==0) {
n3[i] = r+'0';
r = 0;
}
return r;
}
if (d>=0 && n1[i]!=0) {
d++;
int r = add(i+1);
n3[i+1] = addchar(n1[i],(i-d<0)?'0':n2[i-d],r);
return overflow(n1[i],(i-d<0)?'0':n2[i-d],r);
}
if (d<=0 && n2[i]!=0) {
d--;
int r = add(i+1);
n3[i+1] = addchar((i+d<0)?'0':n1[i+d],n2[i],r);
return overflow((i+d<0)?'0':n1[i+d],n2[i],r);
}
n3[i+1] = '\0';
return 0;
}
int main() {
add(0);
printf("%s %s %s\n",n1,n2,n3);
}
The basic idea is to calculate the maximal length and the difference between lengths of numbers when descending through recursion, and then adding the right digits when returning from the recursion. The main difficulty is to manage the difference between the lengths.
This algorithm adds a leading zero to the result when there is no overflow on the left.
You could check for error in strings and do the sum at the same time,
#include <stdio.h>
#include <stdlib.h>
#define MAX_RES 1000
char *s1,*s2,*res;
int getcharval(char *s, int i) {
int n = s[i] - '0';
return n<0 || n>9 ? -1 : n;
}
char *recsum(int i1, int i2, int carry, char *pres) {
int n1 = !i1 ? 0 : getcharval(s1, --i1);
int n2 = !i2 ? 0 : getcharval(s2, --i2);
if (n1 < 0 || n2 < 0) return NULL;
int n = n1 + n2 + carry;
*--pres = (n % 10) + '0';
return !i1 && !i2 ? pres : recsum(i1, i2, n/10, pres);
}
with s1 points to string 1, s2 points to string 2, res points to the result area.
The recursive function recsum does the work, taking i1 decreasing index to next char in s1, i2 decreasing index to next char in s2, carry is the result from the previous calculation and pres (p-res) points to the next result char (+1) in res.
The helper function getcharval gets the digit from strings s index i, and returns that number (0 to 9) or -1 if the character is not a digit.
recsum returns a pointer to the result, i.e. a pointer into res where the result starts.
If there was an error in either string, the function returns NULL instead.
An example as how to use recsum, for a result having 1000 chars max (MAX_RES)
int main (int argc, char **argv)
{
s1 = "02313123";
s2 = "92382472699";
res = malloc(MAX_RES+1);
res[MAX_RES] = 0;
char *ret = recsum(strlen(s1), strlen(s2), 0, res+MAX_RES);
if (!ret) printf("There is an error\n");
else printf("%s + %s = %s\n", s1, s2, ret);
return 0;
}
Since If think this is homework, I only show pseudocode.
def str_sum(a,b):
index_a = len(a)
index_b = len(b)
res_len = max(len(a), len(b))
result = calloc(res_len+2, 1)
if not result:
raise OutOfMemory()
index_a -=1
index_b -= 1
acc = 0
res_index = 0
while (index_a >=0) or (index_b >= 0):
chr_a = '0'
chr_b = '0'
if(index_a >=0):
chr_a = a[index_a]
if(index_b >=0):
chr_b = b[index_b]
temp = acc + ord(chr_a) - ord('0') + ord(chr_b) - ord('0')
result[res_index] = chr((temp % 10) + ord('0'))
acc = temp / 10
index_a -=1
index_b -= 1
res_index += 1
inplace_rewind(result)
return ''.join(result)
print str_sum('9023905350290349', '90283056923840923840239480239480234')
How can I trim a string into pieces of N numbers of characters and then pass them as an array of strings into a function?
This in a part of my program that converts binary<->hex.
I tried doing the same thing with strings but it did not work.
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <String.h>
#define MAXDIGITS 8 // 8bits
int main()
{
int y;
printf("Binary-Hex convertor\n");
printf("Enter the Binary value : ");
scanf("%d", &y);
int i = MAXDIGITS - 1;
int array[MAXDIGITS];
while(y > 0)
{
array[i--] = y % 10;
y /= 10;
}
printf("%s", "-----------------\n");
printf("%s", "HEX:");
int x = array[0];
int x1 = array[1];
int x2 = array[2];
int x3 = array[3];
int x4 = array[4];
int x5 = array[5];
int x6 = array[6];
int x7 = array[7];
char buffer[50];
char buffer2[50];
char buffer3[50];
}
If its just binary to hex from a string then this is much easier....
char *input_string = "1001010101001010";
int count = 0;
int value = 0;
while ( *input_string != '\0' )
{
// Might be worth checking for only 0 and 1 in input string
value <<= 1;
value |= (int)((*input_string--) - '0');
if ( ++count == 8 || *input_string == '\0' )
{
// USE value to print etc, if you want to display use
// the following else you could store this in an array etc.
printf("%x ", value);
count = 0;
value = 0;
}
}
Do you have to null terminate the strings, do you have a limit on this memory used. Do you need to allocate the memory correctly etc? A bit more info would be useful
const char *input_string = "HELLO THIS IS SOME INPUT STRING";
int N = 4; // The number to split on
// Work out how many strings we will end up in
int number_of_strings = (strlen(input_string) + (N - 1)) / N;
// ALlow for an extra string if you want to null terminate the list
int memory_needed = ((number_of_strings + 1) * sizeof(char *)) + (number_of_strings * (N + 1));
char *buffer = malloc(memory_needed);
char **pointers = (char **)buffer;
char *string_start = (buffer + ((number_of_strings + 1) * sizeof(char *));
int count = 0;
while ( *input_string != '\0' )
{
// Fresh string
if ( count == 0 )
{
*pointers++ = string_start;
*pointers = NULL; // Lazy null terminate
}
// Copy a character
*string_start++ = *input_string++;
*string_start = '\0'; // Again lazy terminat
count++;
if ( count == N )
{
count = 0;
string_start++; // Move past the null terminated string
}
}
You can then pass (char **)buffer; to a routine. I havent actually tried this, ive been lazy in the terminating of the strings. You could just terminate at the end of a count run and the end of the while loop. This isnt exactly pretty code, but it should do the job. Bit more info on the other requirements might be good.
I want to build a program which sum a big integers in C.
So I'm ready with the code. The program compiling pass successfully with mingw and Visual C++ compiler. But I have a problem with the run part. The strange thing is that when I debug the program in Visual Studio there is no problems but when I run it my Windows show that the program stop working.
This is the code :
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <ctype.h>
#include "sum.h"
int isNumber(char* number)
{
int lenght = strlen(number);
int i,result = 0;
for (i = 0 ; i < lenght ; i++)
{
if (isdigit(*number++))
{
result = 1;
}
else
{
result = 0;
break;
}
}
return result;
}
int cti(char ch)
{
return ch - '0';
}
char* addZeros(char* number,int lenght)
{
int num_lenght = strlen(number),size = abs(lenght - num_lenght),i;
char* zeros = (char*)malloc(size);
strcpy(zeros,"");
zeros[size - 1] = '\0';
for (i = 0 ; i < abs(lenght - num_lenght) ; i++)
{
strcpy(&zeros[i],"0");
}
strncat(zeros,number,size);
number = (char*)malloc(sizeof(char)*size);
strncpy(number,zeros,size);
return number;
}
char* sum(char* numberOne,char* numberTwo)
{
if (numberOne == NULL || numberTwo == NULL)
return NULL;
if (!isNumber(numberOne) || !isNumber(numberTwo))
return NULL;
int CF = 0;
int lenghtOne = strlen(numberOne),lenghtTwo = strlen(numberTwo);
if (lenghtOne == 0 || lenghtTwo == 0)
return lenghtOne == 0 ? numberTwo : numberOne;
int max = lenghtOne > lenghtTwo? lenghtOne : lenghtTwo,index;
char* result = (char*)malloc(max);
int res = 0;
result[max] = '\0';
if (lenghtOne > lenghtTwo) numberTwo=addZeros(numberTwo,strlen(numberOne));
else if (lenghtOne < lenghtTwo) numberOne = addZeros(numberOne,strlen(numberTwo));
for ( index = max - 1 ; index >=0 ; index--)
{
res = cti(numberOne[index]) + cti(numberTwo[index]);
if (((res%10) + CF) > 9)
{
int num = ((res%10) + CF);
result[index] = (char)((int)'0'+num%10);
CF = num / 10;
}
else
{
result[index] = (char)((int)'0'+((res%10) + CF));
CF = res / 10;
}
}
return result;
}
int main(int argc, char *argv[])
{
char* num = "12345678";
char* num2= "2341";
char* result = sum(num,num2);
printf("%s\n",result);
return 0;
}
I think that the problem is somewhere in the pointers but I'm not absolutely sure about this. Can anyone help me?
The amount of memory you are allocating is not sufficient. It does not include space for the null character terminating the string and it does not take into account changes in the length of the result for sums such as "9" + "1". You are then writing the null terminating character after the end of the array.
You should malloc with the length like this:
char* result = (char*)malloc(max + 2);
result[max] = '\0';
This is incorrect since you only allocated max characters for result. I've not studied the logic in detail but allocating max+1 characters would fix this particular problem.