argon bulletin board

Факултети => Факултет по математика и информатика => Темата е започната от: my_form в 03.02.2010, 23:42:38

Титла: Файлове в Dev С++
Публикувано от: my_form в 03.02.2010, 23:42:38
Къде мога да намеря разбираемо описание за обработка на файлове в Dev С++? Като казвам разбираемо имам предвид само най-важните неща, без много проверки. Особено ме интересува изтриване на елемент във файла.
За съжаление всеки източник си има свой стил и не е написан нито един учебник където има завършен вариант на програма за файлове.
Благодаря на всеки, който би споделил опита си.
Титла: Re:Файлове в Dev С++
Публикувано от: antoniy в 03.02.2010, 23:53:17
Dev  C++ ти е средата за разработка. Трябва да търсиш как се работи с файлове в C++, който подозирам, че ползваш. Иначе в отговор на въпроса ти за изтриването на елемент - прочети файла, после запиши в нов файл (може и същия, но като го изтриеш) всички елементи, без тези, които искаш да ги няма. При големи файлове пълното изчитане не е добра практика в общия случай заради количеството памет, което ти трябва. Отдавна не съм си играл със С++, но предполагам, че можеш да използваш някакъв seek на позицията и да си спестиш четенето на елементите до мястото на целевия елемент за триене. Тъй като вероятно всичко от този елемент нататък ще бъде изтрито при опит за писане на неговата позиция, то пак трябва да се прочете всичко от тази позиция до края на файла в буфер и после запише на мястото на елемента за изтриване. Не съм напълно сигурен дали ще стане точно така. Това последното си е просто мое разсъждение по спомени.

Поздрави
Титла: Re:Файлове в Dev С++
Публикувано от: my_form в 04.02.2010, 00:07:55
Средата която използвам е Dev C++. Намерих работещ код, с вички търсени от мен възможности, който се оказа, че работи без проблем за  Visual C, но не и за Dev. За съжаление са използвани "думи", които не са ми познати и не мога да ги адаптирам за Dev.  Програмата работи, но точно изтриването не във всички случаи се получава коректно.

Пропуснах да напиша, че се опитвам да изтрия елемент в текстов файл. Но същата възможност ме интересува и за двоичен файл.
Титла: Re:Файлове в Dev С++
Публикувано от: antoniy в 04.02.2010, 09:31:12
Прочете ли какво съм написал? За сега разговора прилича повече на монолог.
Титла: Re:Файлове в Dev С++
Публикувано от: Светослав Енков в 04.02.2010, 11:54:39
В глава 19-та (във втората част е) на учебника на Магдалина Тодорова "Програмиране на С++" има всичко, с примери, за потоците и файловете в С++, С минимални преработки си става всичко за DevC++. Предимно се променят леко описването на header-ите и параметрите на main, както и добавянето на using namespace std, ако примерите са били за VC++. Всичко останало е стандартно - езика си е С++. Конкретно в DevC++ май можеха да се закачат няколко различни компилатора, стандартно май беше mingw32. Всички примери от книгата съм ги подкарвал на DevC++.

За въпроса ти за файловете - няма готови функции за изтриване от файл. Има функция изтриване на файл. Също така, в С++, за разлика от Паскал, няма директно понятието файл от даден тип. Няма дори текстов файл. Просто някои функции на потоците добавят или четат до разделител знака за нов ред.

Какво разбираш под елемент от текстов файл? Отделна дума или отделен ред, параграф? Разделени с какво? Текстовият файл е последователен и единственият начин е да се презапише наново или целият файл или поне от мястото, където се изтрива, до края. Имаш позиция в потока, имаш функции за преместване на позицията. Имаш и йерархия на класовете, наследяващи ios. И това е.

Титла: Re:Файлове в Dev С++
Публикувано от: my_form в 04.02.2010, 15:00:39
Прочете ли какво съм написал? За сега разговора прилича повече на монолог.

