This repository has been archived by the owner on Feb 1, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 7
/
proj1.c
298 lines (278 loc) · 8.88 KB
/
proj1.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
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
/*
* Projekt c.1 - Histogram
* Autor: Roman Blanco, [email protected]
* Skupina: 11 (1BIA)
* Datum: 19.10.2012
* Soubor: proj1.c
* Projekt: Tvorba histogramu, projekt c. 1 pro predmet IZP
*
* Popis: Program vypocitava cetnost znaku, ktere se vyskytuji ve
* vstupnim textu, a nasledne vypise prehled danych znaku s jejich cetnosti
* Program take pracuje s pripadnym parametrem, kterym uzivatel udava
* kolik radku chce vypsat.
*/
/* Knihovna pro vstup a vystup */
#include <stdio.h>
/* Standartni funkce jazyka C */
#include <stdlib.h>
/* Kvuli porovnavaci operaci strcmp */
#include <string.h>
/* Kvuli operaci isprint, isdigit */
#include <ctype.h>
const int UNS_CHAR = 256;
/* Vytvoreni funkcnich prototypu */
void napoveda(void);
int prevodParametru(char *parametr);
void nulovaniPole(unsigned char pole[UNS_CHAR]);
void pripraveniAscii(unsigned char ascii[UNS_CHAR]);
void spocitaZnaky(unsigned char pole[UNS_CHAR]);
void vypisePole(unsigned char pole[UNS_CHAR]);
void seradiPole(unsigned char pole[UNS_CHAR], unsigned char pole_ascii[UNS_CHAR]);
void vypiseSerazenePole(unsigned char pole[], unsigned char ascii[], int parametr);
int main(int argc, char *argv[])
{
int parametr;
unsigned char pole[UNS_CHAR];
/*
* Porovna pripadny parametr a pote budto prevede a nasledne vypise znaky podle cetnosti,
* Vypise napovedu a nebo chybove hlaseni. Jsou-li zadany dva parametry, vypise se chybove hlaeni.
* V pripade ze neni zadany parametr, pokracuje sectenim znaku a vypsani podle cisla znaku v ACII
*/
if (argc == 2) /* Overuje, zda je zadán jeden parametr */
{
/* Je-li parametrem je -h nebo --help, vypise napovedu */
if ((argc == 2 && strcmp(argv[1], "-h") == 0) || (argc == 2 && strcmp(argv[1], "--help") == 0))
{
napoveda();
return 0;
}
else
{
parametr = prevodParametru(argv[1]);
/* Pokud je parametr v intervalu 1 az UNS_CHAR, spocitaji se znaky, a vypise znaky serazene podle cetnosti */
if ((parametr >= 1) && (parametr <= UNS_CHAR))
{
/* Definovani pole, ve kterém budou uloženy pozice prohozených znaků, viz radek 243 */
unsigned char ascii[UNS_CHAR];
nulovaniPole(pole);
pripraveniAscii(ascii);
spocitaZnaky(pole);
seradiPole(pole, ascii);
printf("\n");
vypiseSerazenePole(pole, ascii, parametr);
}
else
{
/* Pokud je zadan parametr mimo interval, vypise se chybove hlaseni */
fprintf(stderr, "Byla zadaná hodnota, se kterou nelze pracovat\n");
return 1;
}
}
}
else if (argc > 2)
{
/* Pokud je parametru vice nez 1, vypise se chybove hlaseni */
fprintf(stderr, "Byl zadán chybný počet parametrů\n");
return 1;
}
else
{
/* Paklize neni zadany zadny parametr, program secte znaky a vypise je podle cisla znaku v ASCII */
nulovaniPole(pole);
spocitaZnaky(pole);
printf("\n");
vypisePole(pole);
}
}
void napoveda(void)
/* Funkce, ktera slouzi k vypsani napovedy */
{
printf("Program: proj1.c\n"
"Autor: Roman Blanco, [email protected]\n"
"Popis: Program pro vypis cetnosti znaku\n"
"Použití: proj1 [PREPINAC] [CISLO]\n\n"
"Popis parametrù:\n"
"[CISLO] - parametr, ktery udava kolik radku se ma vypsat\n"
" - je mozne zadat hodnty 1 az %d\n\n"
"Prepinace napovedy:\n"
" -h, --help Vypíše tuto obrazovku s nápovědou.\n", UNS_CHAR);
}
int prevodParametru(char *parametr)
/* Prevede znakovy retezec na dane cislo */
{
int i = 0;
for (int a = 0; parametr[a] != '\0'; a++)
/* Cyklus, ktery se bude opakovat, dokud v poli nedojde na ukoncovaci nulu */
{
/*
* K i se priradi hodnota i vynasobena deseti,
* zvetsena o rozdil ciselne hodnoty znaku na pozici 'a' v poli 'parametr'
* a ciselne hodnoty znaku 0 (-> 48)
*/
if (isdigit(parametr[a])) /* Kontrola, zda je parametr cislice */
{
i = i * 10 + parametr[a] - '0';
}
else
{
return -1;
}
}
return i;
}
void nulovaniPole(unsigned char pole[UNS_CHAR])
/* vynuluje pole, aby bylo zajisteno, ze se budou znaky pricitat od 0 */
{
int i;
for (i = 0; i < UNS_CHAR; i++)
{
pole[i] = 0;
}
}
void pripraveniAscii(unsigned char ascii[UNS_CHAR])
/* nastavi hodnoty v poli, aby mohlo být použito po serazeni na identifikaci znaku */
{
int i;
for (i = 0; i < UNS_CHAR; i++)
{
ascii[i] = i;
}
}
void spocitaZnaky(unsigned char pole[])
/* spocita znaky (umisteni v poli = desitkova hodnota v ascii tabulce) */
{
int c;
while ((c = getchar()) != EOF)
/* Cyklus, ktery pricita znaky, dokud nedojde na EOF (konec vstupu) */
{
if (pole[c] <= UNS_CHAR - 2)
{
/*
* Hodnoty se budou přičítat, dokud nebude počet znaků větší než UNS_CHAR - 2,
* pote priradi znaku pocet UNS_CHAR - 1 (pri vypisu misto cisla UNS_CHAR - 1 bude zobrazeno "NNN")
*/
pole[c]++;
}
else
{
pole[c] = UNS_CHAR - 1;
}
}
}
void vypisePole(unsigned char pole[])
{
/*
* v pripade, ze byl program spusten bez parametru,
* se vypise pole podle desitkove hodnoty v ascii
*/
for (int i = 0; i < UNS_CHAR; i++)
{
/* Zjisteni, zda je znak tisknutelny */
if (isprint(i))
{
/*
* Pokud je soucet znaku jinehodnoty nez UNS_CHAR - 1,
* vypise se cislo, jinak bude vypsano "NNN" (r. 203)
*/
if (pole[i] != UNS_CHAR - 1)
{
/* Pokud bude soucet znaku rovny 0, nebude znak vypsany */
if (pole[i] != 0)
{
printf("%d '%c' %u\n", i, i, pole[i]);
}
}
else
{
printf("%d '%c' NNN\n", i, i);
}
}
else
{
if (pole[i] != UNS_CHAR - 1)
{
if (pole[i] != 0)
{
printf("%d: %u\n", i, pole[i]);
}
}
else
{
printf("%d: NNN\n", i);
}
}
}
}
void seradiPole(unsigned char pole[], unsigned char ascii[])
{
/* Serazeni pole podle cetnosti */
int i, j;
for (i = UNS_CHAR - 1; i > 0; i--)
{
for (j = 0; j < i; j++)
{
/*
* Pokud bude hodnota v naslednem poli vetsi nez v aktualnim,
* hodnoty v poli se preradi
*/
if (pole[j] < pole[j + 1])
{
int docasna;
/* Serazeni pole s pomoci docasne promenne */
docasna = pole[j];
pole[j] = pole[j + 1];
pole[j + 1] = docasna;
/*
* Protoze prehozenim hodnot v poli dojde k problemu,
* ze pozice v poli nebude udavat cislo znaku v ASCII,
* je vytvorene pole cislovane od 0 do UNS_CHAR - 1,
* kde se budou cisla prehazovat zaroven pri prehozeni souctu znaku
*/
docasna = ascii[j];
ascii[j] = ascii[j + 1];
ascii[j + 1] = docasna;
}
}
}
}
void vypiseSerazenePole(unsigned char pole[], unsigned char ascii[], int parametr)
{
/* Funkce vypise pole serazene podle cetnosti znaku. V pripade, ze byl program spusten s parametrem */
/*
* Cyklus, ktery se bude opakovat, dokud nebude hodnota i mensi nez cislo zadane v parametru
* Vypis je obdobny, jako u funkce ktera vypisuje neserazene pole, rozdil je v tom, ze pri vypisu
* nesarazeneho pole je znak rozpoznan pozici v poli. Zde je znad rozpoznan podle hodnoty v poli,
* ktera je na stejne pozici jako prehozeny soucet znaku
*/
for (int i = 0; i < parametr; i++)
{
if (isprint(ascii[i]))
{
if (pole[i] != UNS_CHAR - 1)
{
if (pole[i] != 0)
{
printf("%d '%c' %u\n", ascii[i], ascii[i], pole[i]);
}
}
else
{
printf("%d '%c' NNN\n", ascii[i], ascii[i]);
}
}
else
{
if (pole[i] != UNS_CHAR - 1)
{
if (pole[i] != 0)
{
printf("%d: %u\n", ascii[i], pole[i]);
}
}
else
{
printf("%d: NNN\n", ascii[i]);
}
}
}
}