Qraizer

Advanced Member | Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору Ты заблуждаешься в своём представлении того, как функции xxxscanf() обрабатывают форматную строку. Ты считаешь, что она вначале целиком разбирается по элементам, а потом уже на основе разбора выполняется чтение данных. На самом деле она обрабатывается последовательно, и все встреченные форматные спецификаторы обрабатываются сразу же, без заглядывания вперёд. Т.е. когда разбор дойдёт до %d, сразу же будет выполнена попытка ввести целое десятичное, которое и вводится как 1, т.к. ввод из потока остановится на первом разделителе, неважно, пробел ли это будет или \n. И только потом начнётся анализ дальнейшего содержимого форматной строки. При вводе, каждый спецификатор формата может начинать разбор содержимого потока с последовательности разделителей, каковыми являются пробелы, табуляции и "новые строки". При этом все эти последовательные разделители пропускаются. (Исключение составляет только %c, который никогда не учитывает разделители и считает из обычными символами.) Если в форматной строке встречаются не только спецификаторы формата, считается, что в соответствующих позициях потока должны располагаться именно эти символы. При этом они благополучно вычитываются и отбрасываются. Т.о. scanf("%d%d", &n1, &n2) после ввода n1 будет ожидать в потоке хотя бы один разделитель (иначе два числа просто сольются), а следом значение n2, а scanf("%dи далее%d", &n1, &n2) после ввода n1 будет ожидать последовательности "и далее" и только потом n2; при этом разделители уже не обязательны, т.к. ввод n1 будет остановлен на символе "и" (ибо этот символ явно не относится к цифрам), а после "далее" сразу же ожидается новое число. Если же в потоке между значениями n1 и n2 будет что-то другое, отличное от "и далее", то ввод прекратится на несовпавшем символе, и будет зафиксирована ошибка. Например, если в потоке будет "1и далие2", то после выборки из потока символа "л" вычитается "и", а не "е", как указано в форматной строке, и это будет расценено как ошибка данных в потоке. В результате поток не дойдёт до "2", и n2 не будет введено. Отсюда следует, что указывать сами разделители в форматной строке не имеет особого смысла (если только они не должны быть введены спецификатором %c). Фактически они могут рассматриваться как поясняющие. Смотри например, что произойдёт с scanf("%d\n%d", &n1, &n2). Когда после %d обнаружится \n, то именно он и будет ожидаться после ввода n1. Если он в потоке и правда есть, то он благополучно вычитается и отбросится; если же вместо него там будет, например, какой-нибудь пробел, то произойдёт ошибка, и он не вычитается. Однако далее следует ещё один %d, поэтому дальше начнётся ввод ещё одного целого, и начнётся он с разделителя, того самого, который не вычитался, и который теперь благополучно пропустится как лидирующий. Так что действительно - никакой разницы.
---------- Одни с годами умнеют, другие становятся старше. |
| Всего записей: 613 | Зарегистр. 08-08-2006 | Отправлено: 23:58 23-07-2007 | Исправлено: Qraizer, 00:11 24-07-2007 |
|