Čer
9

Základy programování (IZP) – Projekt č. 1 a 2

By majlan  //  C, FIT VUT, Programování  //  Komentářů: 1

První projekt se věnuje kompresi a dekompresi řetězců, druhý projekt je zaměřen na matematické operace.

Hodnocení:
1. projekt – 4.5/5
2. projekt – 9/10

Je zakázáno kopírovat tyto zdrojové kódy! Veškeré projekty procházejí kontrolou na plagiátorství, takže se nepokoušejte použít mé kódy a to ani tak, že přepíšete názvy proměnných, nepomůže to. Výsledkem opisování je předvolání před komisi a většinou také odebrání zápočtu, takže vzhledem k tomu, že jsem nezpochybnitelným autorem následujících kódů, uškodíte pouze sami sobě.

Přejít na projekt č. 2

Projekt č. 1

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
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
/* Projekt c.1 - komprese a dekomprese textu
 * Autor: Milan Seitler, xseitl01@fit.vutbr.cz
 * Skupina: 36 (1BIB)
 * Datum: 2010/10/25
 * Nazev souboru: proj1.c
 
 * Popis programu: Program komprimuje vstupni text tim, ze opakujici se bloky o delce N
 zapisuje ve tvaru "pocet_opakovani""retezec". Takto vytvoreny text lze opet pomoci
 programu dekomprimovat zpet do puvodni podoby. V programu jsou vyuzita dve pole o
 delce N + 1 (k indexaci neni pouzita 0), ktera nejprve naplnime znaky. Pote je
 porovname, pokud jsou stejna, zvetsime pocet opakovani, pokud pocet dosahne 9, vypiseme
 pocet opakovani, vypiseme opakujici se znaky a opet nacteme dalsi znaky. Pokud se pole
 nerovnaji zjistime, kolik znaku bylo shodnych a pote vsechny neshodne znaky v prvnim
 poli posuneme na zacatek a doplnime je shodnymi znaky z druheho pole, to same provedeme
 s druhym polem, jen nove znaky donacteme ze vstupu. Takto postupne prochazime dokud
 na vstupu neni EOF, pripadny chybny znak.
 
 Pri dekomprimaci nacitame znaky, pokud je na vstupu cislo, pak vypiseme nasledujicich
 N znaku, pokud je mezi nimi cislo nebo nepovoleny znak, vypiseme chybovou hlasku a
 program se ukonci. */
 
#include <stdio.h> /* vstup a vystup */
#include <stdlib.h> /* obecne funkce */
#include <ctype.h> /* funkce pro testovani znaku - isdigit, isprint atd. */
#include <string.h> /* funkce strcmp */
#include <errno.h> /* chybove kody errno */
 
/* definice chybovych kodu */
#define K_OK 0 /* bez chyb */
#define K_CHYBNY_PARAMETR 1 /* chybny parametr prikazove radky */
#define K_CHYBNY_VSTUP 2 /* chybny vstup */
#define K_NEDOSTATEK_PAMETI 3 /* nedostatek pameti */
 
/*definice minima a maxima opakovani */
#define OPAK_MIN 1
#define OPAK_MAX 9
 
/* vytvorime funkcni prototypy */
void dekomprimuj(int c);
void komprimuj(int c);
void napoveda(void);
int dopln_pole(char *pole, char *pole2, int delka, int stejne, int *kon); /* posune druheho pole a donacte znaku ze vstupu */
int nacti_pole(char *pole, char *pole2, int delka, int *kon); /* nacte N znaku ze vstupu */
int porovnej_pole(char *pole, char *pole2, int delka); /* porovna obe pole */
void posun_pole(char *pole, char *pole2, int delka, int stejne); /* posune prvni pole a donacte do nej znaky z druheho pole */
void vycisti_pole(char *pole, int delka); /* vsem prvkum v poli nastavi hodnotu 0 */
void vypis_chybu(int kod); /* podle zadaneho parametru vypise chybovou hlasku a ukonci program */
void vypis_obe(char *pole, char *pole2, int delka, int *kon); /* vypise obe pole najednou, u prvniho testuje, zda je cele naplnene */
void vypis_opakovani(char *pole, int delka, int pocet_op); /* vypise pocet opakovani a opakujici se znaky */
void vypis_pole(char *pole, int delka, int *kon); /* vypise pouze jedno pole */
void zkopiruj_pole(char *pole, char *pole2, int delka); /* zkopiruje pole2 do pole */
 
int main(int argc, char *argv[])
{
  unsigned int n = 0;
  char *stop = NULL;
 
  /* pokud je pocet parametru 2 (argc == 3) a prvnim parametrem je -c, -h, nebo -d a N
  je vetsi nez nula a mensi nebo rovno UINT_MAX + 1 tak spusti prislusnou
  funkci, jinak vypise chybovou hlasku */
  if(argc == 3) {
    if(argv[2][0] > '0' && argv[2][0] <= '9') {
      n = strtoul(argv[2], &stop, 10);
      /* osetruje parametry typu "3ab" */
      if(errno == ERANGE || isalpha(*stop) || ispunct(*stop))
        vypis_chybu(K_CHYBNY_PARAMETR);
    } else {
      vypis_chybu(K_CHYBNY_PARAMETR);
    }
    if(strcmp("-d", argv[1]) == 0) {
      dekomprimuj(n);
    } else if(strcmp("-c", argv[1]) == 0) {
      komprimuj(n);
    } else {
      vypis_chybu(K_CHYBNY_PARAMETR);
    }
  } else if(argc == 2) {
    if(strcmp("-h", argv[1]) == 0) {
      napoveda();
    } else {
      vypis_chybu(K_CHYBNY_PARAMETR);
    }
  } else {
    vypis_chybu(K_CHYBNY_PARAMETR);
  }
  return 0;
}
 
void dekomprimuj(int n)
{
  char *znaky;
  int c, i, j, pocet;
 
  /* dynamicky vytvorime pole, testujeme, zda byla pridelena pamet */
  znaky = (char*) malloc(n * sizeof (char));
  if(znaky == NULL) {
    vypis_chybu(K_NEDOSTATEK_PAMETI);
  }
 
  vycisti_pole(znaky, n);
 
  do {
    c = getchar();
    /* kontrolujeme, zda je na vstupu cislo a zda jej nasleduje povoleny znak, jinak
    vypiseme chybovou hlasku */
    if(isdigit(c)) {
      pocet = c - '0';
      for(i = 0; i < n; i++) {
        c = getchar();
        if((isprint(c) || isspace(c)) && !isdigit(c)) {
          znaky[i] = c;
        } else {
          free(znaky);
          vypis_chybu(K_CHYBNY_VSTUP);
        }
      }
      /* vypis N znaku */
      for(i = 0; i < pocet; i++) {
        for(j = 0; j < n; j++) {
          c = znaky[j];
          putchar(znaky[j]);
        }
      }
    } else {
    /* jinak tiskneme posloupnost znaku */
    if(isprint(c) || isspace(c))
      putchar(c);
    }
  } while(c != EOF);
  free(znaky);
}
 
void komprimuj(int n)
{
  int c = 0, stejne = 0, pocet_op = 1, konec = 0;
  char *znaky1, *znaky2;
 
  /* dynamicky vytvorime pole, testujeme, zda byla pridelena pamet */
  znaky1 = (char*) malloc((n + 1) * sizeof (char));
  if(znaky1 == NULL) {
    vypis_chybu(K_NEDOSTATEK_PAMETI);
  }
 
  znaky2 = (char*) malloc((n + 1) * sizeof (char));
  if(znaky2 == NULL) {
    vypis_chybu(K_NEDOSTATEK_PAMETI);
  }
 
  vycisti_pole(znaky1, n);
  vycisti_pole(znaky2, n);
 
  /* nacteme N prvku do obou poli, pokud je v prvnim EOF, do druheho jiz nenacitame */
  c = nacti_pole(znaky1, znaky1, n, &konec);
  if(c != EOF)
    c = nacti_pole(znaky2, znaky1, n, &konec);
 
  /* porovname pole, pokud jsou stejna, zvetsime pocet opakovani, jinak pole
  posuneme, napr. pri vstupu labloslen udelame z |lab|los| |blo|sle|"*/
  while(c != EOF) {
    stejne = porovnej_pole(znaky1, znaky2, n);
    if(stejne == n) {
      if(pocet_op < OPAK_MAX) {
        pocet_op++;
      } else {
        /* pokud se pocet opakovani rovna 9, vypiseme opakovani */
        vypis_opakovani(znaky1, n, pocet_op);
        pocet_op = 1;
      }
      c = nacti_pole(znaky2, znaky1, n, &konec);
    } else {
      /* pokud se pole nerovnaji, ale pocet opakovani je vetsi nez 1, vypiseme opakovani,
      druhe pole zkopirujeme do prvniho, do druheho nacteme N znaku */
      if(pocet_op > OPAK_MIN) {
        vypis_opakovani(znaky1, n, pocet_op);
        pocet_op = 1;
        zkopiruj_pole(znaky1, znaky2, n);
        c = nacti_pole(znaky2, znaky1, n, &konec);
      } else {
        /* pokud je pocet opakovani roven 1, posuneme pole, viz radek 158 */
        posun_pole(znaky1, znaky2, n, stejne);
        c = dopln_pole(znaky1, znaky2, n, stejne, &konec);
      }
    }
  }
  /* vypis znaku pri dosazeni EOF - bud vypiseme opakovani a zbytek druheho pole
  nebo obe pole, az po EOF pripadne posledni nevypsany znak */
  if(pocet_op > OPAK_MIN) {
    vypis_opakovani(znaky1, n, pocet_op);
    vypis_pole(znaky2, n, &konec);
  } else {
    vypis_obe(znaky1, znaky2, n, &konec);
  }
  free(znaky1);
  free(znaky2);
}
 
