Форум: Форум PHPФорум ApacheФорум Регулярные ВыраженияФорум MySQLHTML+CSS+JavaScriptФорум FlashРазное
Новые темы: 0000000
MySQL на примерах. Авторы: Кузнецов М.В., Симдянов И.В. Самоучитель PHP 5 / 6 (3 издание). Авторы: Кузнецов М.В., Симдянов И.В. PHP Puzzles. Авторы: Кузнецов М.В., Симдянов И.В. MySQL 5. В подлиннике. Авторы: Кузнецов М.В., Симдянов И.В. Социальная инженерия и социальные хакеры. Авторы: Кузнецов М.В., Симдянов И.В.
ВСЕ НАШИ КНИГИ
Консультационный центр SoftTime

Разное

Выбрать другой форум

 

Здравствуйте, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: удаление записи из файла на C/C++
 
 автор: psychomc   (20.10.2009 в 10:17)   письмо автору
 
 

пожалуйста, не переносите тему, т.к форум С++ не посещаем...

в общем привожу кусок кода:

// структура
struct goods
{
    // партнамбер 
    // уникальный для каждого товара
    char pn[10];
    // название товара
    char name[30];
    // цена
    int price;
    // количество
    int kol;
} prod;


// вырезка из функции
if ((tf=fopen("product/file1.dat","rb+")) != NULL)
{  
        printf(" Enter part number: ");
    
        gets(goods);
        fread(&prod,sizeof(prod),1,tf);
    
        while (!feof(tf))
        {
            if (strcmp(prod.pn,goods)==0)
            {
                                // каким образом можно удалить из файла текущую запись?
                break;
            }
            fread(&prod,sizeof(prod),1,tf);
        }
        fclose(tf);
        
}

  Ответить  
 
 автор: Волки   (20.10.2009 в 10:22)   письмо автору
 
   для: psychomc   (20.10.2009 в 10:17)
 

файл это не база данных, "просто удалить" касательно файла имеет примерно следующий алгоритм:
* найти удаляемый кусок,
* прочитать оставшийся файл до конца,
* записать поверх удаляемого куска.
Если удаляются несколько записей, то проще в озу сформировать данные для файла, и потом его переписать полностью

  Ответить  
 
 автор: psychomc   (20.10.2009 в 10:28)   письмо автору
 
   для: Волки   (20.10.2009 в 10:22)
 

запись удаляется только одна, я уже и так и так пробовал...но как говорится - "как-то не удалось". поэтому пошёл на крайности и начал флудить на этом форуме. примерчик какой-нибудь не подкините? гугл мне не помог...

  Ответить  
 
 автор: Trianon   (20.10.2009 в 10:35)   письмо автору
 
   для: psychomc   (20.10.2009 в 10:28)
 

Зависит от организации данных внутри файла.
Например, можно прочитать из файла последнюю запись, записать её на место удаляемой, после чего укоротить файл по позиции начала последней записи.

fread, fwrite, fseek, ftell, ftruncate

  Ответить  
 
 автор: psychomc   (20.10.2009 в 14:10)   письмо автору
 
   для: Trianon   (20.10.2009 в 10:35)
 

извиняюсь, не увидел вашего сообщения.
начало понятно, только объясните плиз смысл и как реализуется вот это:
>после чего укоротить файл по позиции начала последней записи
?

  Ответить  
 
 автор: Trianon   (20.10.2009 в 17:14)   письмо автору
 
   для: psychomc   (20.10.2009 в 14:10)
 

>извиняюсь, не увидел вашего сообщения.

Модератора благодарите. :)


>начало понятно, только объясните плиз смысл и как реализуется вот это:
>>после чего укоротить файл по позиции начала последней записи
>?

если запись из файла удалена, значит файл должен стать на одну запись короче, так?

Это смысл.
А реализация... переносимой реализации некоторое время назад не было... Возможно, нету и сейчас. Тут надо смотреть инструментарий выбранной среды исполнения. То есть набор функций работы с файлами, которым можно пользоваться.
http://www.google.ru/search?hl=ru&q=ftruncate

  Ответить  
 
 автор: psychomc   (20.10.2009 в 17:32)   письмо автору
 
   для: Trianon   (20.10.2009 в 17:14)
 

>Модератора благодарите. :)
а я думал это я слепой, и что Вы ничего не предложили а решили поиздеваться :)

>если запись из файла удалена, значит файл должен стать на одну запись короче, так?
согласен
но это всё барахло делаю в borland c++ 3.1, и в Help'е не вижу такой функции и соответвенно не понимаю как её юзать. в гугле пока тоже ничего не нарыл...
такое чувство что придется заходить с другой стороны :(
просто сначала хотелось как можно проще и грамотнее реализовать. тот вариант что написал Волки я вообще не понял.

  Ответить  
 
 автор: psychomc   (20.10.2009 в 17:43)   письмо автору
 
   для: psychomc   (20.10.2009 в 17:32)
 

прочитал на одном форуме:

>А по старинке файл срезали записью в него 0 байт. Ну, т.е. lseek(где_резать); write(file, buf, 0);

скажите, такое пройдет?

  Ответить  
 
 автор: psychomc   (20.10.2009 в 17:50)   письмо автору
 
   для: psychomc   (20.10.2009 в 17:43)
 

а, всё, нашёл, функция chsize :)
буду пытаться :)
в любом случае - спасибо Вам за идею

  Ответить  
 
 автор: psychomc   (21.10.2009 в 12:25)   письмо автору
 
   для: psychomc   (20.10.2009 в 17:50)
 

