Сочетание fgets()
с sscanf()
обычно хорошо. Тем не менее, вы, вероятно, должны использовать:
if (fgets(line, sizeof(line), fp) != 0)
{
...
}
Проверяет наличие ошибок ввода-вывода и EOF. Это также предполагает, что определение массива является видимым (в противном случае sizeof
дает вам размер указателя, а не массива). Если массив не находится в области видимости, вам, вероятно, следует передать размер массива функции, содержащей этот код. Все это говорит о том, что грехи хуже, чем использование MAX
вместо sizeof(line)
.
Вы не проверяли строку дня рождения нулевой длины; тем не менее, вы, вероятно, в конечном итоге проведете довольно много проверок введенной строки (даты непостоянны и трудно поддаются обработке).
Учитывая, что MAX равен 60, но sizeof(records->bday) == 11
, вам необходимо защитить себя от переполнения буфера в sscanf()
. Один из способов сделать это:
if (sscanf(line, "%10s", records->bday) != 1)
...handle error...
Обратите внимание, что 10
- это sizeof(records->bday) - 1
, но вы не можете указать длину в качестве аргумента sscanf()
; оно должно появляться в строке формата буквально. Здесь вы, вероятно, можете жить с нечетным размером, но если бы вы имели дело с более общим кодом, вы, вероятно, подумали бы о:
sprintf(format, "%%%zus", sizeof(records->bday) - 1);
Первый %%
отображается на %
; %zu
форматирует размер (z
- это C99 для size_t
); s
- для преобразования строки при использовании формата.
Или вы можете использовать strcpy()
или memcpy()
или memmove()
, чтобы скопировать правый подраздел входной строки в структуру - но учтите, что %10s
пропускает начальные пробелы, которые strcpy()
и др. Не будут. Конечно, перед копированием вы должны знать, какова длина строки, и убедиться, что строка завершена нулем.