Исходный формат
Спецификация преобразования %s
пропускает любые пробелы (пробелы, табуляции, новые строки и т. Д.) Во входных данных, а затем считывает непустые пробелы до следующего символа пробела.\t
, появляющийся в строке формата, заставляет fscanf()
пропускать ноль или более символов пробела (не только табуляции).
У вас есть:
fscanf(fPtr,"%s\t%d\t%s\t%s\the n", pObj->name, pObj->age, pObj->country, pObj-profile);
Вам необходимо передатьуказатель на возраст, и вам нужна стрелка ->
между pObj
и profile
(пожалуйста, напишите код, который может скомпилироваться; это не внушает уверенности, когда есть такие ошибки):
fscanf(fPtr,"%s\t%d\t%s\t%s\the n", pObj->name, &pObj->age, pObj->country, pObj->profile);
Учитывая первую строку ввода:
Newton 30 United Kingdom Scientist
fscanf()
будет читать Newton
в pObj->name
, 30
в pObj->age,
United into
pObj-> страна and
Королевство into
pObj-> profile .
fscanf () `и семья в целом очень небрежно относятся к пробелам.В большинстве преобразований пропускаются первые пробелы.
После того, как назначены 4 значения, в конце формата появляется \the n"
.Вкладка пропускает пробел между Kingdom
и Scientist
, но данные не совпадают с he n
, поэтому сканирование останавливается - не то, чтобы вы были мудрее для этого.
Следующийоперация будет определена там, где этот остановился, поэтому следующему pObj->name
будет присвоено Scientist
, а затем преобразование pObj->age
завершится неудачей, поскольку Maxwell
не представляет целое число.Здесь прекратятся преобразования fscanf()
.
И поэтому проблемы продолжаются.Ваш заявленный результат не может быть достигнут с помощью кода, который вы указали в вопросе.
Если вы непреклонны в том, что должны использовать fscanf()
, вам нужно будет использовать наборы сканирования, такие как %24[^\t]
длячитать страну.Но вам лучше использовать fgets()
или функцию POSIX getline()
для чтения целых строк ввода, а затем, возможно, использовать sscanf()
, но большескорее всего, используйте strcspn()
или strpbrk()
из стандартного C (или, возможно, strtok()
или - гораздо лучше - POSIX strtok_r()
или Windows strtok_s()
, или нестандартный strsep()
), чтобы разбить строку на поля на вкладках.Обратите внимание, что strtok_r()
и др. Не волнует, сколько повторений разделителя (вкладок в вашем случае) между полями;вы не можете иметь пустые поля с ними.Вы можете идентифицировать пустые поля с помощью strcspn()
, strpbrk()
и strsep()
.
Очищенный формат
Строка формата была изменена на:
fscanf(fPtr,"%s\t%d\t%s\t%s\n", pObj->name, &pObj->age, pObj->country, pObj->profile);
Это не будет работать, но теперь может быть адаптировано так, чтобы оно работало.
if (fscanf(fPtr," %49[^\t]\t%d\t%24[^\t]\t%19[^\n]", pObj->name, &pObj->age, pObj->country, pObj->profile) != 4)
…handle a format error…
Остерегайтесь конечных пробелов в scanf()
строках формата .Начальный пробел пропускает любой символ новой строки, оставшийся от предыдущих строк, и пропускает любой начальный пробел в строке.%49[^\t]
ищет до 49 не вкладок;вкладка является необязательной и соответствует любой последовательности пробелов, но первый символ будет вкладкой, если имя не было слишком длинным.Затем он читает число, более необязательный пробел (это не обязательно должна быть табуляция, но это будет, если данные не отформатированы), затем до 24 не вкладок, снова пробел (из которых первый символ будетбыть вкладкой, если нет проблем с форматированием), и до 19 не вкладок.Следующим символом должен быть перевод строки, если только не возникла проблема с форматированием.