уря! посидел сегодня полчаса и сделал!
// размер строки структуры
                    s = sizeof(prod);
                    
                    
                                        
                    // переходим на начало строки
                    fseek(tf,-s,1);
                    
                    // сохраняем текущее значение указателя
                    curpos = ftell(tf);
                    
                    // переходим в конец файла
                    fseek(tf, 0L, SEEK_END);
                    
                    // переходим на начало последней строки
                    fseek(tf,-s,1);
                    
                    // считываем последнюю запись
                    fread(&savezap, s, 1, tf);
                    
                    // возвращаем указатель на перезаписываемую запись
                    fseek(tf, curpos, SEEK_SET);
                    
                    // записываем последнюю запись на место удаляемой
                    fwrite(&savezap[0], s, 1, tf);
                    
                    // дескриптор файла
                    handle = fileno(tf);
                    
                    // размер файла
                    fs = filelength(handle);
                    
                    // обрезаем последнюю запись
                    chsize(handle,fs-s);


всё было как бы не так и сложно :)
огромное спасибо Trianon-у!

  Ответить  
 
 автор: Trianon   (20.10.2009 в 10:34)   письмо автору
 
   для: Волки   (20.10.2009 в 10:22)
 

>Если удаляются несколько записей, то проще в озу сформировать данные для файла, и потом его переписать полностью

Это , блин, ни разу не проще, чтоб не сказать - невозможно.
В контексте любых нормальных исполняющих сред предполагается, что объем данных в файле всяко в оперативную память не полезет.

  Ответить  
 
 автор: psychomc   (20.10.2009 в 10:36)   письмо автору
 
   для: Trianon   (20.10.2009 в 10:34)
 

у меня это не актульно...нужно просто сдать курсовой

>* найти удаляемый кусок,
>* прочитать оставшийся файл до конца,
>* записать поверх удаляемого куска.

вот этот вариант мне подходит. но пока не получается реализовать

  Ответить  
 
 автор: Волки   (20.10.2009 в 11:54)   письмо автору
 
   для: psychomc   (20.10.2009 в 10:36)
 

строго не судите, уже год на С не програмил, позабылось немного,
и нужно будет в отладчике все это естественно продебажить
function killGoodById (int id) {
    FILE file = fopen("product/file1.dat","rb+");
    char strId[10];
    sprintf (strId, "%d", id);
    if (file == NULL) return NULL;

    prod *oneGoods = new prod;
    while (!eof(file)) {
        fread(oneGoods, sizeof(prod), 1, file);
        if ( strcmp(strId, oneGoods->pn)==0)
        {
            // найден нужный элемент, удалим
            fseek(file, 0L, SEEK_END);
            int size = ftell (file);
            fseek (file, 0, SEEK_SET);
            
            size -= ftell(file); //размер оставшегося файла
            char *buffer = new char[ size ];
            fread (buffer, size, 1, file);
            fseek (file, -sizeof(prod), SEEK_SET);
            fwrite (buffer, size, 1, file);
            delete buffer;
            break;
        }
    }

    fclose(file);
    delete oneGoods;
}

  Ответить  
 
 автор: psychomc   (20.10.2009 в 12:08)   письмо автору
 
   для: Волки   (20.10.2009 в 11:54)
 

не совсем понял как вызвать функцию из программы, точнее что в неё передать...

  Ответить  
 
 автор: psychomc   (20.10.2009 в 12:12)   письмо автору
 
   для: psychomc   (20.10.2009 в 12:08)
 

а если такой вариант


................
if (strcmp(prod.pn,goods)==0)
{
   // получаем текущую позицию в файле
   int pos = ftell(tf);
   
}
.................


можно ли считать файл с этой позиции и скажем запихнуть в перменную и записать с помощью fwrite с этой позиции??

  Ответить  
 
 автор: Волки   (20.10.2009 в 12:39)   письмо автору
 
   для: psychomc   (20.10.2009 в 12:12)
 

> записать с помощью fwrite с этой позиции
с этой позиции нельзя, т.к. считав информацию про конкретный товар - указатель передвинулся, и надо вернуть назад на "размер товара"
а внутрь функции передается идентификатор удаляемой записи.
и кстати, у вас структура выравнена по границе 8 байт?

  Ответить  
 
 автор: psychomc   (20.10.2009 в 12:46)   письмо автору
 
   для: Волки   (20.10.2009 в 12:39)
 

>и кстати, у вас структура выравнена по границе 8 байт?
на этот вопрос у меня нет ответа т.к я не понял о чём Вы :(

указатель вот так получается возвратить обратно:

fseek(tf,-sizeof(prod),1);


так можно ли в таком случае записать переместив?

  Ответить  
 
 автор: Волки   (20.10.2009 в 13:23)   письмо автору
 
   для: psychomc   (20.10.2009 в 12:46)
 

sizeof (prod) = 48 байт, что кратно 8 .
> так можно ли в таком случае записать переместив?
Да, думаю можно, пробовать надо, дебугером.

  Ответить  
 
 автор: psychomc   (20.10.2009 в 13:40)   письмо автору
 
   для: Волки   (20.10.2009 в 13:23)
 

никак не могу считать файл полностью с этой позиции

  Ответить  
Rambler's Top100
вверх

Rambler's Top100 Яндекс.Метрика Яндекс цитирования