Най-напред искам да благодаря за съвета. Всъщност имам следните идеи за изтриване на елемент във файл:
1. Като се запълни елемента за изтриване с празно съдържание (Магдалина Тодорова)
2. Като се запише последния елемент на мястото на елемента за изтриване и се изчисти файла до края.
3. Като се прехвърлят всички следващи елементи напред, заемайки мястото на елемента за изтриване.
4. Като се маркират елементите за изтриване и след това файлът се презапише в нов файл, като се прескочат изтритите.
Както вече написах, кода който имам работи коректно във вижуъл С, но не и в Dev. Ето го:

void Delete(fstream &iofile)
{
iofile.open("Ukazatel.txt", ios::in|ios::out);
string name;
cout<<"Enter name:";
getline(cin, name); cin.get();
string line;
int pos_write, pos_delete;
while (getline(iofile, line))
if (line.find(name)!=string::npos)
{cout<<line<<endl;
cout<<"Are you sure:(Y/N)";
char otg = cin.get(); cin.get();
if (toupper (otg)=='Y')
{iofile.seekg(-32, ios::cur);
pos_write = iofile.tellg();
iofile.seekg (-32, ios::end);
pos_delete = iofile.tellg();
getline (iofile,line);
iofile.seekp (pos_write);
iofile<<line<<endl;
int fd = _open ("Ukazatel.txt", _O_RDWR );
_chsize(fd, pos_delete);
iofile.seekg(pos_write);
}
}
iofile.clear();
iofile.close();
}
Ако някой може да ми помогне да го адаптирам за Dev C ще му бъда много благодарна.
Титла: Re:Файлове в Dev С++
Публикувано от: Светослав Енков в 04.02.2010, 16:02:44
Ох, извинявам се, не знаехме, че си колежка (не правя намек, че колежките са по-проблемни програмистки).

Не каза къде точно ти дава грешки и какви хедъри използваш?

int fd = _open ("Ukazatel.txt", _O_RDWR );
_chsize(fd, pos_delete);

Това ми дава грешка и при мен на DevC++. Откъде го изкопа този код?

P.S. Това наистина си е част от Microsoft CRTL и няма как да го има в DevC++, съжалявам!
http://msdn.microsoft.com/en-us/library/z0kc8e3z%28VS.71%29.aspx

Измисли как да замениш този код с такъв, ползващ ios обектите.
М/у другото - да отвориш вече отворен файл в друг файлов обект, за да му смениш големината,
може да го измисли само върл хакер - противоречи на всякакви идеологии и правила за мен!
Титла: Re:Файлове в Dev С++
Публикувано от: my_form в 04.02.2010, 16:59:18
Ох, извинявам се, не знаехме, че си колежка (не правя намек, че колежките са по-проблемни програмистки).
Едва ли мога да се нарека така  :roll:

Ето хедърите:

#include <iostream>
#include <fstream>
#include <string>
#include<iomanip>
#include <io.h>
#include <fcntl.h>
using namespace std;

Грешката е при изпълнение:  след избор на име за изтриване, последното се записва върху част от избраното. Тоест не се изтрива напълно. Последното се губи наистина.
Титла: Re:Файлове в Dev С++
Публикувано от: Светослав Енков в 04.02.2010, 17:06:23
А на VC++ си го изтрива коректно, така ли?

Може би, защото няма навсякъде проверки, дали файловите операции са успешни и някоя пропада?

Да, аз нямах io.h и fcntl.h, затва нямах _open() и _chsize() функциите.
Титла: Re:Файлове в Dev С++
Публикувано от: my_form в 04.02.2010, 17:17:23
Да, във Visual C работи без проблем, дори ако името се състои от 2 имена.
Титла: Re:Файлове в Dev С++
Публикувано от: antoniy в 04.02.2010, 18:36:13
Един съвет малко встрани от въпроса. Ако използваш езика С за тези неща ще си спестиш тези глупости покрай ios стриймове и обекти. Знанието за тях няма да ти донесе нищо особено в бъдеще, а и ако ти потрябва ще го прочетеш. В С нещата са много по-опростени, имаш функции, имаш типове и си действаш. Да си играеш с обекти без дори да пишеш ООП (да не говорим за майкрософтските извращения) ми се струва излишно и прави ученето на основните неща, свързани с файлове много по-трудно. Това е моето мнение.

