Tohle byl původně jeden z úkolů na ČVUT. Jen jsem si mírně upravil zadání pro vlastní potřebu a vyšel z toho takový pěkný prográmek. Bylo to skvělé cvičení v programování. Nic moc extra, ale hezky jsem se s tím pobavil, a chci se tedy pochlubit výsledkem.
Cílem úkolu bylo procvičit práci s poli v jazyku C. Výstup programuvypadá například takhle:
Stáhnout můžete zde: nasobeni.c.
/******************************************************************************* * * * NASOBENI CISEL * * * * Graficka simulace nasobeni dvou cisel * * * * Jiri Rohan Leden 2012 * ******************************************************************************* Jednotliva cisla nacitam jako retezce, abych mohl nasobit i skutecne velka cisla. Nezajimam se tak o preteceni datovych typu, nasobim a scitam cisla maximalne v radu desitek. Pozor si musim davat jen na velikost poli a spravnemu adresovani jejich prvku. Cisla v poli numbers[][] jsou ulozena pozpatku, cili sloupec 0 jsou jednotky, sloupec 1 jsou desitky, sloupec 2 stovky... Je to kvuli finalnimu scitani. Proste az vynasobim prvni cislo jednotlivymi cislicemi z druheho, a ziskam tak radu nezivysledku, proste jen sectu cisla v jednotlivych sloupcich. Po radcich jsou tam ulozena postupne od 0 vyse cisla A, B, mezivypocty a nakonec vysledek celeho nasobeni. O vypis na obrazovku se stara funkce printAll(). Teprve v ni resim jestli ma byt radek posunut doleva ci doprava, aby byla cisla zarovnana pod sebe atd. */ #include <stdio.h> #include <stdlib.h> #include <math.h> #include <ctype.h> #define MAX_NUMBER_LENGTH 100 #define NUMBER_A 0 #define NUMBER_B 1 #define OTHER 3 int getLastDigit(long long int number); void printLine(int len); void countSemiResults(int numbers[MAX_NUMBER_LENGTH][MAX_NUMBER_LENGTH], int* lines, int linesLen[MAX_NUMBER_LENGTH]); int getLen(int number[MAX_NUMBER_LENGTH]); void countResult(int numbers[MAX_NUMBER_LENGTH][MAX_NUMBER_LENGTH], int *lines, int linesLen[MAX_NUMBER_LENGTH]); void printEqRow(int line[MAX_NUMBER_LENGTH], int len, int number); void printAll(int numbers[MAX_NUMBER_LENGTH][MAX_NUMBER_LENGTH], int lines, int linesLen[MAX_NUMBER_LENGTH], int positiveA, int positiveB); void reverseFieldData(int number[MAX_NUMBER_LENGTH], int len); int checkForZero(int number[MAX_NUMBER_LENGTH], int len); int readInput(int number[MAX_NUMBER_LENGTH], int* positive); int getLastDigit(long long int number) { double lastDigit, num; lastDigit = modf(number/10.0, &num); return floor(lastDigit * 10 + 0.5); } void printLine(int len) { int i; for (i = 0; i < len; i++) printf("-"); printf("\n"); } void countSemiResults(int numbers[MAX_NUMBER_LENGTH][MAX_NUMBER_LENGTH], int* lines, int linesLen[MAX_NUMBER_LENGTH]) { int* numberA = numbers[NUMBER_A]; int* numberB = numbers[NUMBER_B]; int* semiResult = 0; int numberALength = linesLen[0]; int numberBLength = linesLen[1]; int idxB = 0, idxA = 0, tmp = 0; while (idxB < numberBLength) { semiResult = numbers[idxB + 2]; while (idxA < numberALength || tmp != 0) { if (numberB[idxB] == 0) break; semiResult[idxA] = idxA < numberALength ? getLastDigit(numberB[idxB] * numberA[idxA] + tmp) : tmp; tmp = (numberB[idxB] * numberA[idxA] + tmp) / 10; idxA++; linesLen[*lines]++; } idxA = 0; (*lines)++; idxB++; } } int getLen(int number[MAX_NUMBER_LENGTH]) { int res = MAX_NUMBER_LENGTH - 1; while (number[res] == 0) res--; return res; } void countResult(int numbers[MAX_NUMBER_LENGTH][MAX_NUMBER_LENGTH], int *lines, int linesLen[MAX_NUMBER_LENGTH]) { int idxRow, j, row = 2, column = 1; int length = linesLen[NUMBER_A] >= linesLen[NUMBER_B] ? linesLen[NUMBER_A] : linesLen[NUMBER_B]; length += *lines; int number = 0; while (column < length || number > 0) { for (j = 0, idxRow = row; j < column && idxRow > 1; j++, idxRow--) { if (idxRow >= *lines) continue; number += numbers[idxRow][j]; } numbers[*lines][column - 1] = getLastDigit(number); number = (number - getLastDigit(number)) / 10; linesLen[*lines]++; row++; column++; } (*lines)++; linesLen[*lines -1] = getLen(numbers[*lines - 1]); } void printEqRow(int line[MAX_NUMBER_LENGTH], int len, int number) { int idx, printSpace = 1; if (number == NUMBER_B) { printf(" X "); len -= 3; } for (idx = 1; idx <= len; idx++) { if (line[len - idx] == 0 && printSpace == 1) { if (line[len - idx - 1] != 0 && line[0] < 0) { printf("-"); line[0] *= -1; continue; } printf(""); continue; } else printSpace = 0; printf("%d", line[len - idx]); } printf("\n"); } void printAll(int numbers[MAX_NUMBER_LENGTH][MAX_NUMBER_LENGTH], int lines, int linesLen[MAX_NUMBER_LENGTH], int positiveA, int positiveB) { int i, charactersCount; int shift = 5; charactersCount = linesLen[lines - 1] + shift; numbers[NUMBER_A][0] *= positiveA; numbers[NUMBER_B][0] *= positiveB; numbers[lines - 1][0] *= (positiveA * positiveB); printEqRow(numbers[NUMBER_A] , charactersCount, NUMBER_A); printEqRow(numbers[NUMBER_B] , charactersCount, NUMBER_B); printLine(charactersCount); if (linesLen[NUMBER_B] == 1) { printEqRow(numbers[lines - 1], charactersCount, OTHER); return; } for (i = 2; i < lines - 1; ++i) { if (linesLen[i] != 0) printEqRow(numbers[i] , charactersCount, OTHER); if (i >1) charactersCount--; } charactersCount = linesLen[lines - 1] + shift; printLine(charactersCount); printEqRow(numbers[lines - 1], charactersCount, OTHER); } void reverseFieldData(int number[MAX_NUMBER_LENGTH], int len) { int i, tmp; for (i = 0; i < len / 2; i++) { tmp = number[i]; number[i] = number[len - 1 - i]; number[len - 1 - i] = tmp; } } int checkForZero(int number[MAX_NUMBER_LENGTH], int len) { int i; for (i = 0; i < len; i++) { if (number[i] != 0) return len; } return 1; } int readInput(int number[MAX_NUMBER_LENGTH], int* positive) { int idx = 0; int c; int continueReadingDontSave = 0; *positive = 1; while ((c = getchar())!= '\n') { if (idx == MAX_NUMBER_LENGTH || continueReadingDontSave) continue; if (c == '-') { if (idx > 0) { continueReadingDontSave = 1; continue; } (*positive) *= -1; continue; } if (isdigit(c)) { number[idx++] = c - 48; continue; } if (isalpha(c) || (idx > 0 && !isdigit(c))) continueReadingDontSave = 1; }; reverseFieldData(number, idx); idx = checkForZero(number, idx); return idx; } int main(int argc, char *argv[]) { int numbers[MAX_NUMBER_LENGTH][MAX_NUMBER_LENGTH]; int linesLen[MAX_NUMBER_LENGTH]; int lines = 2; int positiveA = 1, positiveB = 1; printf("=========================\n"); printf("==== Nasobeni cisel =====\n"); printf("=========================\n"); printf("Zadejte cislo A : "); linesLen[NUMBER_A] = readInput(numbers[NUMBER_A], &positiveA); printf("Zadejte cislo B : "); linesLen[NUMBER_B] = readInput(numbers[NUMBER_B], &positiveB); if (linesLen[NUMBER_A] == 0 || linesLen[NUMBER_B] == 0) { printf("Chybny vstup.\n"); return 0; } printf("\n"); countSemiResults(numbers, &lines, linesLen); countResult(numbers, &lines, linesLen); printAll(numbers, lines, linesLen, positiveA, positiveB); return 0; }