220 lines
6.4 KiB
C
220 lines
6.4 KiB
C
/*----------------------------------------------------------
|
|
* HTBLA-Leonding / Class: 2IHIF
|
|
* ---------------------------------------------------------
|
|
* Exercise Number: 0
|
|
* Title: Pyramid of Numbers
|
|
* Author: Marc Tismonar
|
|
* ----------------------------------------------------------
|
|
* Description:
|
|
* Calculates a pyramid of numbers, i.e., it multiplies a big
|
|
* integer by the number 2, its result by 3, etc. and then
|
|
* returns to the original value by subsequently dividing,
|
|
* again starting by 2, 3, etc.
|
|
* ----------------------------------------------------------
|
|
*/
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
/// The maximum number of digits allowed in a big int.
|
|
#define MAX_DIGITS 80
|
|
|
|
/** BigInt represents an integer number which can have MAX_DIGITS digits
|
|
*** @see MAX_DIGITS
|
|
*/
|
|
struct BigInt {
|
|
/** number of digits of the big int. */
|
|
int digits_count;
|
|
|
|
/** array of digits of big int. */
|
|
unsigned int the_int[MAX_DIGITS];
|
|
};
|
|
|
|
/** reset_big_int sets content to 0
|
|
*** @param *big_int The BigInt to be reset
|
|
*** @param startPos The start position where the reset shall begin
|
|
**/
|
|
void reset_big_int(struct BigInt *big_int, int startPos) {
|
|
if (startPos < 0 || startPos > MAX_DIGITS) {
|
|
startPos = 0;
|
|
}
|
|
|
|
startPos = MAX_DIGITS - startPos;
|
|
for (int i = startPos; i >= 0; i--)
|
|
{
|
|
big_int->the_int[i] = 0;
|
|
}
|
|
big_int->digits_count = 0;
|
|
}
|
|
|
|
/** set_big_int_length determines the length and sets it
|
|
*** @param *big_int The BigInt to determine the length
|
|
**/
|
|
void set_big_int_length(struct BigInt *big_int)
|
|
{
|
|
for (int i = 0; i < MAX_DIGITS; i++)
|
|
{
|
|
if(big_int->the_int[i] != 0)
|
|
{
|
|
big_int->digits_count = MAX_DIGITS - i;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
/** strtobig_int converts a string into a BigInt. If strtobig_int runs
|
|
*** against a character not between '0' and '9' the conversion stops
|
|
*** at this point.
|
|
*** @param *str The string to be converted.
|
|
*** @param len Number of characters in string to be converted.
|
|
*** @param *big_int The converted string now as BigInt.
|
|
* @return The number of characters converted.
|
|
*/
|
|
int strtobig_int(const char* str, int len, struct BigInt* big_int) {
|
|
reset_big_int(big_int, -1);
|
|
int conversions = 0;
|
|
int j = 0;
|
|
for (int i = len - 1; i >= 0; i--)
|
|
{
|
|
int big_int_position = MAX_DIGITS - j - 1;
|
|
int converted = str[i] - '0';
|
|
if (converted >= 0 && converted <= 9)
|
|
{
|
|
big_int->the_int[big_int_position] = converted;
|
|
conversions++;
|
|
}
|
|
else
|
|
{
|
|
big_int->digits_count = conversions;
|
|
//reset_big_int(big_int, conversions);
|
|
return conversions;
|
|
}
|
|
j++;
|
|
}
|
|
big_int->digits_count = conversions;
|
|
//reset_big_int(big_int, conversions);
|
|
return conversions;
|
|
}
|
|
|
|
/** print_big_int() prints a BigInt.
|
|
*** @param *big_int The BigInt to be printed.
|
|
*/
|
|
void print_big_int(const struct BigInt *big_int) {
|
|
for (int i = MAX_DIGITS - big_int->digits_count; i < MAX_DIGITS; i++)
|
|
{
|
|
printf("%d", big_int->the_int[i]);
|
|
}
|
|
}
|
|
|
|
/** multiply() multiplies a BigInt by an int.
|
|
*** @param big_int The BigInt to be multiplied.
|
|
*** @param factor The int value which is multiplied by BigInt.
|
|
*** @param *big_result The result of the multiplication.
|
|
*/
|
|
void multiply(const struct BigInt* big_int, int factor, struct BigInt* big_result) {
|
|
//set everything in the result to 0
|
|
reset_big_int(big_result, -1);
|
|
|
|
//no global overflow needed as it automatically saves it in the next place
|
|
//no need for '()' braces in the calculation, but used for a better view
|
|
for (int i = MAX_DIGITS - 1; i >= MAX_DIGITS - big_int->digits_count; i--) {
|
|
int result = (big_int->the_int[i] * factor) + big_result->the_int[i];
|
|
int overflow = result / 10;
|
|
int result_for_i = result - overflow * 10;
|
|
|
|
big_result->the_int[i] = result_for_i;
|
|
big_result->the_int[i - 1] = overflow;
|
|
}
|
|
set_big_int_length(big_result);
|
|
}
|
|
|
|
/** divide() multiplies a BigInt by an int.
|
|
*** @param big_int The BigInt to be divided.
|
|
*** @param divisor The int value by which we want to devide big_int.
|
|
*** @param *big_result The result of the division.
|
|
*/
|
|
void divide(const struct BigInt* big_int, int divisor, struct BigInt* big_result) {
|
|
//set everything in the result to 0
|
|
reset_big_int(big_result, -1);
|
|
|
|
//no global remainder needed as the remainder is automatically saved in the big_result
|
|
//no need for '()' braces in the calculation, but used for a better view
|
|
for (int i = MAX_DIGITS - big_int->digits_count; i < MAX_DIGITS; i++) {
|
|
int result = (big_int->the_int[i] + big_result->the_int[i]) / divisor;
|
|
int remainder = big_int->the_int[i] + big_result->the_int[i] - (result * divisor);
|
|
|
|
big_result->the_int[i + 1] = remainder * 10;
|
|
big_result->the_int[i] = result;
|
|
}
|
|
set_big_int_length(big_result);
|
|
}
|
|
|
|
/** copy_big_int() copies a BigInt to another BigInt.
|
|
*** @param from The source where we want to copy from.
|
|
*** @param *to The target where we want to copy to.
|
|
*/
|
|
void copy_big_int(const struct BigInt* from, struct BigInt* to) {
|
|
to->digits_count = from->digits_count;
|
|
for (int i = 0; i < MAX_DIGITS; i++) {
|
|
to->the_int[i] = from->the_int[i];
|
|
}
|
|
}
|
|
|
|
/**
|
|
*** main() reads the base number from which the pyramid has to be calculated
|
|
*** into an array of char. The max. length of this number is MAX_DIGITS.
|
|
*** The number is checked to contain only digits. If not the program exits.
|
|
*** Then the inputted number is converted into a big int by calling the
|
|
*** function strtobig_int().
|
|
*** After the conversion the tower is calculated by calling the functions
|
|
*** multiply(), print_big_int(), and copy_big_int() consecutively from 2 to
|
|
*** 9 and then again with divide() instead of multiply() from 2 to 9.
|
|
***
|
|
*/
|
|
int main(int argc, char* argv[])
|
|
{
|
|
printf("Pyramid of Numbers\n\n");
|
|
|
|
printf("Please enter a number: ");
|
|
char input_str[MAX_DIGITS];
|
|
scanf("%s", input_str);
|
|
|
|
struct BigInt original_big_int;
|
|
int len = strlen(input_str);
|
|
reset_big_int(&original_big_int, -1);
|
|
strtobig_int(input_str, len, &original_big_int);
|
|
|
|
struct BigInt changed_big_int;
|
|
copy_big_int(&original_big_int, &changed_big_int);
|
|
|
|
//multiply
|
|
for (int i = 2; i < 10; i++)
|
|
{
|
|
//create temp BigInt & multiply
|
|
struct BigInt temp;
|
|
multiply(&changed_big_int, i, &temp);
|
|
|
|
print_big_int(&changed_big_int);
|
|
printf(" * %d = ", i);
|
|
print_big_int(&temp);
|
|
printf("\n");
|
|
|
|
copy_big_int(&temp, &changed_big_int);
|
|
}
|
|
|
|
//divide
|
|
for (int i = 9; i > 1; i--)
|
|
{
|
|
//create temp BigInt & divide
|
|
struct BigInt temp;
|
|
divide(&changed_big_int, i, &temp);
|
|
|
|
print_big_int(&changed_big_int);
|
|
printf(" / %d = ", i);
|
|
print_big_int(&temp);
|
|
printf("\n");
|
|
|
|
copy_big_int(&temp, &changed_big_int);
|
|
}
|
|
|
|
return 0;
|
|
}
|