Обновить du3/program.c

This commit is contained in:
Bohdana Marchenko 2025-03-12 17:55:58 +00:00
parent 4254807502
commit c9f4b35f7a

View File

@ -4,7 +4,7 @@
#include <math.h> #include <math.h>
#include <ctype.h> #include <ctype.h>
#define EPSILON 0.001 // Tolerancia pre porovnanie reálnych čísel: ak je rozdiel dvoch čísel menší alebo rovný EPSILON, považujeme ich za rovnaké. #define EPSILON 0.001 // Tolerancia pre porovnanie reálnych čísel: ak je rozdiel menší alebo rovný EPSILON, považujeme čísla za rovnaké.
/* /*
* Funkcia trim_newline * Funkcia trim_newline
@ -36,7 +36,7 @@ void trim_newline(char *line) {
* - Ukazovateľ na prvý znak, ktorý nie je whitespace. * - Ukazovateľ na prvý znak, ktorý nie je whitespace.
*/ */
char* skip_spaces(char *str) { char* skip_spaces(char *str) {
while(*str && isspace((unsigned char)*str)) { while (*str && isspace((unsigned char)*str)) {
str++; str++;
} }
return str; return str;
@ -60,7 +60,7 @@ char* skip_spaces(char *str) {
* *
* Návratová hodnota: * Návratová hodnota:
* - 0, ak sa parsovanie podarilo úspešne. * - 0, ak sa parsovanie podarilo úspešne.
* - 1, ak nastala chyba (napr. nesprávny formát, chýbajúce číslo, operátor alebo '=') * - 1, ak nastala chyba (nesprávny formát, chýbajúce číslo, operátor alebo '=')
* *
* Príklad vstupu: * Príklad vstupu:
* " 10.0 / 2.0 = 5.0" * " 10.0 / 2.0 = 5.0"
@ -125,16 +125,16 @@ int parse_expression(char *line, float *num1, char *op, float *num2, float *resu
* *
* Parametre: * Parametre:
* - num1: Prvé číslo. * - num1: Prvé číslo.
* - op: Operátor, ktorý môže byť '+', '-', '*' alebo '/'. * - op: Operátor ('+', '-', '*' alebo '/').
* - num2: Druhé číslo. * - num2: Druhé číslo.
* - error: Ukazovateľ na premennú, do ktorej sa uloží 1, ak nastane chyba (napr. delenie nulou). * - error: Ukazovateľ, do ktorého sa uloží 1, ak nastane chyba (napr. delenie nulou).
* *
* Návratová hodnota: * Návratová hodnota:
* - Výsledok operácie, ak prebehne úspešne. * - Výsledok operácie, ak prebehne úspešne.
* - V prípade chyby (napr. delenie nulou) sa error nastaví na 1 a funkcia vráti 0. * - Ak nastane chyba, error je nastavený na 1 a funkcia vráti 0.
* *
* Príklad: * Príklad:
* calculate(10.0, '/', 2.0, &error) vráti 5.0, pričom error zostáva 0. * calculate(10.0, '/', 2.0, &error) vráti 5.0, error zostáva 0.
*/ */
float calculate(float num1, char op, float num2, int *error) { float calculate(float num1, char op, float num2, int *error) {
*error = 0; // Inicializácia chyby na 0 (žiadna chyba) *error = 0; // Inicializácia chyby na 0 (žiadna chyba)
@ -150,7 +150,7 @@ float calculate(float num1, char op, float num2, int *error) {
res = num1 * num2; res = num1 * num2;
break; break;
case '/': case '/':
// Pred delením overíme, či nedochádza k deleniu nulou // Kontrola delenia nulou; ak num2 je takmer 0, signalizujeme chybu
if (fabs(num2) < EPSILON) { if (fabs(num2) < EPSILON) {
*error = 1; // Chyba: delenie nulou *error = 1; // Chyba: delenie nulou
return 0; return 0;
@ -167,18 +167,17 @@ float calculate(float num1, char op, float num2, int *error) {
/* /*
* Funkcia process_line * Funkcia process_line
* --------------------- * ---------------------
* Spracuje jeden riadok vstupu obsahujúci matematický príklad a určí, či je príklad * Spracuje jeden riadok vstupu obsahujúci matematický príklad a určí, či je zápis
* zapísaný správne a či je výsledok správny. Výsledok sa uloží do parametra output. * správny a či je výsledok správny.
* *
* Postup: * Postup:
* 1. Skopíruje vstupný riadok do lokálneho bufferu a odstráni prípadný koncový znak nového riadku. * 1. Skopíruje vstupný riadok do lokálneho bufferu a odstráni prípadný koncový znak nového riadku.
* 2. Predpokladá sa, že riadok nie je prázdny (kontrola prázdnoty sa vykoná v main). * 2. Rozparsuje riadok na časti: prvé číslo, operátor, druhé číslo a očakávaný výsledok.
* 3. Pokúsi sa rozparsovať riadok na jednotlivé časti: prvé číslo, operátor, druhé číslo a výsledok. * 3. Ak parsovanie zlyhá, nastaví output na "CHYBA".
* 4. Ak parsovanie zlyhá, nastaví output na "CHYBA". * 4. Vykoná operáciu a ak nastane chyba (napr. delenie nulou), nastaví output na "ZLE".
* 5. Vykoná operáciu a porovná vypočítaný výsledok so zadaným výsledkom s toleranciou EPSILON. * 5. Zaokrúhli výsledok operácie na 2 desatinné miesta, pretože čísla zadané na max. 2 desatinné miesta.
* - Ak sa výsledok zhoduje, nastaví output na "OK". * 6. Porovná zaokrúhlený výsledok s očakávaným výsledkom. Ak sa líšia o viac ako EPSILON,
* - Ak sa výsledok nezhoduje, nastaví output na "ZLE". * nastaví output na "ZLE", inak na "OK".
* 6. V prípade delenia nulou, keď calculate vráti chybu, program nastaví output na "ZLE".
* *
* Parametre: * Parametre:
* - line: Vstupný riadok (napr. "10.0 / 2.0 = 5.0"). * - line: Vstupný riadok (napr. "10.0 / 2.0 = 5.0").
@ -207,14 +206,16 @@ void process_line(const char *line, char *output, size_t output_size) {
int calcError = 0; int calcError = 0;
float calculatedResult = calculate(num1, op, num2, &calcError); float calculatedResult = calculate(num1, op, num2, &calcError);
if (calcError) { if (calcError) {
// V prípade delenia nulou (alebo inej chyby v calcultion) vypíšeme "ZLE" // V prípade chyby (napr. delenie nulou) vypíšeme "ZLE"
snprintf(output, output_size, "ZLE"); snprintf(output, output_size, "ZLE");
return; return;
} }
// Porovnáme vypočítaný výsledok so zadaným výsledkom. // Zaokrúhľujeme výsledok operácie na 2 desatinné miesta, pretože vstupné čísla majú max. 2 desatinné miesta.
// Ak je absolútny rozdiel menší alebo rovný EPSILON, považujeme príklad za správny. float roundedResult = round(calculatedResult * 100) / 100;
if (fabs(calculatedResult - givenResult) <= EPSILON) {
// Porovnáme zaokrúhlený výsledok so zadaným výsledkom.
if (fabs(roundedResult - givenResult) <= EPSILON) {
snprintf(output, output_size, "OK"); snprintf(output, output_size, "OK");
} else { } else {
snprintf(output, output_size, "ZLE"); snprintf(output, output_size, "ZLE");
@ -233,10 +234,10 @@ void process_line(const char *line, char *output, size_t output_size) {
* 1+2=3 * 1+2=3
* 3.333+4.667=8.0 * 3.333+4.667=8.0
* *
* Program pre každý neprázdny riadok overí správnosť zápisu a výsledku a na štandardný výstup * Pre každý neprázdny riadok program overí správnosť zápisu a výsledku a na štandardný výstup
* vypíše "OK", "ZLE" alebo "CHYBA". * vypíše "OK", "ZLE" alebo "CHYBA".
* *
* Poznámka: Ak sa načíta prázdny riadok (obsahuje iba medzery), program ho ignoruje a ukončí sa. * Ak sa načíta prázdny riadok (iba medzery), program sa ukončí.
* *
* Ako skompilovať: * Ako skompilovať:
* gcc program.c -o program -lm * gcc program.c -o program -lm
@ -251,7 +252,7 @@ int main(int argc, char *argv[]) {
// Načítavame riadky zo štandardného vstupu (napr. z konzoly alebo súboru) // Načítavame riadky zo štandardného vstupu (napr. z konzoly alebo súboru)
while (fgets(buffer, sizeof(buffer), stdin) != NULL) { while (fgets(buffer, sizeof(buffer), stdin) != NULL) {
trim_newline(buffer); trim_newline(buffer);
// Ak je riadok prázdny (iba medzery), ukončíme cyklus a teda program // Ak je riadok prázdny (iba medzery), ukončíme cyklus a program
if (*skip_spaces(buffer) == '\0') { if (*skip_spaces(buffer) == '\0') {
break; break;
} }
@ -260,4 +261,4 @@ int main(int argc, char *argv[]) {
} }
return 0; return 0;
} }