Форум программистов, компьютерный форум CyberForum.ru
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
Рейтинг: Рейтинг темы: голосов - 9, средняя оценка - 4.89
kravam
быдлокодер
1695 / 882 / 45
Регистрация: 04.06.2008
Сообщений: 5,459
#1

вопрос к спецам: почему функция fputc при работе не устанавливает счётчик файла в конец? - C++

22.02.2010, 11:33. Просмотров 1089. Ответов 14
Метки нет (Все метки)

Друзья!
То есть написана программка. С клавы вводится ОДИН символ и он запихивается в файл.
А потом этот файл с помощью функции fread считывается обратно в переменную.
Это реализовано в цикле, условие выхода из которого- счётчик считанных байтов достиг конца файла

Но после первого считывания счётчик байтов не достигает конца файла!
Почему? Загадка. Файл имеет размер равный 1, содержит на самом деле один символ (смотрено в hex редакторе), по идее ьон должен считаться и всё, конец цикла

Но то ли функция fread не передвигает счётчик, то ли feof возвращает непрпавильное значение, но мы имеем второе считывание. В чём тут дело?

Эту идею можно и по другому реализовать, но хотелось бы разобраться именно в этом вопросе. Спасибо.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <stdio.h>
int main() {
 
 char simvol;
 int i;
 FILE* f;
 
 //Вводим символ 
 printf ("vvedi odin simvol ");
 scanf ("%c", &simvol);
 
 //Теперь запихаем этот символ в файл
 if (!(f= fopen ("fail","wb"))) {
  printf ("fail ne otkrit\n");
  getchar ();
 } 
 printf ("zapisanni simvol est %c\n", fputc (simvol, f));
 getchar ();
 fclose (f);
 
 
 
 //а теперь попробуем считать. Символ будет считываться 2 раза!
 if (!(f= fopen ("fail","rb"))) {
  printf ("fail ne otkrit\n");
  getchar ();
 } 
 
 //непосредственно считывание
 i= 0;
 while(!feof(f)) {
  fread(&simvol, 1, 1, f);
  i++;
  printf("i= %d\n", i);
 }
 printf("kak vidim, i== 2");
 fclose(f);
 getchar ();
 return 0;
}
Добавлено через 3 минуты
Прошу прощения, в заголовке надо исправить fputc на fread
Товарищи модераторы, исправьте, пожалуйста. Спасибо.
0
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
22.02.2010, 11:33
Здравствуйте! Я подобрал для вас темы с ответами на вопрос вопрос к спецам: почему функция fputc при работе не устанавливает счётчик файла в конец? (C++):

Функция getc (FILE*) при первом вызве считывает НЕ ПЕРВЫЙ символ файла.Почему? - C++
Друзья! Здравствуйте! Вот код. #include &lt;iostream&gt; using namespace std; int main () { FILE* zapis_v_fail; FILE*...

Вопрос к спецам - Windows XP
На ноуте Acer стоят две винды, 7 и XP, по умолчанию была загрузка 7, надо было переделать на XP, отредактировал диспетчер загрузки в XP,...

Вопрос к спецам по ремонту. - Ремонт ноутбуков
Времени доброго всем. Ноут ASUS K52J. Чуть меньше года. А случилось вот что: После просмотра кина выключил комп как всегда, не след день...

