Я бы не стал использовать fscanf
здесь, потому что вы не можете смотреть в будущее и видеть, является ли следующая строка REGISTERS
или MEMORY
или что-то еще.Теоретически вы можете проверить возвращаемое значение fscanf
, но код очень быстро запутается.
Лучшее решение - использовать fgets
для извлечения всей строки.Если строка равна REGISTERS\n
, то вы знаете, что следующие строки являются строками регистра и т. Д. Сам анализ может быть выполнен с помощью sscanf
, что похоже на fscanf
, но вместо чтения из буфера FILE*
,он читает из строки.
Итак, я бы сделал:
enum mode_t {
REGISTERS = 0,
MEMORY,
...,
INVALID
};
int parse_file(FILE *file_ptr, int *registers, int some_other_params)
{
if(file_ptr == NULL || registers == NULL)
return 0;
char line[1024];
enum mode_t mode = INVALID;
while(fgets(line, sizeof line, file_ptr))
{
if(strcmp(line, "REGISTERS\n") == 0)
{
mode = REGISTERS;
continue;
} else if(strcmp(line, "MEMORY\n") == 0) {
mode = MEMORY;
continue;
} // keep adding if(strcmp.... as needed)
if(mode == INVALID)
{
fprintf(stderr, "Invalid file format\n");
return 0; // or a better error handling
}
int ret;
switch(mode)
{
case REGISTERS:
ret = parse_registers(line, registers);
break;
case MEMORY:
ret = parse_memory(line, some_other_args);
break;
...
}
// evaluate ret and do error handling if necessary
}
return 1;
}
Используя mode
для состояния анализа, вы можете определить, какой раздел вы анализируете.Затем вам нужно написать такие функции, как parse_registers
и parse_memory
, которые выполняют реальный анализ строк, например:
int parse_registers(const char *line, int *registers)
{
if(line == NULL || registers == NULL)
return 0;
int regNumber, regValue;
if(sscanf("R%d %d", ®Number, ®Value) != 2)
{
fprintf(stderr, "Invalid format for REGISTER section\n");
return 0;
}
if(regNumber < 0 || regNumber > 31)
{
fprintf(stderr, "Invalid register number %d\n", regNumber);
return 0;
}
registers[regNumber] = regValue;
return 1;
}
Теперь вы можете реализовать parse_memory
и другие parse_xxx
функции длядругие разделы файла.