Приветствую всех!
Сделал так:
#define GIANT_SIZE 1024*32
#define HUGE_SIZE 1024*16
#define LARGE_SIZE 1024*8
#define BIG_SIZE 1024
#define MIDDLE_SIZE 512
#define MEDIUM_SIZE 256
#define SMALL_SIZE 128
#define LITTLE_SIZE 64
#define TINY_SIZE 32
Стильно получилось?
Часто требуется, например, считать строку из файла, и чтобы не плодить магических констант, вместо 512 писать MIDDLE_SIZE
...
while (!feof(fp))
{
char buff[MIDDLE_SIZE];
fgets(buff, MIDDLE_SIZE, fp);
buff[MIDDLE_SIZE-1]='\0';
char* line = str_dup(buff);
str_trim(line);
...
Например, загрузка матрицы из файла формата (нарочно зашумленный пробелами и tab-ами):
DIM1= 3
DIM2 = 7
{
0.935 0.674 -1.687 0.468 2.436 -1.743 0.275
0.111 0.346 0.368 0.907 -7.346 -0.235 -0.139
0.436 -0.134 -1.047 0.879 -1.051 -0.367 -0.196
}
выглядит вот так
void matrix_load( MATRIX* A, const char* fileName)
{
FILE* fp;
bool b_is_dim1_read=false;
bool b_is_dim2_read=false;
unsigned int dim1, dim2;
bool begin=false;
bool end = false;
int row_count = 0;
if ((fp = fopen(fileName,"r")) == NULL)
{
fprintf(stderr,"File '%s' open failed\n", fileName);
enter_pause();
exit(EXIT_FAILURE);
}
else
{
while (!feof(fp))
{
char buff[MIDDLE_SIZE];
fgets(buff, MIDDLE_SIZE, fp);
buff[MIDDLE_SIZE-1]='\0';
char* line = str_dup(buff); //
str_trim(line); // обрезаем '\t','\v', '\f', '\n', '\r', ' '
if (0==strlen(line)) // если после обрезки строка пустая, то пропускаем обработку
{
free(line);
continue;
}
if (line[0] == 'D' && line[1] == 'I' && line[2]== 'M') // если встретилось "DIM"
{
Tokens* dim = tokens_new(2);
string_split(dim, line, "="); // разбиваем строку по '='
if (line[3]== '1' || line[3]== '2') // DIM1 или DIM2
{
errno = 0;
char *endptr;
unsigned int d = strtoul(dim->array[1]->data, &endptr, 10);
if (*endptr != '\0' || errno !=0 || d==0 || d>30) // не более 30x30
{
fprintf(stderr,"Error: dimension wrong '%s'\n", dim->array[1]->data);
tokens_free(dim);
free(line);
enter_pause();
exit(EXIT_FAILURE);
}
switch (line[3])
{
case '1':
dim1 = d;
b_is_dim1_read = true;
break;
case '2':
dim2 = d;
b_is_dim2_read = true;
break;
}
}
// если все размерности считаны, то выделяем память для матрицы
if (b_is_dim1_read && b_is_dim2_read)
{
matrix_create(A, dim1, dim2);
}
tokens_clear(dim);
tokens_free(dim);
}
if (line[0] =='{') { begin=true; free(line); continue; } // признак начала значений матрицы
if (line[0] =='}') { end=true; free(line); continue; }
if (begin && !end)
{
//printf("%s\n", line);
Tokens* row = tokens_new(dim2); // по кол-ву элементов в строке
string_split(row, line, " ");
// если столбцов недостаточно или строк больше заявленных
if (dim2 != row->size || row_count >= dim1)
{
fprintf(stderr,"Error: Invalid file format '%s'\n", fileName);
enter_pause();
exit(EXIT_FAILURE);
}
// заполнение строки матрицы
for (int j=0; j<dim2; ++j)
{
errno = 0;
char *endptr;
double value = strtod(row->array[j]->data, &endptr);
if (*endptr != '\0' || errno != 0 || 10 < strlen(row->array[j]->data) ) //не более 10-значное число
{
fprintf(stderr,"Error: wrong value '%s'\n", row->array[j]->data);
tokens_free(row);
free(line);
matrix_free(A);
enter_pause();
exit(EXIT_FAILURE);
}
matrix_set_elem(A, row_count, j, value);
}
row_count++;
tokens_clear(row);
tokens_free(row);
}
free(line);
}
fclose(fp);
if (row_count != dim1) // недочитали заявленные dim1 строк
{
fprintf(stderr,"Error: Invalid file format '%s'\n", fileName);
enter_pause();
exit(EXIT_FAILURE);
}
}
}
Функция str_dup:
char *str_dup(char const *in)
{
if ( !in ) return NULL;
size_t len = strlen(in);
char *out = malloc(len+1);
strncpy(out, in, len+1);
return out;
}
Буду рад услышать отзывы о стиле.