Поздрави
Титла: Re:Файлове в Dev С++
Публикувано от: my_form в 04.02.2010, 18:53:04
        Вероятно в С нещата са доста подобни като на Паскал. За съжаление не избирам аз средата, в която ще се пишат програмите.
        Според мен езикът Паскал има много добри възможности за обучение в основните алгоритми, но беше отхвърлен категорично. Колко енергия се разпилява когато без подходящ учебник се иска да бъдат преподадени нови знания? (риторичен въпрос)
Титла: Re:Файлове в Dev С++
Публикувано от: antoniy в 04.02.2010, 19:04:12
Не става дума за среда, а за език. И между другото можеш да използваш С библиотеките за вход и изход като пишеш С++ код, който си се компилира, нормално, от С++ компилатора. Това не е проблем.
Титла: Re:Файлове в Dev С++
Публикувано от: my_form в 05.02.2010, 23:40:45
Елементите на моя файл са от тип структура с едно числово и едно символно поле с дължина 20. Запазих нулевия елемент за съхраняване на текущия брой записи във файла. Опитвам се да реализирам добавяне на елемент след последния, но сега и това не се получава (без нулевия се получаваше). Ето как изглежда моята функция за добавяне:

 void appendF()
  {
    g.open("opit1.bin",ios::in|ios::binary|ios::app);
    g.seekg(0,ios::beg);
    g.read((char*)&z,sizeof(z));
    n1=z.nomer;cout<<n1<<'\n';
    g.seekp(0,ios::end);
    cout<<"Vavedi ime:";cin>>z.ime;
    z.nomer=n1+1;
    g.write((char*)&z,sizeof(z));
    g.seekp(0,ios::beg);
    g.write((char*)&z,sizeof(z));
    g.clear();
    g.close();   
  }
Титла: Re:Файлове в Dev С++
Публикувано от: my_form в 06.02.2010, 23:05:07
 Ето как изглежда работещата функция за добавяне:

 void appendF()
  {
    g.open("buff.bin",ios::out|ios::in|ios::binary);
    g.seekg(0,ios::beg);
    g.read((char*)&z,sizeof(z));
    n1=z.nomer;
    cout<<n1<<'\n';
    g.clear();
    g.seekp(0,ios::end);
    cout<<"Vavedi ime:";cin>>z.ime;g.clear();
    z.nomer=n1+1;
    g.write((char*)&z,sizeof(z));
    g.flush();
    g.seekp(0,ios::beg);
    g.write((char*)&z,sizeof(z));
    g.flush();
    g.close();  
  }

Остана да измисля изтриването.

P.S. Явно не мога да редактирам стари мнения.
Титла: Re:Файлове в Dev С++
Публикувано от: my_form в 09.02.2010, 21:45:40

В средата Dev C++,  EOF  е макрос. Как мога да го добавя на избрана позиция във файла?
Титла: Re:Файлове в Dev С++
Публикувано от: antoniy в 10.02.2010, 09:26:09
EOF == End Of File

Каква позиция, какви 5 лв?
Титла: Re:Файлове в Dev С++
Публикувано от: my_form в 10.02.2010, 16:08:28
              Опитвам се да следвам идеята: нулевият запис съхранява информация за броя записи във файла (това е ясно и от функцията за добавяне, според мен).
              При изтриване вземам последния елемент във файла и го записвам на мястото на посочения елемент за изтриване. Сега трябва да "отрежа" последния елемент от файла, за да не е достъпен при следващи обработки. Мислех си, че това мога да направя като сложа знак за край на файла на избрана от мен позиция. Как става това? Ако EOF е макрос, как се използва той?
              В други версии на езика С има режим ios::trunc има функции  truncate, ftruncate. Как да постигна същия ефект в Dev C за двоични, а не за текстови файлове?