void napoveda(void)
{
  printf("------------------------------------------------\n"
         "Program na kompresi a dekompresi vstupniho textu \n"
         "\n"
         "Autor: Milan Seitler, 1BIB, sk. 36\n"
         "\n"
         "Spusteni programu: ./proj -c N / -d N / -h\n"
         "-c - komprese\n"
         "-d - dekomprese\n"
         "-h - napoveda\n"
         "N - parametr, ktery urcuje delku opakujicich se bloku, musi byt vetsi nez nula a"
         " mensi nez UINT_MAX (4,294,967,295)\n"
         "\n"
         "Vstupni text lze zadavat bud primo z klavesnice nebo jej presmerovat z prikazove"
         " radky pomoci <<< \"blabla\", pripadne ze souboru: < vstup.txt\n"
         "Podobne lze smerovat take vystup do souboru > vystup.txt\n"
         "\n"
         "Program zpracovava vstupni text a hleda opakujici se bloky o delce N, ktere pri "
         "kompresi zapisuje ve tvaru 3abc. Takto vytvoreny text lze zpetne dekomprimovat, "
         "tedy z 3hop bude pri N = 3 hophophop.\n"
         "------------------------------------------------\n");
}
 
int dopln_pole(char *pole, char *pole2, int delka, int stejne, int *kon)
{
/* v druhem poli se posouvaji znaky, doplnuji se dalsimi ze vstupu, parametr delka urcuje
delku obou poli, parametr stejne urcuje, kolik znaku bylo pri porovnani stejnych,
do promenne kon se ulozi pozice pripadneho EOF */
  int i, j, x = 0;
  stejne++;
 
  /* znaky, ktere se nerovnaly, posuneme na zacatek pole */
  for(i = 1; i <= (delka - stejne); i++) {
    pole2[i] = pole2[i + stejne];
  }
 
  /* donacteme zbytek znaku ze vstupu, pri nepovolenem znaku vypiseme chybu */
  j = delka - stejne + 1;
  for(i = 1; i <= stejne; i++) {
    if((x = getchar()) != EOF) {
      if(isprint(x) || isspace(x)) {
        pole2[j] = x;
        j++;
      } else {
        free(pole);
        free(pole2);
        vypis_chybu(K_CHYBNY_VSTUP);
      }
    } else {
      /* do promenne kon ulozime pozici posledniho znaku, v pripade za nacteme
      nepovoleny znak */
      *kon = j;
      break;
    }
  }
  return x;
}
 
