-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtest.c
214 lines (214 loc) · 6.68 KB
/
test.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
/*=============================================================================*/
/* Программа тестирования функций, реализующих операции с десятичными дробями. */
/* Автор: Орещенков Игорь Сергеевич, 2019 г. */
/* Язык программирования: Си. */
/* Компилятор: Digital Mars C++ Compiler. */
/*=============================================================================*/
#include <stdio.h>
#include "iadf.h"
int TestSample (int line, const char* s);
int IadfEqually (struct IADF* df1, struct IADF* df2);
const char* SkipOver (const char* s, const char* t);
int main ()
{
int res, r1, r2;
int line;
char fn[] = "test.txt"; /* имя файла с тестовыми примерами */
char s[256]; /* буфер для чтения строк из файла */
const char* p; /* указатель на позицию в буфере */
FILE* fp; /* указатель на сведения о файле */
/* Подготовка к чтению тестовых примеров из файла. */
fp = fopen (fn, "r");
if (fp != NULL) {
/* Сообщение об условиях тестирования. */
printf ("IADFCAPACITY = %d\n", IADFCAPACITY);
printf ("----------------------------------------------------------\n");
/* Построчная обработка содержимого файла. */
line = 0;
r1 = r2 = 0;
while (fgets (s, sizeof s / sizeof (char), fp)) {
line++;
/* Пропуск строк с комментариями. */
p = SkipOver (s, " \t");
if (*p == '#')
continue;
/* Прогон тестового примера. */
if (TestSample (line, s))
r1++;
else
r2++;
}
fclose (fp);
/* Сообщение о результате проверки. */
printf ("----------------------------------------------------------\n");
printf ("Samples TOTAL: %d\n", r1 + r2);
printf ("Samples PASSED: %d\n", r1);
printf ("Samples ERROR: %d\n", r2);
printf ("Summary: %s", r2 > 0? "ERROR": "PASSED");
res = 0;
}
else {
/* Ошибка открытия файла для чтения. */
printf ("ERROR: Cannot open the file \"%s\" for reading.\n");
res = 1;
}
return res;
}
/*===========================================================*/
/* Прогон тестового примера. */
/* Вызов: line - порядковый номер строки в файле, */
/* s - указатель на строку, содержащую пример. */
/* Возврат: 1 - тестовый пример прошёл проверку, */
/* 0 - ошибка при выполнении тестового примера. */
/*===========================================================*/
#define DEBUG 0
int TestSample (int line, const char* s)
{
char buf[64];
struct IADF df1, df2, df3;
int res;
char op; /* знак операции */
int ec, rc; /* код завершения */
const char* p; /* указатель на текущую позицию в строке */
int ef; /* признак ошибки */
int i, n;
ef = 0;
/* Пропуск пробелов. */
p = SkipOver (s, " \t");
/* Считывание первого операнда. */
n = iadfInit (&df1, p);
p += n;
ef = !n;
if (!ef) {
/* Пропуск пробелов. */
p = SkipOver (p, " \t");
/* Считывание символа операции. */
if (*p != '\0')
op = *p;
ef = op != '+' && op != '-' && op != '*' && op != '/';
}
if (!ef) {
/* Пропуск пробелов. */
p = SkipOver (p + 1, " \t");
/* Считывание второго операнда. */
n = iadfInit (&df2, p);
p += n;
ef = !n;
}
if (!ef) {
/* Пропуск пробелов. */
p = SkipOver (p, " \t");
/* Считывание символа '='. */
ef = *p != '=';
}
if (!ef) {
/* Пропуск пробелов. */
p = SkipOver (p + 1, " \t");
/* Считывание результата. */
n = iadfInit (&df3, p);
p += n;
ef = !n;
}
if (!ef) {
/* Пропуск пробелов. */
p = SkipOver (p, " \t");
/* Считывание кода завершения. */
ef = *p < '0' || *p > '9';
if (!ef)
ec = *p - '0';
}
/* Обработка строки с примером. */
if (ef) {
/* Произошла ошибка синтаксического разбора строки. */
printf ("Line #%d - sample string parsing ERROR:\n", line);
puts (s);
n = p - s;
for (i = 0; i < n; i++)
putchar (' ');
puts ("^-- parsing error occures");
res = 0;
}
else {
/* Проверка записанного в строке примера. */
#if DEBUG == 1
printf ("Line #%d string parsed:\n", line);
puts (s);
iadfToStr (&df1, buf, sizeof buf / sizeof (char));
printf ("DEBUG first operand: [%s]\n", buf);
printf ("DEBUG operation: [%c]\n", op);
iadfToStr (&df2, buf, sizeof buf / sizeof (char));
printf ("DEBUG second operand: [%s]\n", buf);
iadfToStr (&df3, buf, sizeof buf / sizeof (char));
printf ("DEBUG result value: [%s]\n", buf);
printf ("DEBUG result code: %d\n", ec);
#endif
/* Выполнение операции, приведенной в примере. */
switch (op) {
case '+': /* Сложение. */
rc = iadfAdd (&df1, &df2);
break;
case '-': /* Вычитание. */
rc = iadfSub (&df1, &df2);
break;
case '*': /* Умножение. */
rc = iadfMul (&df1, &df2);
break;
case '/': /* Деление. */
rc = iadfDiv (&df1, &df2);
}
/* Сверка полученного результата. */
if (!IadfEqually (&df1, &df3) || ec != rc) {
printf ("Line #%d sample checking error:\n", line);
printf ("> %s\n", s);
iadfToStr (&df3, buf, sizeof buf / sizeof (char));
printf ("> Expected result: [%d] - [%s]\n", ec, buf);
iadfToStr (&df1, buf, sizeof buf / sizeof (char));
printf ("> Calculated result: [%d] - [%s]\n", rc, buf);
res = 0;
}
else
res = 1;
}
return res;
}
/*============================================*/
/* Проверка равенства двух десятичных дробей. */
/* Вызов: df1 - указатель на первую дробь, */
/* df2 - указатель на вторую дробь. */
/* Возврат: 1 - дроби равны, */
/* 0 - дроби не равны. */
/*============================================*/
int IadfEqually (struct IADF* df1, struct IADF* df2)
{
int res;
int i;
res = 1;
res = res && df1->n == df2->n;
res = res && df1->m == df2->m;
res = res && df1->s == df2->s;
if (res)
for (i = 0; i < df1->n; i++)
res = res && df1->v[i] == df2->v[i];
return res;
}
/*===========================================================*/
/* Пропуск символов в строке. */
/* Вызов: s - указатель на начальную позицию в строке, */
/* t - указатель на строку с пропускаемыми символами. */
/* Возврат: указатель на позицию в строке, следующую за */
/* пропущенными символами. */
/*===========================================================*/
const char* SkipOver (const char* s, const char* t)
{
const char* p;
do {
/* Проверка совпадения текущего символа строки с одним из пропускаемых символов. */
p = t;
while (*p && *s != *p)
p++;
/* Пропуск символа в случае совпадения. */
if (*p)
s++;
} while (*p);
return s;
}