-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.c
261 lines (188 loc) · 9.39 KB
/
main.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
static const char END_OF_LINE = '\0';
static const char ZERO_ASCII = '0';
/*
* Reverses the string. String is passed pointer. So technically don't need a return char*
* But still return type char* used so that it can also be directly used with return statement
*/
char* reverse_string(char *string_to_reverse)
{
char *pointer1, *pointer2;
if (! string_to_reverse || ! *string_to_reverse)
return string_to_reverse;
for (pointer1 = string_to_reverse,
pointer2 = string_to_reverse + strlen(string_to_reverse) - 1;
pointer2 > pointer1; ++pointer1, --pointer2) {
*pointer1 ^= *pointer2;
*pointer2 ^= *pointer1;
*pointer1 ^= *pointer2;
}
return string_to_reverse;
}
/*
* Multiplying first number by each digit of second number by passing digit of second number one by one
*/
void single_step_multiplication(char *primary_number_as_string,
int secondary_number_digit, char *wip_answer, int secondary_number_digit_position) {
char carry_forward = 0, single_digit_number = 0 , wip_length_counter = 0;
/*
* Depending on which layer it is, add tailing zero. As you understand, with digit position at unit
* ten, hundred, thousand etc position, you need to accordingly add tailing zeros to
*/
while(wip_length_counter < secondary_number_digit_position)
wip_answer[wip_length_counter++] = ZERO_ASCII;
/*
* so work in progress answer has tailing 0 basis secondary number digit position in second_number
*/
int primary_number_length_counter = strlen(primary_number_as_string) -1 ;
/*
* Now traverse the first number and multiply its each digit with second number's digit passed
*/
for(; primary_number_length_counter >= 0 ; primary_number_length_counter--) {
/*
* Simple maths of multiplying two numbers and if result is greater than single digit then
* carry forward the second digit to add in the next cycle of digit multiplication
*/
single_digit_number = primary_number_as_string[primary_number_length_counter] - ZERO_ASCII;
single_digit_number = single_digit_number * secondary_number_digit + carry_forward;
carry_forward = single_digit_number / 10;
single_digit_number -= carry_forward * 10;
wip_answer[wip_length_counter] = single_digit_number + ZERO_ASCII;
wip_length_counter++;
}
/*
* The layer can be longer so continue processing it by checking if there is a carry forward to
* add to it. And if so do it. Because work in progress length counter has already incremented
* towards the end of loop, it would be pointing to an empty cell. Note entry processing is
* done in this function from left to right as the number string is reverse
*/
if (carry_forward != 0 )
wip_answer[wip_length_counter] = carry_forward + ZERO_ASCII;
}
/*
* When you multiply first number with a digit of second number, you have one layer of number
* And when you multiply first number with another digit of second number, then you have one more layer
* So you need to keep adding these layers with a shift, as you do it conventionally
*/
void paired_layer_addition(char* wip_answer, char* final_answer) {
int wip_answer_counter = 0;
char final_answer_digit, wip_answer_digit, net_of_digits, carry_forward = 0;
for(; wip_answer_counter < strlen(wip_answer); wip_answer_counter++) {
/*
* final answer holds values from previous paired layer addition, so we check if final answer
* and work in progress aligned digits are added, carry forward taken to next and all finsihed
*/
if(wip_answer_counter < strlen(final_answer)) {
final_answer_digit = final_answer[wip_answer_counter] - ZERO_ASCII;
wip_answer_digit = wip_answer[wip_answer_counter] - ZERO_ASCII;
net_of_digits = final_answer_digit + wip_answer_digit + carry_forward;
carry_forward = (net_of_digits / 10);
net_of_digits = net_of_digits - 10 * carry_forward;
final_answer[wip_answer_counter] = net_of_digits + ZERO_ASCII;
/*
* Then start with just work in progress layer digits, if carry forward, then add to it, and if it
* again results in carry forward continue until last digit is done
*/
} else {
wip_answer_digit = wip_answer[wip_answer_counter] - ZERO_ASCII;
net_of_digits = wip_answer_digit + carry_forward;
carry_forward = (net_of_digits / 10);
net_of_digits = net_of_digits - 10 * carry_forward;
final_answer[wip_answer_counter] = net_of_digits + ZERO_ASCII;
}
}
/*
* Because loop ends with the length of work in progress answer but there can be a carry forward
* left to adjust in the final number, this extra step is performed
*/
if(carry_forward)
final_answer[wip_answer_counter] = carry_forward + ZERO_ASCII;
}
void digit_by_digit_processing(char* first_number, char* second_number, char* wip_answer, char* final_answer) {
/*
* We reverse the second number string so that we pick digits left to right instead of right to left
* as it is easier to traverse left to right instead of right to left
*/
reverse_string(second_number);
/*
* This counter helps us keep track of up to which position we have used digits of second number
* and also this same variable is used to add zeros to the layer depending on which position digit
* it was
*/
int second_number_length_counter = 0;
/*
* Variables to hold single digits extracted from second number to pass for multiple with first number
*/
char multiplier_digit;
for(;second_number_length_counter < strlen(second_number); second_number_length_counter++) {
wip_answer = (char*)malloc(sizeof(char) * (strlen(first_number) + second_number_length_counter + 1));
multiplier_digit = second_number[second_number_length_counter] - ZERO_ASCII;
/*
* Fill the work in progress answer with end of line character
*/
memset(wip_answer, END_OF_LINE, strlen(wip_answer));
single_step_multiplication(first_number,
multiplier_digit, wip_answer,
second_number_length_counter);
/*
* Check if we have two layers to start addition, if not copy the starting layer into final answer
* and thereafter new layers would be added to final answer, result stored back in final answer
*/
final_answer[0] == END_OF_LINE ? strcpy(final_answer, wip_answer) : paired_layer_addition(wip_answer, final_answer);
/*
* Must free the work in progress variable as it is not used beyond this point
*/
free(wip_answer);
}
}
char* multiply(char* first_passed_number, char* second_passed_number) {
// Initialized variable to create a program copy
char* first_number, *second_number, *wip_answer, *final_answer;
// Allocating memory equivalent to the length of first string value passed on command line
first_number = (char*)malloc(sizeof(char) * strlen(first_passed_number));
// Allocating memory equivalent to the length of second string value passed on command line
second_number = (char*)malloc(sizeof(char) * strlen(second_passed_number));
/*
* Multiplication results in total number of digits, which as much as n + 2
* where n is the sum of total digits in first number and second number.
* As we have to hold the final multiplication answer spanning over n + 2 digits
* we need to allocate that space for final answer
*/
final_answer = (char*)malloc(sizeof(char) * (strlen(first_passed_number) +
strlen(second_passed_number) + 4));
/*
* Fill the variable with end of line characters, so that during operation, when used,
* if partially occupied and string length to be calculated, random memory garbage should
* not get counted
*/
memset(final_answer, END_OF_LINE, strlen(final_answer));
strcpy(first_number, first_passed_number);
strcpy(second_number, second_passed_number);
/*
* This function plans out executing multiplication by using first number and multiply
* each digit of second number. Multiplying first number with each digit of second number results
* in layers of results that have to added with carry forwards like traditional multiplication
*/
digit_by_digit_processing(first_number, second_number, wip_answer, final_answer);
/*
* All done, so no need of first and second number, free them up
*/
free(first_number);
free(second_number);
/*
* Return the reverse of the string as we have been operating from left to right
* And it is time to show to the correct flipped string
*/
return reverse_string(final_answer);
}
int main(int argc, char **argv) {
// command line arguments, which are as string are passed as pointers to the multiply function
char* result = multiply(argv[1], argv[2]);
// print the result
printf("Result: %s\n",result);
// because result is a pointed and has been passed a malloc variable, it should be freed before exiting
free(result);
return 0;
}