Титла: Re:Файлове в Dev С++
Публикувано от: Светослав Енков в 10.02.2010, 16:23:03
EOF е едновременно и знак за край на файла (ctrl-Z), но само при текстови файлове; така и функция, показваща true, ако в момента файловият указател е достигнал краят на файла (предимно за бинарни файлове, но сигурно работи и с текстови, т.к. реално няма разлика в С/С++ м/у тях).

Не може да няма Truncate (като дума, термин) метод (функция) в класа ios и наследниците му в DevC++ - все пак това е стандартна библиотека. Точно затова мразя DevC++, че не е окомплектован с нормална, добре попълнена система за помощ за класовете с примери и референции, каквото е MSDN (или помощната система на Borland C++).
Титла: Re:Файлове в Dev С++
Публикувано от: my_form в 11.02.2010, 20:40:50
        При изтриване няма начин да не се използва chsize(fd,size); - за смяна размера на файла, която се намира във fcntl.h, тоест това беше което търсех за изрязване от файла. Това са следните два реда, от първия вариант на функцията за изтриване, които се изпълняват и без подчертаващите тирета:

int fd = _open ("Ukazatel.txt", _O_RDWR );  //този параметър _O_RDWR може да се замести с 2
_chsize(fd, pos_delete);


След добре свършена работа  се полага поне малко музика:  :#7:
http://www.youtube.com/watch?v=2S_YrqdA_40&feature=related

    Поздрав към всички, които ми помогнаха!
Титла: Re:Файлове в Dev С++
Публикувано от: neli_randewa в 27.04.2012, 16:11:51
Здравейте!
И аз имам прблем. ГОЛЯМ! ПОМОГНЕТЕ МИ?
Искам да направя информационна ситема, която работи с файлове, чийто елементи са структура. Про извеждането на елементите на файла винаги последния ми го отпечатва два пъти.Успях да добавя елемент, но не мога да промена даден елемент. Дава ми грешка при функцията seekp! Ако се справя с това вероятно ще успея и да изтрий елемент от файла.
#include<iostream.h>
#include<fstream.h>
struct uchenik
{unsigned nom;
char ime[20];
char egn[11];
float usp;
 }u;
int is;



/*void append();
void update();
void choose();
void del();
*/
void create ()
 {  ofstream f;
    f.open("klas.dat",ios::out);
    if (!f) {cout<<"Error"<<"\n";
     system("pause");
     return ;}
    int n=-1, is;
    while (n!=0)
      {cout<<"Nomer: "; cin>>u.nom;
   cout<<"Ime: ";cin>>u.ime;
   cout<<"EGN: "; cin>>u.egn;
   cout<<"Uspeh: "; cin>>u.usp;
    f.write((const char*)&u,sizeof(struct uchenik));
    cout<<"Nov zapis: 1-da,0-ne"<<"\n";
    cin>>n; }
    f.close();
}
void print()
{    ifstream f;
     f.open("klas.dat",ios::in);
    if (!f) {cout<<"Error"<<"\n";
     system("pause");
     return ;}
     do
      {f.read((char*)&u,sizeof(struct uchenik));
      cout<<"Nomer: "<<u.nom<<endl;
     cout<<"Ime: "<<u.ime<<endl;
     cout<<"EGN: "<<u.egn<<endl;
     cout<<"Uspeh: "<<u.usp<<endl<<endl;
      }
       while (!f.eof());
    f.close();
}
void append()
{    ofstream f;
     f.open("klas.dat",ios::app);
     /*if (!f) {cout<<"Error"<<"\n";
     system("pause");
     return ;}*/
     int n=-1;
    while (n!=0)
    {cout<<"Nomer: "; cin>>u.nom;
   cout<<"Ime: ";cin>>u.ime;
   cout<<"EGN: "; cin>>u.egn;
   cout<<"Uspeh: "; cin>>u.usp;
    f.write((const char*)&u,sizeof(struct uchenik));
    cout<<"Nov zapis: 1-da,0-ne"<<"\n";
    cin>>n; }
    f.close();
 }