int nacti_pole(char *pole, char *pole2, int delka, int *kon)
{
/* do pole a pole2 (o velikosti delka) se nacitaji nove znaky, pozice
pripadneho EOF se ulozi do kon */
  int x, i;
 
  /* nacteme N znaku ze vstupu, pokud je na vstupu nepovoleny znak, vypiseme chybu */
  for(i = 1; i <= delka; i++) {
    if((x = getchar()) != EOF) {
      if(isprint(x) || isspace(x)) {
        pole[i] = x;
      } else {
        free(pole);
        free(pole2);
        vypis_chybu(K_CHYBNY_VSTUP);
      }
    } else {
      /* do promenne kon ulozime pozici posledniho znaku, v pripade za nacteme
      nepovoleny znak */
      *kon = i;
      break;
    }
  }
  return x;
}
 
int porovnej_pole(char *pole, char *pole2, int delka)
{
/* porovnava pole a pole2 (velikost "delka") */
  int i, stejne = 0;
 
  /* porovname znaky na i-te pozici v obou polich, vracime pocet stejnych znaku */
  for(i = 1; i <= delka; i++) {
    if(pole[i] == pole2[i]) {
      stejne++;
    } else {
      break;
    }
  }
  return stejne;
}
 
void posun_pole(char *pole, char *pole2, int delka, int stejne)
{
/* v bufferu pole se posouvaji znaky, ktere se doplni znaky z bufferu pole2
parametr delka urcuje velikost poli, parametr stejne urcuje, kolik bylo pri
porovnani stejnych znaku */
  int i, j;
  stejne++;
 
  /* nejprve vypiseme shodne znaky */
  for(i = 1; i <= stejne; i++)
    putchar(pole[i]);
 
  /* pote zbytek posuneme na zacatek pole */
  for(i = 1; i <= (delka - stejne); i++) {
    pole[i] = pole[i + stejne];
  }
 
  /* a donacteme znaky z druheho pole */
  j = delka - stejne + 1;
  for(i = 1; i <= stejne; i++) {
    pole[j] = pole2[i];
    j++;
  }
}
 
void vycisti_pole(char *pole, int delka)
{
  int i;
  for(i = 0; i < delka; i++)
    pole[i] = 0;
}
 
void vypis_chybu(int kod)
{
  switch(kod) {
    case 1:
      fprintf(stderr, "\n\nChybny parametr prikazove radky! Program bude ukoncen. \n\n");
      exit(1);
      break;
    case 2:
      fprintf(stderr, "\n\nChybny znak na vstupu! Program bude ukoncen. \n\n");
      exit(2);
      break;
    case 3:
      fprintf(stderr, "\n\nNedostatek volne pameti! Program bude ukoncen. \n\n");
      exit(3);
      break;
    default:
      break;
  }
}
 
void vypis_obe(char *pole, char *pole2, int delka, int *kon)
{
  int i;
  /* vypise obe pole (o velikosti "delka"), bud cele nebo po pozici EOF ci nepovoleneho znaku */
  for(i = 1; i <= delka; i++) {
    if(pole[i] != 0)
      putchar(pole[i]);
  }
  for(i = 1; i < *kon; i++) {
    putchar(pole2[i]);
  }
}
 
void vypis_opakovani(char *pole, int delka, int pocet_op)
{
  int i = 0;
 
  /* vypiseme pocet opakovani a blok textu o delce N (delka) */
  putchar(pocet_op + '0');
  for(i = 1; i <= delka; i++) {
    putchar(pole[i]);
  }
}
 
void vypis_pole(char *pole, int delka, int *kon)
{
  int i;
  for(i = 1; i < *kon; i++) {
    putchar(pole[i]);
  }
}
 
void zkopiruj_pole(char *pole, char *pole2, int delka)
{
  int i = 0;
  for(i = 1; i <= delka; i++) {
    pole[i] = pole2[i];
  }
}

Zpět nahoru

Projekt č. 2

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
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
/* Projekt c.2 - iteracni vypocty
 * Autor: Milan Seitler, xseitl01@fit.vutbr.cz
 * Skupina: 36 (1BIB)
 * Datum: 2010/11/19
 * Nazev souboru: proj2.c
 
 * Popis programu: program provadi celkem 4 pocetni operace: obecny logaritmus, hyperbolicky tangens,
   vazeny aritmeticky a vazeny kvadraticky prumer. Program spoustime s temito parametry
 
   -h - napoveda
   --logax sigdig a - obecny logaritmus o zakladu a, pocet platnych cislic vysledku urcuje sigdig
   --tanh sigdig - hyperbolicky tangens, pocet platnych cislic vysledku urcuje sigdig
   --wam - vazeny aritmeticky prumer
   --wqm - vazeny kvadraticky prumer
 
   Podrobny popis viz. dokumentace k projektu
 */
 
#include <errno.h>
#include <ctype.h>
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
 
#define K_OK 0 /* bez chyb */
#define K_CHYBNY_PARAMETR 1 /* chybny parametr prikazove radky */
#define K_CHYBNY_VSTUP 2 /* chybny vstup */
 
/* urcime si kody jednotlivych funkci, podle kterych budeme volat */
#define LOGAX 0
#define TANH 1
#define WAM 2
#define WQM 3
 
double wam(double cislo, double vaha); // vypocet vazeneho aritmetickeho prumeru
double wqm(double cislo, double vaha); // vypocet vazeneho kvadratickeho prumeru
double muj_sinh(double cislo, double eps); // vypocet sinh (pouzito ve vypoctu tanh)
double muj_cosh(double cislo, double eps); // vypocet cosh (pouzito ve vypoctu tanh)
double muj_tanh(double cislo, double eps); // vypocet tanh podle vzorce sinh/cosh
double muj_ln(double cislo, double eps); // vypocet prirozeneho logaritmu
double muj_logax(double cislo, double eps, double a); // vypocet logaritmu podle vzorce loga x = ln x / ln a
double preved_eps(int sigdig); // prevede sigdig na epsilon
void vypis_chybu(int kod); // vypise chybove hlaseni podle zadaneho kodu chyby
void napoveda(void);
void nacti_parametry(int argc, char *argv[]);
 
const double IZP_E = 2.7182818284590452354;        // e
const double log_horni_hranice = 2; // horni hranice pro konvergenci funkce muj_ln
const double log_dolni_hranice = 0.1; // dolni hranice pro konvergenci funkce muj_ln
 
// slouzi pro ukladani mezisouctu statistickych funkci
struct stat_hodnoty {
  double citatel;
  double jmenovatel;
} stat_h;
 
// struktura slouzi k nacteni a osetreni parametru ve funkci nacti_parametry
struct parametry {
  double eps, zaklad_log;
  int sigdig, spust; // do promenne spust ukladame kod funkce, kterou chceme spustit, ten nacteme z prikazove radky
  char *stop; // tento pointer pouzijeme pri kontrole, zda parametry sigdig a "a" byly cislo
} param;
 
int main(int argc, char *argv[])
{
    int temp1 = 0, temp2 = 0; // promenne pro uchovani vysledku funkce scanf a promenna chyba pro pripadny vypis nan
    double cislo1 = 0, cislo2 = 0, vysledek = 0;
 
    nacti_parametry(argc, argv); // zpracujeme parametry ve specialni funkci, ulozi se do struktury param
 
    while((temp1 = scanf("%le", &cislo1)) != EOF) { // nacita hodnoty dokud na vstup neprijde EOF ci neplatny znak
      if(temp1 == 0) { // pokud nacte neplatny znak, "preskoci" jej, aby se program nezacyklil
        scanf("%*s");
        vysledek = NAN;
        printf("%.10e\n", vysledek);
        vypis_chybu(K_CHYBNY_VSTUP);
      }
      switch(param.spust) { // podle kodu spusti prislusny program
        case 0:
          vysledek = muj_logax(cislo1, param.eps, param.zaklad_log);
          break;
        case 1:
          vysledek = muj_tanh(cislo1, param.eps);
          break;
        case 2:
          temp2 = scanf("%le", &cislo2); // pokud jde o statistickou funkci, nacteme druhe cislo
          if(temp2 == 0) { // pokud neni nacteno cislo, nahlasime chybu (dale vypiseme nan, ukoncime program)
          vysledek = NAN;
          printf("%.10e\n", vysledek);
          vypis_chybu(K_CHYBNY_VSTUP);
          break;
          }
          vysledek = wam(cislo1, cislo2);
          break;
        case 3:
          temp2 = scanf("%le", &cislo2);
          if(temp2 == 0) {
          vysledek = NAN;
          printf("%.10e\n", vysledek);
          vypis_chybu(K_CHYBNY_VSTUP);
          break;
          }
          vysledek = wqm(cislo1, cislo2);
          break;
        default:
          break;
      }
      printf("%.10e\n", vysledek);
    }
    return EXIT_SUCCESS;
}
 