Вопрос к прожженным спецам XL ..... - MS Excel
Как запрограмировать в XL (ячейку),чтобы на нее нажать и появится запрограмируемое (мною) изображение (фотография крупным...

Чудеса разгона . Вопрос к спецам. - Процессоры
Имеется системник Intel Celeron 1300 (13*100) Сокет 370, мать Gigabyte GA - 60XT. Немного добваил частоты процессору (13*115), но в этом...

Почему не видит конец файла? - Visual C++
Есть процедура записи отрезка в файл: void write_to_file(double a, double b) { FILE *file; fopen_s(&amp;file, file_name, &quot;a+&quot;); ...

Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
лендер
46 / 46 / 2
Регистрация: 12.01.2010
Сообщений: 183
22.02.2010, 12:04 #2
попробуй заменить
C
1
2
3
4
5
 while(!feof(f)) {
  fread(&simvol, 1, 1, f);
  i++;
  printf("i= %d\n", i);
 }
на
C
1
2
3
4
5
6
while(!feof(f)) {
  fread(&simvol, 1, 1, f);
if(feof(f)) break;
  i++;
  printf("i= %d\n", i);
 }
0
kravam
быдлокодер
1695 / 882 / 45
Регистрация: 04.06.2008
Сообщений: 5,459
22.02.2010, 12:45  [ТС] #3
Заменил, сработало.
Но в чём прикол, я понять не могу.
Почему функция feof () в одном случае возвращает 0, а в другом 1?

Ничё не могу понять. Хотелось бы услышать ответ знающих людей.
0
easybudda
Модератор
Эксперт CЭксперт С++
9625 / 5573 / 947
Регистрация: 25.07.2009
Сообщений: 10,708
22.02.2010, 13:07 #4
Цитата Сообщение от kravam Посмотреть сообщение
Но в чём прикол, я понять не могу.
Да всё правильно.
1. проверяется условие ( !feof(f) )
2. читается символ fread(&simvol, 1, 1, f); вот тут, если неудачно, feof вернула бы 1
3. i++ и тд. - не должно выполняться, если достигнут конец файла...
Просто цикл неправильно организован
C
1
2
3
4
5
...
int ch;
while ( ( ch = fgetc(f) ) != EOF ){
  ...
}
или
C
1
2
3
...
while ( fread(&simvol, 1, 1, f) ){
  ...
0
kravam
быдлокодер
1695 / 882 / 45
Регистрация: 04.06.2008
Сообщений: 5,459
22.02.2010, 13:22  [ТС] #5
C++
1
2
3
4
5
while(!feof(f)) {
  fread(&simvol, 1, 1, f);
  i++;
  printf("i= %d\n", i);
 }
Тут что неправильно?
Давай пошагово. Итак, в файле один символ

1) feof возвращает 0 (так?)
2) зашли в тело цикла считали один символ
3) инкременировали i
4) пошли на проверку условия

...Теперь отвлекёмся и зададимся вопросом:
должно ли условие выполняться?
Или уж совсем просто: что должна вернуть функция feof,
учитывая, что в файле ОДИН симол и тот считан?
Ну, наверное единицу, угу?

Но ничё подобного, возаращается НОЛЬ, (наблюдаем выполнение тела цикла
второй раз).

Вопрос: почему feof возвращает ноль?

Добавлено через 2 минуты
P. S. Я понимаю, что если сделать, как говорит лендер, то некотрый результат будет достигнут. Некотоый, но не желательный. Ибо заявленый результат: показать, что непрпавильно в моём коде.
спасибо за понимание.
0
easybudda
Модератор
Эксперт CЭксперт С++
9625 / 5573 / 947
Регистрация: 25.07.2009
Сообщений: 10,708
22.02.2010, 13:40 #6
Цитата Сообщение от kravam Посмотреть сообщение
Вопрос: почему feof возвращает ноль?
потому, что feof() вернёт 1 не после чтения первого (и единственного) байта, а после попытки чтения второго (несуществующего). Сначала нужно выполнить операцию (чтения в данном случае), а потом её результаты проверять. У Вас же наоборот получается.
0
kravam
быдлокодер
1695 / 882 / 45
Регистрация: 04.06.2008
Сообщений: 5,459
22.02.2010, 13:57  [ТС] #7
Всё понятно! И можно было бы подумать о закрытии темы, если бы Ваши слова не вступали в противоречие с реальностью. Вот код Лендера.
C++
1
2
3
4
5
6
while(!feof(f)) {
  fread(&simvol, 1, 1, f);
  if(feof(f)) break;
  i++;
  printf("i= %d\n", i);
 }
Судя по тому, что Вы сказали, feof после первого считывания должна что вернутть? 0! Поскольку попытки чтения второго (несуществующего) просто нет!

Но щас она возвращает 1!

Как быть?
То, что Вы говорите, объясняет мой код, но АБСОЛЮТНО не объясняет код Лендера. А ведь у нас различия-то минимальны! Он вызывает feof (второй раз) СРАЗУ после чтения символа, а я... так и я тоже СРАЗУ, просто делаю это в условии, а он в теле цикла. Всё! (инкременацию i опускаю пока.)

Добавлено через 1 минуту
И извините, при таком раскладе я, при всём уважении к Вам, крайне не удовлетворён объяснением.
0
easybudda
Модератор
Эксперт CЭксперт С++
9625 / 5573 / 947
Регистрация: 25.07.2009
Сообщений: 10,708
22.02.2010, 14:06 #8
Цитата Сообщение от kravam Посмотреть сообщение
C++
1
2
fread(&simvol, 1, 1, f); 
if(feof(f)) break;
Цитата Сообщение от easybudda Посмотреть сообщение
Сначала нужно выполнить операцию (чтения в данном случае), а потом её результаты проверять.
После чтения первого символа if(feof(f)) возвращает 0, цикл отрабатывает. После попытки чтения второго if(feof(f)) вернёт 1 и выполнится команда break; При таком подходе можно вообще вот так:
C
1
2
3
4
5
6
while(1) {
  fread(&simvol, 1, 1, f);
  if(feof(f)) break;
  i++;
  printf("i= %d\n", i);
 }
сделать и тоже будет работать.
0
kravam
быдлокодер
1695 / 882 / 45
Регистрация: 04.06.2008
Сообщений: 5,459
22.02.2010, 14:30  [ТС] #9
Ага. То есть если вызов fread неудачен, то feof вернёт 1
Что ж, это объясняет многое, но не всё.

Снова обратимся к моему коду и опять протрассируем его пошагово с учётом вновь полученых знаний.
C++
1
2
3
4
5
while(!feof(f)) {
  fread(&simvol, 1, 1, f);
  i++;
  printf("i= %d\n", i);
 }
1) feof возвращает 0 (так?)
2) зашли в тело цикла считали один символ
3) инкременировали i
4) пошли на проверку условия
5) условие выполняется потому, что предыдущее считывание было удачным

...И вот тут стоп. Я понимаю, почему выполняется условие, Вы объяснили. (Предыдущий вызов fread был удачным, вот оно и выполняется)

А темерь внимание, вопрос, которого мы не касались:


6) зашли в тело цикла удачно считали считанный уже символ.

Почему? Он ведь уже считан? По идее вызов fread должен завершиться неудачно.
Но нет, символ считывается. Почему?
0
easybudda
Модератор
Эксперт CЭксперт С++
9625 / 5573 / 947
Регистрация: 25.07.2009
Сообщений: 10,708
22.02.2010, 14:34 #10
Цитата Сообщение от kravam Посмотреть сообщение
Почему? Он ведь уже считан? По идее вызов fread должен завершиться неудачно.
Но нет, символ считывается. Почему?
Вот именно уже считан. И после неудачной попытки чтения следующего просто не изменяется.
1
kravam
быдлокодер
1695 / 882 / 45
Регистрация: 04.06.2008
Сообщений: 5,459
22.02.2010, 15:12  [ТС] #11
Ну вот теперь всё понятно и всё просто. Учитываем, что feof возвращает значение в зависимости от значения, возвращённого fread, а я не знал этого. Думал, считался единственный символ и feof вернёт не ноль, но я ошибался. Большое спасибо!
0
alkagolik
Заблокирован
09.11.2012, 12:26 #12
kravam, вообще - то как бы делается вот так
C
1
2
3
4
5
6
7
while (expression) {
    ret = fread(bufer, size, nmemb, FILE);
    if (ret == EOF)
        break;
    if ( ret != nmemb )
        work_exeption(...);
}
0
Croessmah
09.11.2012, 12:28
  #13

Не по теме:

Цитата Сообщение от alkagolik Посмотреть сообщение
kravam, вообще - то как бы делается вот так
теме почти 3 года...

0
alkagolik
Заблокирован
09.11.2012, 13:00 #14
Croessmah, да. она просто сегодня упомянулась в соседней теме, да и не раскрыт вопрос. Считаю что поставил в нем точку. ИМХО

Не по теме:

считай меня некропостером)))

0
kravam
09.11.2012, 14:54  [ТС]     вопрос к спецам: почему функция fputc при работе не устанавливает счётчик файла в конец?
  #15

Не по теме:

А я люблю добросовестных парней, которым по фигу, как их назовут- некропостерами или ещё как-то. Уж ни-то точно 100 раз подумают, прежде чем тему новую скропать, уже за одно это им спасибо.

0
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
09.11.2012, 14:54
Привет! Вот еще темы с ответами:

Аналог !foef, или как найти конец строки при работе с файлом - C++
День добрый. Если вопрос касается конца файла, то можно написать так: long count; char massiv; FILE f1 ...

Функция fread: Для чего указатель устанавливается в конец файла? - C (СИ)
Доброго времени суток! Не могу понять для чего при чтении данных с текстовго документа нужно сделать следующие действия: 1) установить...

Вопрос по безопасности кода в многопоточном приложении при работе с сетью - Java ME
Есть следующий код: DefaultHttpClient httpClient = new DefaultHttpClient(httpParams); ...

Как при чтении файла проверить достигнут ли конец файла? - Visual Basic .NET
Как при чтении файла проверить достигнут ли конец файла? Dim Red As IO.BinaryReader Red = New...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
Yandex
Объявления
09.11.2012, 14:54
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru