-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtail.c
161 lines (134 loc) · 3.92 KB
/
tail.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
/*
Daniel Pátek (xpatek08)
VUT FIT
IJC - Projekt 2
19.4.2020
překladač: gcc (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#define DEFAULT_COUNT 10
#define MAX_SIZE 1023
#define MIN(a,b) ((a < b) ? a : b)
FILE *openFile(const char* file);
int checkNumber(const char* numArg, const char* number, bool * doSkip);
void tail(int n, FILE *f);
void tailSkip(int n, FILE *f);
int main(int argc, char const *argv[]) {
FILE *f = stdin;
int lines = DEFAULT_COUNT;
bool doSkip = false;
if (argc == 2) {
//musi byt jako jediny argument zadan soubor
f = openFile(argv[1]);
}
else if (argc == 3) {
//bude zadan jen cislo radku (bez souboru)
lines = checkNumber(argv[1], argv[2], &doSkip);
}
else if (argc == 4) {
//bude zadano i cislo radku i soubor
lines = checkNumber(argv[1], argv[2], &doSkip);
f = openFile(argv[3]);
}
else if (argc != 1) {
fprintf(stderr, "Zadan spatny pocet argumentu programu. Ocekavaji se 2-4 argumenty.\n");
return EXIT_FAILURE;
}
(doSkip) ? tailSkip(lines, f) : tail(lines, f);
fclose(f);
return EXIT_SUCCESS;
}
FILE *openFile(const char* file) {
FILE *fr;
fr = fopen(file, "r");
if (fr == NULL) {
fprintf(stderr, "Soubor %s se nepodarilo otevrit.\n", file);
exit(EXIT_FAILURE);
}
return fr;
}
int checkNumber(const char* numArg, const char* number, bool *doSkip) {
//overit -n argument
if (strcmp(numArg, "-n") != 0) {
fprintf(stderr, "Ocekava se argument \"-n\" pro definovani poctu radku.\n");
exit(EXIT_FAILURE);
}
if (number[0] == '+') {
*doSkip = true;
}
//prevest cislo na integer
char *endptr = NULL;
int num = strtol(number, &endptr, 10);
if (endptr[0] != '\0') {
fprintf(stderr, "Cislo \"%s\" nemohlo byt spravne prevedeno na typ integer.\n", number);
exit(EXIT_FAILURE);
}
//nesmi byt zaporne
if (num < 0) {
fprintf(stderr, "Zadany pocet radku nemuze byt zaporny.\n");
exit(EXIT_FAILURE);
}
return num;
}
void tail(int n, FILE *f) {
//netiskne se nic pri n 0
if (n == 0) {
return;
}
//kruhove pole o velikosti radku, ktere se maji vypsat
char *arr[n];
for (int i = 0; i < n; i++) {
arr[i] = malloc(MAX_SIZE * sizeof(char));
}
//celkovy pocet radku bude v promenne size, pole naplnime hodnotami
int size = 0;
bool warningWasShown = false;
char *dummy = malloc(MAX_SIZE * sizeof(char));
while (fgets(arr[size % n], MAX_SIZE, f) != NULL) {
if (arr[size % n][strlen(arr[size % n])-1] != '\n') {
if (!warningWasShown) {
fprintf(stderr, "Doslo ke zkraceni konce radku.\n");
warningWasShown = true;
}
while (fgets(dummy, MAX_SIZE, f) != NULL) {
if (dummy[strlen(dummy)-1] == '\n') {
break;
}
}
arr[size % n][strlen(arr[size % n])-1] = '\n';
}
size++;
}
free(dummy);
//zjistime kde zacit s vypisovanim z pole a kolik znaku vypsat
int startArrIndex = size > n ? (size % n) : 0;
int count = MIN(n, size);
//vypiseme poslednich count radku z kruhoveho pole
for(int i = 0; i < count ; i++){
printf("%s", arr[(i + startArrIndex) % n]);
}
//uvolneni pameti
for (int i = 0; i < n; i++) {
free(arr[i]);
}
}
void tailSkip(int n, FILE *f) {
//netiskne se nic pri n 0
if (n == 0) {
return;
}
char *arr = malloc(MAX_SIZE * sizeof(char));
//skippnout prvnich n radku
for (int i = 0; i < n; i++) {
if (fgets(arr, MAX_SIZE, f) != NULL) {
}
}
while (fgets(arr, MAX_SIZE, f) != NULL) {
printf("%s", arr);
}
//uvolneni pameti
free(arr);
}