Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

RFpro.ru: Программирование на C / C++


Хостинг портала RFpro.ru:
Московский хостер
Профессиональный ХОСТИНГ на базе Linux x64 и Windows x64

РАССЫЛКИ ПОРТАЛА RFPRO.RU

Лучшие эксперты по данной тематике

Асмик Гаряка
Статус: Академик
Рейтинг: 10474
∙ повысить рейтинг »
Коцюрбенко Алексей aka Жерар
Статус: Советник
Рейтинг: 4152
∙ повысить рейтинг »
CradleA
Статус: Бакалавр
Рейтинг: 2500
∙ повысить рейтинг »

/ КОМПЬЮТЕРЫ И СОФТ / Программирование / C/C++

Номер выпуска:1744
Дата выхода:18.05.2012, 19:30
Администратор рассылки:Киселёва Алёна aka Verena (Академик)
Подписчиков / экспертов:138 / 92
Вопросов / ответов:1 / 2

Консультация # 186035: Здравствуйте, уважаемые эксперты! Прошу вас ответить на следующий вопрос: Есть вот такой текст программы:

Код :
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

//Ячейка хранения
typedef struct 
{
  unsign
...

Консультация # 186035:

Здравствуйте, уважаемые эксперты! Прошу вас ответить на следующий вопрос:
Есть вот такой текст программы:

Код :
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

//Ячейка хранения
typedef struct 
{
  unsigned int Number;      //Номер записи
  unsigned int Length1;      
  unsigned int Length2;      
  unsigned int Length3;  
 } tdata_len;


//Сохранение данных в файл
//Параметр:
//   Item - одна ячейка хранения
void SaveToFile(tdata_len * Item)
{
  FILE * file;
    
  if ((file = fopen("data.dat", "a"))==NULL)
    printf("Не могу открыть файл для записи.");
  else
  {
    fwrite(Item, sizeof(tdata_len), 1, file);
    fclose(file);
  }    
};

//Чтение данных о строке из файла и вывод на экран
//Возвращаемое значение - количество ячеек хранения в файле
int ReadFromFile1()
{
  FILE * file;
  tdata_len * Item;
  int Count = 0;
    
  
  if ((file = fopen("data.dat", "r"))==NULL)
    printf("Не могу открыть файл для чтения.");
  else
  {
    Item = (tdata_len *) malloc(sizeof(tdata_len));
    while (!feof(file))
    {
      
      fread(Item, sizeof(tdata_len), 1, file);
      printf("Номер ячейки : %d\n", Item->Number);
      printf("Длина 1      : %d\n", Item->Length1);
      printf("Длина 2      : %d\n", Item->Length2);
      printf("Длина 3      : %d\n", Item->Length3);
      printf("------------------------\n");
      Count++;
    };  
    fclose(file);
    free(Item);
  }

  return Count;
};

int main()
{
  tdata_len * mycell;
  int i = 0;
  int Count = 0;
  
  srand(time(NULL));
  mycell = (tdata_len *) malloc(sizeof(tdata_len));
   
  //Файла пока не существует. Вводим новые данные
  for (i=1;i<4;i++)
  {
    //Заполнение данных
    mycell->Number = i;
    mycell->Length1 = rand();
    mycell->Length2 = rand();
    mycell->Length3 = rand();
    
    //Запись данных в файл
    SaveToFile(mycell);
  };
  
  //Читаем данные из файла и выводим на экран
  Count = ReadFromFile1();
  
  free(mycell);
  
  return 0;
}

Результат получается такой:
© Цитата:
Номер ячейки : 1
Длина 1 : 18336
Длина 2 : 10247
Длина 3 : 2159
------------------------
Номер ячейки : 2
Длина 1 : 5070
Длина 2 : 6043
Длина 3 : 22372
------------------------
Номер ячейки : 3
Длина 1 : 16295
Длина 2 : 13428
Длина 3 : 8190
------------------------
Номер ячейки : 3
Длина 1 : 16295
Длина 2 : 13428
Длина 3 : 8190
------------------------

Вопрос такой:
почему функция ReadFromFile1() последняя ячейка №3 выводится 2 раза (хотя файл имеет размер 3*16 байт = 48, т.е. записано ровно три ячейки)?

Дата отправки: 15.05.2012, 19:14
Вопрос задал: sir Henry (Старший модератор)
Всего ответов: 2
Страница онлайн-консультации »


Консультирует Micren (Профессор):

Здравствуйте, sir Henry!
Потому, что проверку на EOF надо делать после чтения, а не перед. Так у Вас получается, что данные не считаны(остались от предыдущего цикла), но встретился конец файла и программа вывела данные, которых нет.

Код :
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
//Ячейка хранения

typedef struct
{
    unsigned int Number; //Номер записи
    unsigned int Length1;
    unsigned int Length2;
    unsigned int Length3;
} tdata_len;
//Сохранение данных в файл
//Параметр:
// Item - одна ячейка хранения

void SaveToFile(tdata_len * Item)
{
    FILE * file;
    if ((file = fopen("data.dat", "a")) == NULL)
        printf("Не могу открыть файл для записи.");
    else
    {
        fwrite(Item, sizeof (tdata_len), 1, file);
        fclose(file);
    }
};
//Чтение данных о строке из файла и вывод на экран
//Возвращаемое значение - количество ячеек хранения в файле

int ReadFromFile1()
{
    FILE * file;
    tdata_len * Item;
    int Count = 0;
    if ((file = fopen("data.dat", "r")) == NULL)
        printf("Не могу открыть файл для чтения.");
    else
    {
        Item = (tdata_len *) malloc(sizeof (tdata_len));
        fread(Item, sizeof (tdata_len), 1, file);
        while (!feof(file))
        {
            printf("Номер ячейки : %d\n", Item->Number);
            printf("Длина 1 : %d\n", Item->Length1);
            printf("Длина 2 : %d\n", Item->Length2);
            printf("Длина 3 : %d\n", Item->Length3);
            printf("------------------------\n");
            Count++;
            fread(Item, sizeof (tdata_len), 1, file);
       };
        fclose(file);
        free(Item);
    }
    return Count;
};

int main()
{
    tdata_len * mycell;
    int i = 0;
    int Count = 0;
    srand(time(NULL));
    mycell = (tdata_len *) malloc(sizeof (tdata_len));
    //Файла пока не существует. Вводим новые данные
    for (i = 1; i < 4; i++)
    {
        //Заполнение данных
        mycell->Number = i;
        mycell->Length1 = rand();
        mycell->Length2 = rand();
        mycell->Length3 = rand();
        //Запись данных в файл
        SaveToFile(mycell);
    };
    //Читаем данные из файла и выводим на экран
    Count = ReadFromFile1();
    free(mycell);
    return 0;
}

Код :
Номер ячейки : 1
Длина 1 : 678671864
Длина 2 : 2097842989
Длина 3 : 1266140926
------------------------
Номер ячейки : 2
Длина 1 : 1400430739
Длина 2 : 1258691281
Длина 3 : 248056681
------------------------
Номер ячейки : 3
Длина 1 : 393117925
Длина 2 : 463589343
Длина 3 : 911030439
------------------------

Консультировал: Micren (Профессор)
Дата отправки: 15.05.2012, 19:43
Рейтинг ответа:

НЕ одобряю +1 одобряю!


Консультирует Хватов Сергей (Академик):

Здравствуйте, sir Henry!

Вы слишком рано проверяете конец файла. Он же начинает возвращать 1 только после попытки чтения дальше конца файла, и у вас получается лишняя итерация со старыми данными Правильно будет проверить сразу после fread():

Код :
for (;;) {
  fread(...);
  if (feof(file)) break;
  /* работа с результатом */
}

Но только сам fread() тоже возвращает осмысленное значение (количество прочитанных элементов), так что понятнее написать как-то так:
Код :
while(fread (Item, sizeof (*Item), 1, file) > 0) {
 /* работа с результатом */
}

Консультировал: Хватов Сергей (Академик)
Дата отправки: 15.05.2012, 19:47

5
нет комментария
-----
Дата оценки: 16.05.2012, 03:46

Рейтинг ответа:

НЕ одобряю +1 одобряю!


Оценить выпуск | Задать вопрос экспертам

главная страница  |  стать участником  |  получить консультацию
техническая поддержка  |  восстановить логин/пароль

Дорогой читатель!
Команда портала RFPRO.RU благодарит Вас за то, что Вы пользуетесь нашими услугами. Вы только что прочли очередной выпуск рассылки. Мы старались. Пожалуйста, оцените его. Если совет помог Вам, если Вам понравился ответ, Вы можете поблагодарить автора - для этого в каждом ответе есть специальные ссылки. Вы можете оставить отзыв о работе портале. Нам очень важно знать Ваше мнение. Вы можете поближе познакомиться с жизнью портала, посетив наш форум, почитав журнал, который издают наши эксперты. Если у Вас есть желание помочь людям, поделиться своими знаниями, Вы можете зарегистрироваться экспертом. Заходите - у нас интересно!
МЫ РАБОТАЕМ ДЛЯ ВАС!



В избранное