void update()
 {unsigned long pos;
      fstream f;
      f.open("klas.dat",ios::in|ios::ate|ios::binary);
 unsigned  search_nom;
 float ocenka;
 cout<<"Vyvedi tyrseniq nomer: ";cin>>search_nom;
 cout<<"Vyvedi nova ocenka: ";cin>>ocenka;
 //if (!f) {cout<<"Error"<<"\n";
  //   system("pause");
    // return ;}
      while (f)
      {f.read((char*)&u,sizeof(struct uchenik));
      if(u.nom==search_nom)
      {pos=f.tellg()-sizeof(struct uchenik);
      f.seekp(pos);
      u.usp=ocenka;
      f.write((const char*)&u,sizeof(struct uchenik));
      }
      }
          f.close();
 
  }
int main()
{ int op=-1;
while (op!=0)
  {cout<<"izberete funciq:"<<endl;
   cout<<"     1-sazdavane na fail\n"<<endl;
   cout<<"     2-izvejdane na fail\n"<<endl;
   cout<<"     3-dobavqne na u4enik\n"<<endl;
   cout<<"     4-promqna na ocenka\n"<<endl;
   cout<<"     5-izbor po uspeh\n"<<endl;
   cout<<"     6-iztrivane\n"<<endl;
   cout<<"vsi4ko drugo-krai\n"<<endl;
   cin>>op;
    switch (op)
    { case 1: create();break;
      case 2:print();break;
      case 3:append();break;
     /*case 4:update();break;
      case 5:choose();break;
      case 6:del();break;*/
     default:exit(0); }
     }   
  system("PAUSE");   
  return 0;
}
Титла: Re:Файлове в Dev С++
Публикувано от: lamerko в 28.04.2012, 13:26:33
Здрасти. Сега ставам и не ми се гледа много сорса, но на пръв поглед ми направи впечатлението, че използваш параметър на seekp() от типа на tellg(). Пробвай комбинацията seek/tell да са от един тип - например за двоични файлове да са seekg() и tellg().
Титла: Re:Файлове в Dev С++
Публикувано от: neli_randewa в 29.04.2012, 08:21:25
Благодаря!
Но на мен целта ми е като чета от файла и намеря елемент, който отговаря на някакво условие да се върна снимка назад и да презапиша в-у този елемент, т. е едновременно искам да чета и пиша във файла.
Незнам, трябва да се справя.
Титла: Re:Файлове в Dev С++
Публикувано от: Светослав Енков в 29.04.2012, 10:20:26
Да де, ама ....g и ....p работят с различни буфери и може да са в различен режим. Мисля, че ти пратих някакъв готов пример, не тръгна ли?

В http://en.wikipedia.org/wiki/Data_file - File pointers and random access - казват, че двата указателя са равни, ако е fstream. Така че бъркаш нещо дребно, но принципно.

И още - обхождане се прави с while (), не с do while (), защото може файлът да е празен. Също така, добър подход е след всяка операция read/write/seek да се прави проверка за грешка. Но за конкретният ти въпрос е друг проблема. Всъщност, трябва да си кача devC++ и да ти го компилирам и дебъгна, за да хвана проблема, защото на пръв поглед е ок.

А, да - и желателно е да има винаги и ios::binary

File streams opened in binary mode perform input and output operations independently of any format considerations. Non-binary files are known as text files, and some translations may occur due to formatting of some special characters (like newline and carriage return characters).

Виж и тук секцията Binary files http://www.cplusplus.com/doc/tutorial/files/
Титла: Re:Файлове в Dev С++
Публикувано от: neli_randewa в 29.04.2012, 20:42:28
Благодаря и за тези съвети!
По-късно ще изпробвам!
Ако успея с нещо ще пиша!
Благодаря още веднъж!
Титла: Re:Файлове в Dev С++
Публикувано от: neli_randewa в 29.04.2012, 21:27:33
А що се отнася за цикъла do-while. Да така е, той е останал, защото имах проблеми с отпечатването на файла. Последния елемент ми го печаташе винаги два пъти. Този проблем го оправих. Ето кода - в него работят create, print и append.
#include <iostream>
#include <fstream>
#include <fcntl.h>
using namespace std;

struct uchenik
{unsigned nom;
char ime[20];
char egn[11];
float usp;
 }u;
int is;



/*void append();
void update();
void choose();
void del();
*/
void create ()
 {  ofstream f;
    f.open("klas.dat",ios::out);
    if (!f) {cout<<"Error"<<"\n";
     system("pause");
     return ;}
    int n=-1, is;
    while (n!=0)
      {cout<<"Nomer: "; cin>>u.nom;
   cout<<"Ime: ";cin>>u.ime;
   cout<<"EGN: "; cin>>u.egn;
   cout<<"Uspeh: "; cin>>u.usp;
    f.write((const char*)&u,sizeof(struct uchenik));
    cout<<"Nov zapis: 1-da,0-ne"<<"\n";
    cin>>n; }
    f.close();
}
void print()
{    ifstream f;
     f.open("klas.dat",ios::in);
    if (!f) {cout<<"Error"<<"\n";
     system("pause");
     return ;}
   while (!f.eof())
      {if(!(f.read((char*)&u,sizeof(struct uchenik))))break;
     
      cout<<"Nomer: "<<u.nom<<endl;
     cout<<"Ime: "<<u.ime<<endl;
     cout<<"EGN: "<<u.egn<<endl;
     cout<<"Uspeh: "<<u.usp<<endl<<endl;
      }
     
    f.close();
}
void append()
{    ofstream f;
     f.open("klas.dat",ios::app);
     if (!f) {cout<<"Error"<<"\n";
     system("pause");
     return ;}
     int n=-1;
    while (n!=0)
    {cout<<"Nomer: "; cin>>u.nom;
   cout<<"Ime: ";cin>>u.ime;
   cout<<"EGN: "; cin>>u.egn;
   cout<<"Uspeh: "; cin>>u.usp;
    f.write((const char*)&u,sizeof(struct uchenik));
    cout<<"Nov zapis: 1-da,0-ne"<<"\n";
    cin>>n; }
    f.close();
 }
void update()
 {unsigned long pos;
      fstream f;
      f.open("klas.dat",ios::in|ios::ate|ios::binary);
 unsigned  search_nom;
 float ocenka;
 cout<<"Vyvedi tyrseniq nomer: ";cin>>search_nom;
 cout<<"Vyvedi nova ocenka: ";cin>>ocenka;
 if (!f) {cout<<"Error"<<"\n";
     system("pause");
    return ;}
      while (!f.eof())
      {f.read((char*)&u,sizeof(struct uchenik));
      if(u.nom==search_nom)
      {
                            pos=f.tellp()-sizeof(struct uchenik);
                            cout << pos << endl;
      f.seekp(pos,ios::beg   );
      u.usp=ocenka;
      f.write((const char*)&u,sizeof(struct uchenik));
      }
      }
          f.close();
 
  }
int main()
{ int op=-1;
while (op!=0)
  {cout<<"izberete funciq:"<<endl;
   cout<<"     1-sazdavane na fail\n"<<endl;
   cout<<"     2-izvejdane na fail\n"<<endl;
   cout<<"     3-dobavqne na u4enik\n"<<endl;
   cout<<"     4-promqna na ocenka\n"<<endl;
   cout<<"     5-izbor po uspeh\n"<<endl;
   cout<<"     6-iztrivane\n"<<endl;
   cout<<"vsi4ko drugo-krai\n"<<endl;
   cin>>op;
    switch (op)
    { case 1: create();break;
      case 2:print();break;
      case 3:append();break;
      /*case 4:update();break;
      case 5:choose();break;
      case 6:del();break;*/
     default:exit(0); }
     }   
  system("PAUSE");   
  return 0;
}