![]() |
|
Модераторы: bsa |
![]()
|
|
| neocpp |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 10 Регистрация: 21.1.2013 Репутация: нет Всего: нет |
Добрый день. Имеется текстовый файл, в котором просто записано несколько чисел, например: 1 2 3 4
Читаю их таким образом:
Получаю: 1 2 3 4. Но, стоит заменить тип переменной на: char c; Вывод получается таким, с лишней цифрой: 1 2 3 4 4 Вопрос. Почему в первом случае eofbit установился раньше, сразу после чтения последней цифры? И что происходит во втором случае? |
|||
|
||||
| korian |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 651 Регистрация: 8.3.2008 Где: Украина, Харьков Репутация: 2 Всего: 17 |
а с char'ом разве пробелов не в три раза больше?
нету компилятора под рукой, проверить... |
|||
|
||||
| NoviceF |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 313 Регистрация: 13.3.2012 Где: Ростов-на-Дону Репутация: 2 Всего: 2 |
korian, вот у кого нет компилятора
http://liveworkspace.org/code/1bmmjj$2 эффект, описанный автором, присутствует.. |
|||
|
||||
| korian |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 651 Регистрация: 8.3.2008 Где: Украина, Харьков Репутация: 2 Всего: 17 |
NoviceF,
спасибо Для описание возьмем буфер "12 3 4" В случае с int мы читаем "числа", так сказать, и происходит примерно следующее: 1) прочитали символ '1', запомнили 2) прочитали символ '2', умножили предыдущее значение (цифру 1) на 10, прибавили 2 3) прочитали пробел (закончили читать число) 4) вывели int - 12 и пробел 5) прочитали символ '3', запомнили 6) прочитали пробел (закончили читать число) 7) вывели int - 3 и пробел 8) прочитали символ '4', запомнили 9) попытались прочитать еще символ - eof = 1, (закончили читать число) // <<<<<< это главное как бы 10) вывели int - 4 и пробел 11) вышли из цикла В случае с char мы читаем "символы", так сказать, и происходит примерно следующее (пробелы пропускаются скорее всего из-за включенного skip_ws или как оно там): 1) прочитали символ '1' 2) вывели символ - '1' и пробел 3) прочитали символ '2' 4) вывели символ - '2' и пробел 5) прочитали символ <пробел> (skip_ws), тупо читаем след символ 6) прочитали символ '3' 7) вывели символ - '3' и пробел 8) прочитали символ <пробел> (skip_ws) 9) прочитали символ '4' 10) вывели символ - '4' и пробел 11) попытались прочитать еще один символ - eof 12) вывели то, что прочитали в прошлый раз 13) вышли из цикла Кстати, если взять строку "1 2 3 4 " (тут главное пробел в конце), то вывод будет одинаковый Это сообщение отредактировал(а) korian - 9.2.2013, 22:15 |
|||
|
||||
| volatile |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2107 Регистрация: 7.1.2011 Репутация: 16 Всего: 85 |
Уважаемые программеры, все гораздо проще.
Запомните одну вещь, поток нужно проверять на конец файла не до ввода, а после. А еще лучше проверять не на конец файла, а на любую ошибку. что в коде выразицца след. образом:
Код стал немного короче, и много надежней. |
|||
|
||||
| neocpp |
|
||||||||
|
Новичок Профиль Группа: Участник Сообщений: 10 Регистрация: 21.1.2013 Репутация: нет Всего: нет |
В этом-то и проблема. Я хотел действовать по схеме - сначала считываю значение, и, если установился eofbit, то выхожу из цикла. Так примерно:
Но так получается, что последнее число не выводится. То есть eofbit установился не после неудачного чтения, а сразу после последнего успешного чтения. Поэтому число 4 записалось в c, а потом сразу произошел выход, без вывода c на экран. Вот еще небольшой код:
Из него видно, что сначала установился eofbit - после последнего успешного чтения, а уже на следующем шаге failbit, после неудачного чтения. eofbit: 0 failbit: 0 1 eofbit: 0 failbit: 0 2 eofbit: 0 failbit: 0 3 eofbit: 1 failbit: 0 4 eofbit: 1 failbit: 1 4 А вот в случае char-переменной, eofbit и failbit установились одновременно, уже после неудачного чтения: eofbit: 0 failbit: 0 1 eofbit: 0 failbit: 0 2 eofbit: 0 failbit: 0 3 eofbit: 0 failbit: 0 4 eofbit: 1 failbit: 1 4 Я не понимаю, почему так. В какой конкретно момент устанавливается eofbit и как это зависит от типа переменной? volatile, полностью согласен, ваш код надежнее, и обычно я так и делаю. Но вот в чем проблема, if(f) - это проверка на failbit и badbit. Меня в контексте данного вопроса интересует именно eofbit. _____________________________________________________________________________________________________________ Добавлено @ 09:12
Хм... получается для типа int операция << читает символы, которые являются цифрами и следующий после них разделитель тоже считывает? То есть пробел или признак конца файла считается вместе с последним числом, и устанавливается eofbit. А уже на следующей итерации (если она есть) - попытка читать после конца приводит к fail. А для char просто читает 1 символ, и "не смотрит" на следующие? То есть, последний символ считали, потом пробуем считать конец файла - получаем сразу eof и fail? Пока я еще больше запутался, но кажется вы правильно все написали. Это сообщение отредактировал(а) neocpp - 10.2.2013, 09:12 |
||||||||
|
|||||||||
| NoviceF |
|
||||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 313 Регистрация: 13.3.2012 Где: Ростов-на-Дону Репутация: 2 Всего: 2 |
Прочитай что написал korian, там этот момент объясняется. В итоге смысл в том, что для char всегда читается 1 символ из потока, а int читает до тех пор, пока не убедится, что число закончилось, то есть для интов, чтение из потока происходит минимум 2 раза за 1 проход цикла, и именно поэтому при чтении int из потока, конец файла обнаруживается быстрее, чем при чтении char. Добавлено через 7 минут и 37 секунд Ну в данном контексте конец файла не считается ошибкой и проверку
проходит. Хотя такой способ проверки, конечно, удобнее. |
||||
|
|||||
| volatile |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2107 Регистрация: 7.1.2011 Репутация: 16 Всего: 85 |
neocpp, вас как я понял интересует внутренняя кухня? Здесь все уже сказали верно. При чтении инта программа не знает когда он закончицца. инт может быть таким "1", и таким "10", и таким "100" и т.д. программа будет читать поток до тех пор, пока не встретицца первый не цифровой символ. Если сразу за цифрами последует конец файла, то eofbit и установицца. Если же после цифр будет идти хотябы один пробел, или перевод строки, то eofbit не установицца. Из этого вытекает, кстати, что проверять на конец файла, вообще не очень корректно. Нужно проверять именно на ошибку, и проверять ее именно после чтения, как я и привел пример. Такой способ не будет зависеть от оконечных пробелов/переводов строк, в файле. |
|||
|
||||
| neocpp |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 10 Регистрация: 21.1.2013 Репутация: нет Всего: нет |
Всем спасибо за подробные ответы, теперь все более менее встало на свои места. К сожалению, не получается добавить плюсов к репутации((
|
|||
|
||||
![]()
|
| Правила форума "C/C++: Для новичков" | |
|
|
Запрещается! 1. Публиковать ссылки на вскрытые компоненты 2. Обсуждать взлом компонентов и делиться вскрытыми компонентами
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa. |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | C/C++: Для новичков | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |