| 
			| 
					
						| lightmaker 
								Участник    Offline | 
								|  | «  : 28-02-2008 12:52 »  |  | 
 
 Платформа: Unixgcc 2.95
 Имеется текстовый файл, содержащий строку "123"
 
 while(!feof(fp))
 ch=fgetc(fp);
 
 Напал тупняк и не могу понять, почему цикл выполняется 4 раза??? Работу я себе представляю так: Вначале указатель стоит на самый первое значение. Далее мы читаем его после чего указатель стоит на следующее значение, потом мы проверяем не указывает ли он на конец файла. Соответственно когда мы считаем символ '3', указатель по идее должен стоять на EOF, но почему-то происходит еще одна итерация? Может я чего-то не правельно понял?
 
 |  
						| 
								|  |  
								|  |  Записан | 
 |  |  | 
	| 
			| 
					
						| Алексей++ 
								глобальный и пушистыйГлобальный модератор    Offline 
								Сообщений: 13
								
								
								
								
								
							 | 
								|  | « Ответ #1 : 28-02-2008 13:01 »  |  | 
 
 1) возможно, после 3 ещё символ ? (тот же твой любимый \n   ) 2) а как себя ведёт с абсолютно пустым файлом? |  
						| 
								|  |  
								|  |  Записан | 
 
 |  |  | 
	| 
			| 
					
						| Антон (LogRus) | 
								|  | « Ответ #2 : 28-02-2008 13:03 »  |  | 
 
 ответ прост, потому, что fgetc возвращает следующий элемент, а не текущий
 можешь написать по другому
 int tmp;
 while((tmp = fgetc(fp)) != EOF)
 {
 ch = tmp;
 }
 |  
						| 
								|  |  
								|  |  Записан | 
 
 Странно всё это.... |  |  | 
	| 
			| 
					
						| lightmaker 
								Участник    Offline | 
								|  | « Ответ #3 : 28-02-2008 13:26 »  |  | 
 
 ответ прост, потому, что fgetc возвращает следующий элемент, а не текущий
 можешь написать по другому
 int tmp;
 while((tmp = fgetc(fp)) != EOF)
 {
 ch = tmp;
 }
 
 Хм.. получается, что из файла со строкой 123, символ '1' не будет считан? нЕ понятно |  
						| 
								|  |  
								|  |  Записан | 
 |  |  | 
	| 
			| 
					
						| RXL | 
								|  | « Ответ #4 : 28-02-2008 18:06 »  |  | 
 
 lightmaker, LogRus дал тебе совершенно верный пример. Выкладывай свой код.  |  
						| 
								|  |  
								|  |  Записан | 
 
 ... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С. |  |  | 
	| 
			| 
					
						| lightmaker 
								Участник    Offline | 
								|  | « Ответ #5 : 28-02-2008 20:59 »  |  | 
 
 RXL, да пример правельный, не спорю! Смутила фраза:  ответ прост, потому, что fgetc возвращает следующий элемент, а не текущий Согласно этому самый первый символ не будет считан... А код в первом сообщении! И я не могу понять почему он так работает, т.е. почему 4 итерации. Извеняюсь за тупняк.  |  
						| 
								|  |  
								|  |  Записан | 
 |  |  | 
	| 
			| 
					
						| RXL | 
								|  | « Ответ #6 : 28-02-2008 21:27 »  |  | 
 
 lightmaker, да, несколько путано. Давай лучше так: feof возвращает состояние последнего чтения из потока. Т.е., если при последнем чтении случился конец файла, то feof даст истину, а нет (или чтения еще вообще не производилось) - лож. |  
						| 
								|  |  
								|  |  Записан | 
 
 ... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С. |  |  | 
	| 
			| 
					
						| lightmaker 
								Участник    Offline | 
								|  | « Ответ #7 : 28-02-2008 22:08 »  |  | 
 
 RXL, спасибо за точное объяснение.  Честно говоря фигня какая-то. В большом справочнике по С товарисча Шилдта про ето не написано. А мануал в Линухе вообще говорит: "Функция feof проверяет указатель конца файла для потока stream, возвращая ненулевое значение, если он указывает на конец файла."  После этого я не врубаюсь почему fseek устанавливаю указатель на конец файла, а feof молчит засранец:) p.s. Получается, если открыть файл fopen и применить fgetc, получим первый символ. А так, как замечено выше, что fgetc читает не текущий символ, а следующий, получается, что после открытия файловый указатель стоит на "что-то"   до первого символа.   ) Ну я и занудисчееееее   |  
						| 
								|  |  
								| « Последнее редактирование: 28-02-2008 23:21 от lightmaker » |  Записан | 
 |  |  | 
	| 
			| 
					
						| RXL | 
								|  | « Ответ #8 : 29-02-2008 00:10 »  |  | 
 
 lightmaker, feof неудобная функция и, по сути, не нужна совсем. |  
						| 
								|  |  
								|  |  Записан | 
 
 ... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С. |  |  | 
	| 
			| 
					
						| Антон (LogRus) | 
								|  | « Ответ #9 : 29-02-2008 07:06 »  |  | 
 
 lightmaker, ну это просто вопрос восприятия    так написано в описании функции. Считай, что до первого чтения указатель в файле стоит перед первым символом или считай, что в конце файла есть символ конца файла CTRL+D   можно while, заменить на do while или for(fgetc;feof;fgetc){} второй вариант предпочтительней |  
						| 
								|  |  
								|  |  Записан | 
 
 Странно всё это.... |  |  | 
	| 
			| 
					
						| RXL | 
								|  | « Ответ #10 : 29-02-2008 08:29 »  |  | 
 
 LogRus, даже второй вариант бессмысленный - можно сравнение с EOF сделать.
 do c = fgetc(f); while(feof(f));
 Это вообще недопустимо: fgetc вернет EOF, что по сути - значение int, которое преобразуется в char и будет паразитный символ 0xff.
 
 Т.ч. проще просто while - так обычно и делают.
 |  
						| 
								|  |  
								| « Последнее редактирование: 29-02-2008 08:32 от RXL » |  Записан | 
 
 ... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С. |  |  | 
	| 
			| 
					
						| Антон (LogRus) | 
								|  | « Ответ #11 : 29-02-2008 11:41 »  |  | 
 
 RXL, не люблю я while его почти всегда заменяю на for
 лично меня конструкция for(int ch = fgetc(fp); ch != EOF; ch = fgetc(fp)) вполне устроит
 нет лишней итерации цикла, нет while
 |  
						| 
								|  |  
								|  |  Записан | 
 
 Странно всё это.... |  |  | 
	| 
			| 
					
						| geg Maneg 
								Гость
 | 
								|  | « Ответ #12 : 29-03-2008 11:52 »  |  | 
 
 RXLлично меня конструкция for(int ch = fgetc(fp); ch != EOF; ch = fgetc(fp)) вполне устроит
 нет лишней итерации цикла, нет while
 
 что значит нет лишней итерации?? значение в ch считается 4 раза пусть даже и за 3 итерации...а если эти значения надо обрабатывать постоянно? тогда первый считанный символ будет утерян, а в последнем получем ЕОФ  это не решает проблемы в общем есть ли еще какой-нибудь способ проверки ТЕКУЩУГО состояния указателя файла, кроме проверки вручную |  
						| 
								|  |  
								| « Последнее редактирование: 29-03-2008 11:55 от geg Maneg » |  Записан | 
 |  |  | 
	| 
			| 
					
						| RXL | 
								|  | « Ответ #13 : 29-03-2008 13:23 »  |  | 
 
 geg Maneg, еще раз: гарантированный результат даст только чтение из файла.
 Т.к. здесь использовались потоковые ф-ии, то удавшийся fgetc можно компенсировать ungetc, запихнув символ назад в буфер.
 |  
						| 
								|  |  
								|  |  Записан | 
 
 ... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С. |  |  | 
	| 
			| 
					
						| geg Maneg 
								Гость
 | 
								|  | « Ответ #14 : 29-03-2008 14:09 »  |  | 
 
 Т.к. здесь использовались потоковые ф-ии, то удавшийся fgetc можно компенсировать ungetc, запихнув символ назад в буфер.
 да в принципе обратно запихивать и не надо...считываем же с файла а что нету больше каких-нить функций проверки текущуего состояния указателя?? |  
						| 
								|  |  
								|  |  Записан | 
 |  |  | 
	| 
			| 
					
						| RXL | 
								|  | « Ответ #15 : 29-03-2008 14:24 »  |  | 
 
 geg Maneg, понимаешь, под "файлом" может оказатся что угодно: может быть файл, открытый несколькими программами (напр., другая программа дописывает в него), может оказатся символьное устройство (COM-порт, к примеру) и может быть буфер в памяти и мало ли еще чего. Нет универсального метода. Потому, только чтение из файла даст ответ - есть ли данные. Причем, для файла это будет означать конец файла, для COM-порта и буфера в памяти - пустой буфер приема. Скажем, ситуация, когда другая программа пишет в файл, а твоя считывает из него. Ты дочитал до конца и получил истину на eof(), но спустя некоторое время другая программа дописала в файл. Тебе eof() по прежнему выдает истину, а если бы ты выполнил чтение, то получил бы еще данные и, возможно, сброс eof(). Конец физического файла можно еще определить, сравнивая размер файла с текущей позицией. int fgetpos(FILE *restrict stream, fpos_t *restrict pos);long ftell(FILE *stream);
 
 int fstat(int fildes, struct stat *buf);
 /*
 dev_t     st_dev     Device ID of device containing file.
 ino_t     st_ino     File serial number.
 mode_t    st_mode    Mode of file (see below).
 nlink_t   st_nlink   Number of hard links to the file.
 uid_t     st_uid     User ID of file.
 gid_t     st_gid     Group ID of file.
 dev_t     st_rdev    Device ID (if file is character or block special).
 off_t     st_size    For regular files, the file size in bytes.
 For symbolic links, the length in bytes of the
 pathname contained in the symbolic link.
 For a shared memory object, the length in bytes.
 For a typed memory object, the length in bytes.
 For other file types, the use of this field is
 unspecified.
 time_t    st_atime   Time of last access.
 time_t    st_mtime   Time of last data modification.
 time_t    st_ctime   Time of last status change.
 blksize_t st_blksize A file system-specific preferred I/O block size for
 this object. In some file system types, this may
 vary from file to file.
 blkcnt_t  st_blocks  Number of blocks allocated for this object.
 */
 [/code
 |  
						| 
								|  |  
								|  |  Записан | 
 
 ... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С. |  |  | 
	| 
			| 
					
						| geg Maneg 
								Гость
 | 
								|  | « Ответ #16 : 29-03-2008 14:38 »  |  | 
 
 блин ты прав...запихивать обратно файл надо...токо я вот не пойму почему если у меня файл открыт токо для чтения функции getc() ungetc() меняеют его как ни в чем не бывало...
 и в таком случае помоги как правильно считать с файла проверить и обратно запихнуть
 
 делаю
 while(int ch=fgetc(stream)!=EOF)
 {
 ungetc(ch,stream);
 //..
 }
 
 указатель правильно становится на свое место а вот значение левое какое вписывается...че я не так делаю?
 из файла у меня структурки считываются файл бинарный
 |  
						| 
								|  |  
								| « Последнее редактирование: 29-03-2008 14:40 от geg Maneg » |  Записан | 
 |  |  | 
	| 
			| 
					
						| RXL | 
								|  | « Ответ #17 :  29-03-2008 17:28 »   |  | 
 
 geg Maneg, погоди... Последний мосй пост к unget отношения не имеет - я описывал особенность чтения и бесполезность eof. Если об иммитации eof чтением: int my_eof(FILE *f){
 int c;
 
 c = fgetc(f);
 
 if (c == EOF)
 return 1;
 
 unget(f, c);
 return 0;
 }
 Такое возможно только с потоковыми функциями, т.к. они используют буферы в памяти и unget просто помещает символ в буфер. |  
						| 
								|  |  
								|  |  Записан | 
 
 ... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С. |  |  | 
	|  |