double wam(double cislo, double vaha) // pocita vazeny aritmeticky prumer
{
  if(vaha < 0) { // zapornou vahu oznacime jako naplatny vstup
    cislo = NAN;
  }
  stat_h.citatel += cislo * vaha; // predchozi vypocty mame ulozeny ve strukture
  stat_h.jmenovatel += vaha;
  return stat_h.citatel / stat_h.jmenovatel;
}
 
double wqm(double cislo, double vaha) // pocita vazeny kvadraticky prumer
{
  if(vaha < 0) {
    cislo = NAN; // zapornou vahu oznacime jako naplatny vstup
  }
  stat_h.citatel += (cislo * cislo) * vaha; // predchozi vypocty mame ulozeny ve strukture
  stat_h.jmenovatel += vaha;
  return sqrt(stat_h.citatel / stat_h.jmenovatel);
}
 
double muj_sinh(double cislo, double eps)
{
  double soucet = cislo;
  double soucet_p = 0;
  double clen = cislo; // prvni clen je x
  double citatel = 0, jmenovatel = 0;
  int i = 3;
  double mocnina = cislo * cislo; // pro urychleni vypoctu spocitame mocninu "predem"
 
  citatel = cislo * cislo * cislo;
  jmenovatel = 3 * 2;
  clen = citatel / jmenovatel; // rucne spocitame druhy clen
  soucet_p = soucet;
  soucet = soucet + clen; // a soucet prvnich dvou clenu
 
  // pocitame pomoci tayorova rozvoje: x + (x ^ 3) / 3! + (x ^ 5) / 5! + ...
  while(fabs(soucet - soucet_p) > eps) {
    i += 2;
    citatel *= mocnina; // predchozi citatel nasobime hodnotou cislo^2, ziskame tak cislo^i
    // v jmenovateli pridavame postupne cleny faktorialu o dva vyssi, tj. napr. 5! = 5 * 4 * 3!
    jmenovatel *= (i * (i - 1));
    clen = citatel / jmenovatel;
    soucet_p = soucet; // ulozime predchozi soucet, abychom mohli testovat, zda se provede dalsi opakovani cyklu
    soucet += clen;
  }
  return soucet;
}
 
double muj_cosh(double cislo, double eps)
{
  double soucet = 1;
  double soucet_p = -1;
  double clen = 1; // prvni clen je 1
  int i = 0;
  double citatel = 1, jmenovatel = 1;
  double mocnina = cislo * cislo; // pro urychleni vypoctu spocitame mocninu "predem"
 
  // pocitame pomoci tayorova rozvoje: 1 + (x ^ 2) / 2! + (x ^ 4) / 4! + ...
  while(fabs(soucet - soucet_p) > eps) {
    i += 2;
    citatel *= mocnina; // predchozi citatel nasobime hodnotou cislo^2, ziskame tak cislo^i
     // v jmenovateli pridavame postupne cleny faktorialu o dva vyssi, tj. napr. 6! = 6 * 5 * 4!
    jmenovatel *= (i * (i - 1));
    clen = citatel / jmenovatel;
    soucet_p = soucet; // ulozime predchozi soucet, abychom mohli testovat, zda se provede dalsi opakovani cyklu
    soucet += clen;
  }
  return soucet;
}
 
double muj_tanh(double cislo, double eps) {
  double vysl, sinh_v, cosh_v;
  sinh_v = muj_sinh(cislo, eps);
  cosh_v = muj_cosh(cislo, eps);
  if(sinh_v == INFINITY) { // pokud je vysledek sinh (staci testovat pouze jednu fci) inf, vracime 1
    vysl = 1;
  } else if(sinh_v == -INFINITY) { // pokud je -inf, vracime -1
    vysl = -1;
  } else { // jinak spocitame vysledek jako podil sinh / cosh
    vysl =  sinh_v / cosh_v;
  }
  return vysl;
}
 
double muj_ln(double cislo, double eps)
// pocitame prirozeny logaritmus pomoci rozvoje 2 * (((x - 1) / (x + 1)) + (1 / 3 * (x - 1 / x + 1)^3) + ...)
// tento vypocet je nejefektivnejsi pro hodnoty v rozsahu <0.1, 2>, proto hodnoty mimo tento interval do nej musime prevest
{
  double soucet = 0;
  double clen = 0;
  double mocnina = 0;
  int i = 1, pocet_v = 0, pocet_m = 0;
 
  if(cislo == INFINITY)
    return cislo;
 
  if(fabs(cislo) > log_horni_hranice) { // prevod cisel vyssich nez 2
    while(fabs(cislo) > log_horni_hranice) {
      cislo = cislo / IZP_E;
      pocet_v += 1;
    }
  } else if(fabs(cislo) < log_dolni_hranice ) { // prevod cisel mensich nez 0.1
     while(fabs(cislo) < log_dolni_hranice) {
      cislo = cislo * IZP_E;
      pocet_m += 1;
    }
  }
 
  double citatel = cislo - 1, jmenovatel = cislo + 1;
  double citatel2 = 0, mocnina2 = 0;
 
  mocnina = jmenovatel;
  clen = 2 * (citatel / jmenovatel); // vypocet prvniho clenu
  soucet = clen;
  citatel2 = (cislo - 1) * (cislo - 1); // pro urychleni vypoctu si dopredu spocitame hodnotu (x - 1)^2
  mocnina2 = (cislo + 1) * (cislo + 1); // pro urychleni vypoctu si dopredu spocitame hodnotu (x + 1)^2
 
  while(fabs(clen) > eps) {
    i += 2;
    citatel *= citatel2; // predchozi citatel nasobime (x - 1)^2
    mocnina *= mocnina2; // odobne ve jmenovateli
    jmenovatel = i * mocnina; // a jeste vynasobime hodnotou i
    clen = 2 * (citatel / jmenovatel); // cely clen musime dle matematicke definic nasobit 2
    soucet += clen;
  }
 
  // pro prevod cisla do intervalu <0.1, 2> jsme pouzili vztah ln(x) = ln(r) + m * ln(z)
  // kde r je cislo z intervalu <0.1, 2>, m je pocet deleni, ktere jsme potrebovali, aby cislo bylo v intervalu
  // z je cislo, kterym jsme delili, z = e, tedy ln(e) = 1, z toho vyplyva, ze k vysledku ln(x) musime pricist jeste m
  // stejne postupujeme i pri cisle mensim nez 0.1, kde vsak nasobime cislem e a od vysledku m odcitame
  if(pocet_v > 0) {
    soucet += pocet_v;
  } else if(pocet_m > 0) {
    soucet -= pocet_m;
  }
  return soucet;
}
 
double muj_logax(double cislo, double eps, double a)
{
  double vysledek = 0;
  // dle matematicke definice testujeme specialni vstupy
  if(cislo < 0) {
    vysledek = NAN;
  } else if (cislo == 0 && a > 1) {
    vysledek = -INFINITY;
  } else if (cislo == 0 && a < 1) {
    vysledek = INFINITY;
  } else if (cislo == INFINITY && a > 1) {
    vysledek = INFINITY;
  } else if (cislo == INFINITY && a < 1) {
    vysledek = -INFINITY;
  } else {
    vysledek = muj_ln(cislo, eps) / muj_ln(a, eps);
  }
  return vysledek;
}
 
void vypis_chybu(int kod) // podle obdrzeneho chyboveho kodu vypiseme chybove hlaseni na stderr a ukoncime program
{
  switch(kod) {
    case 1:
      fprintf(stderr, "\n\nChybny parametr prikazove radky! Program bude ukoncen. \n\n");
      exit(1);
      break;
    case 2:
      fprintf(stderr, "\n\nChybny znak na vstupu! Program bude ukoncen. \n\n");
      exit(2);
      break;
    default:
      break;
  }
}
 
double preved_eps(int sigdig) // prevadi pocet platnych cislic na eps
{
  double eps = 0.1;
  while(sigdig--)
    eps *= 0.1;
 
  return eps;
}
 
void napoveda(void)
{
  printf("\n\n"
         "Iteracni vypocty\n"
         "Autor: Milan Seitler\n"
         "\n"
         "Spusteni programu: ./proj2 -h | --logax sigdig a | --tanh sigdig | --wam | --wqm"
         "-h - napoveda\n"
         "--logax - obecny logaritmus\n"
         "--tanh - hyperbolicky tangens\n"
         "--wam - vazeny aritmeticky prumer\n"
         "--wqm - vazeny kvadraticky prumer \n"
         "sigdig - pocet platnych cislic\n"
         "a - zaklad logaritmu\n\n"
         "Program pocita tyto funkce s pouzitim iteracnich vypoctu. U logax a tanh uzivatel zadava"
         " pocet platnych cislic, ktere urcuji pocet cislic od prvni nenulove cislice, ktere budou"
         " odpovidat \"spravnemu\" vysledku.\n\n");
  exit(EXIT_SUCCESS);
}
 
void nacti_parametry(int argc, char *argv[])
{
    if(argc == 4) { // pokud uzivatel zada logax
      param.zaklad_log = strtod(argv[3], &param.stop);
      if(errno == ERANGE || isalpha(*param.stop) || ispunct(*param.stop) || param.zaklad_log == 1 || param.zaklad_log <= 0) // testujeme, zda je parametr a cislo typu double
        vypis_chybu(K_CHYBNY_PARAMETR);
      param.sigdig = strtoul(argv[2], &param.stop, 10);
      if(errno == ERANGE || isalpha(*param.stop) || ispunct(*param.stop) || param.sigdig <= 0) // testujeme, zda je parametr sigdig cislo typu int
        vypis_chybu(K_CHYBNY_PARAMETR);
      if(strcmp("--logax", argv[1]) == 0) { // testujeme, zda uzivatel spravne napsal parametr pro funkci
        param.eps = preved_eps(param.sigdig); // prevedeme sigdig na epsilon
        param.spust = LOGAX;
      } else {
        vypis_chybu(K_CHYBNY_PARAMETR);
      }
    } else if(argc == 3) { // pokud uzivatel zada tanh
      param.sigdig = strtoul(argv[2], &param.stop, 10);
      if(errno == ERANGE || isalpha(*param.stop) || ispunct(*param.stop) || param.sigdig <= 0) // testujeme, zda je parametr sigdig cislo typu int
        vypis_chybu(K_CHYBNY_PARAMETR);
      if(strcmp("--tanh", argv[1]) == 0) { // testujeme, zda uzivatel spravne napsal parametr pro funkci
        param.eps = preved_eps(param.sigdig); // prevedeme sigdig na epsilon
        param.spust = TANH;
      } else {
        vypis_chybu(K_CHYBNY_PARAMETR);
      }
    } else if(argc == 2) { // pokud uzivatel zada stat. fce
      if(strcmp("--wam", argv[1]) == 0){ // testujeme, zda uzivatel spravne napsal parametr pro funkci
        param.spust = WAM;
      } else if(strcmp("--wqm", argv[1]) == 0) { // testujeme, zda uzivatel spravne napsal parametr pro funkci
        param.spust = WQM;
      } else if(strcmp("-h", argv[1]) == 0) {
        napoveda();
      } else {
        vypis_chybu(K_CHYBNY_PARAMETR);
      }
    }
}

Zpět nahoru

1 komentář k “Základy programování (IZP) – Projekt č. 1 a 2”

  • Dobre ty… Až na to, že máš zakázané použiť dynamickú alokáciu v projekte 1

    VA:F [1.9.20_1166]
    +2 / -0

Vyjádři svůj názor



Zajímá vás cokoliv o mobilních aplikacích? Uvažujete o spolupráci? Kontaktujte mne na seitler@reinto.cz

O mně

Jmenuji se Milan Seitler a jsem spoluzakladatelem společnosti Reinto s.r.o., ve které se věnujeme mobilním i webovým aplikacím a marketingu.

Zabývám se celým procesem tvorby mobilních a webových aplikací. Nejvíce se věnuji návrhu aplikace a UX/UI designu. Kladu velký důraz na jednoduchost a srozumitelnost uživatelského rozhraní.

Zajímám se o online i offline podnikání, fascinují mě úspěšní lidé, kteří se nebojí tvrdé práce. Mou hlavní motivací je konkurence, která mě vždy nutí jít do všeho naplno, protože nerad prohrávám.

Mám rád hudbu, knížky, sport a cestování.

milan@seitler.cz

Odkazy

Inzerujte zde!

Kupte si odkaz! PR 3, SR 2

Inzerujte zde!

Kupte si odkaz! PR 3, SR 2

Inzerujte zde!

Kupte si odkaz! PR 3, SR 2

Partner links