[ hninel @ 25.05.2004. 21:35 ] @
Code:


#include <iostream>
#include <fstream>
#include <conio.h>
#include <vector>
#include <string>

using namespace std;

 template <typename elemType>
 void readFromFile(string filename, vector <elemType> &vec)
 {
        fstream iFile;
        iFile.open (filename.c_str(), ios::in | ios::binary);
        if (!iFile)
        {
                cerr << "\nNemogu otvoriti " << filename;
                return;
        }
        
        while (iFile)
        {

                elemType *obj=new elemType;
                iFile.read( (char*)obj, sizeof(elemType));
                vec.push_back(*obj);
         }

     iFile.close();
 }

 template <typename elemType>
 void writeToFile(string filename, vector <elemType> &vec)
 {
        ofstream oFile;
        oFile.open(filename.c_str(), ios::trunc | ios::binary | ios::out);
        if (!oFile)
        {       cerr << "\nNemogu da otvorim ya upis fajl: " << filename;
                return;
        }

       for (int i=0; i<vec.size(); i++)
       {
             oFile.write( (char *)&vec[i], sizeof(elemType));
       }
       oFile.close();

 }


template <typename elemType>
void showAll(vector <elemType> &vec)
{
        for (int i = 0; i<vec.size(); i++)
        {
                cout << vec[i] << endl;
        }
}


void main (void)
{

  vector <string> vecStr;
  strting str;
  char c;

  do
  {
        cout << "\nUnesite rijec: " << endl;
        cin >> str;
        vecStr.push_back(str);

        cout << "\Ako zelite jos pritisnite 'y'" << endl;

        cin >> c;
  }while (c=='y' || c=='Y');

  writeToFile("asd.dat", vecStr);
  vecStr.clear();

  readFromFile("asd.dat", vecStr);
  showAll(vecStr);


getch();
return;

}


Ovo je code s kojim imam problema. Kada unesem string,kao u gornjem primjeru i nesto upisem (par stringova) te to snimim u file i onda iscitam u vector on mi pokazuje nekakve znakove koji nemaju veze sa mojim tekstom.
Isto tako kada umjesto stringa stavim recimo int, dobijem, kada iscitam ponovo iz filea u vector, moje brojeve i jos jedan 6-sifreni broj.

Moze li mi neko malo ovo objasniti.

Ovaj code je samo jednostavniji jer sa ovim template-om kojim citam i pisem u fajl hocu da radim sa drugim objektima klasa koje napravim. Do sada imam samo probleme.

Hvala unaprijed.

////////////////////
[ filmil @ 25.05.2004. 22:11 ] @
Koliko vidim, ti bi želeo da napraviš perzistentne objekte uz pomoć šablona.

Na žalost, to neće ići tako kako si zamislio. Najpre je zapisivanje pogrešno jer ti pokušavaš da upišeš &vec[ i] koji je forsirano pretvoren u char*. Za upisivanje u fajl se onda koriste pravila koja važe za ASCIIZ, što u opštem slučaju ne mora da bude primenljivo na tvoj objekat i u slučaju stringa u primeru ne daje tačan rezultat.

Drugi je problem sa time što ćeš, ukoliko je objekat agregat (a praktično svaki složeni objekat pa i string jeste agregat) na disk upisati niz nekakvih pointera koji zavise od trenutne memorijske slike programa - koja se menja praktično iz takta u takt. Drugim rečima, ono što si zapisao na disk je potpuno beskorisno sa stanovišta čuvanja objekata.

Ispravna perzistencija je malko komplikovana stvar; nisam čuo za neku jednostavnu c++ biblioteku za to. Koliko vidim ni http://www.boost.org nema neki pametan savet oko toga. Perzistencija u Javi na primer je praktično ugrađena u sve objekte koji mogu da se „serijalizuju“, dakle deo je dizajna jezika. C++ koliko znam to nema.

f
[ Dragi Tata @ 26.05.2004. 16:21 ] @
Code:

#include <iostream>
#include <fstream>
#include <conio.h>
#include <vector>
#include <string>

using namespace std;

 template <typename elemType>
 void readFromFile(string filename, vector <elemType> &vec)
 {
        fstream iFile;
        iFile.open (filename.c_str(), ios::in | ios::binary);
        if (!iFile)
        {
                cerr << "\nNemogu otvoriti " << filename;
                return;
        }
        
        while (iFile.peek() != char_traits<char>::eof ( ))
        {

                elemType *obj=new elemType;
                //iFile.read( (char*)obj, sizeof(elemType));
                iFile >> *obj;
                vec.push_back(*obj);
         }

     iFile.close();
 }

 template <typename elemType>
 void writeToFile(string filename, vector <elemType> &vec)
 {
        ofstream oFile;
        oFile.open(filename.c_str(), ios::trunc | ios::binary | ios::out);
        if (!oFile)
        {       cerr << "\nNemogu da otvorim ya upis fajl: " << filename;
                return;
        }

       for (int i=0; i<vec.size(); i++)
       {
             //oFile.write( (char *)&vec[i], sizeof(elemType));
            oFile << vec[i];
       }
       oFile.close();

 }


template <typename elemType>
void showAll(vector <elemType> &vec)
{
        for (int i = 0; i<vec.size(); i++)
        {
                cout << vec[i] << endl;
        }
}


void main (void)
{

  vector <string> vecStr;
  string str;
  char c;

  do
  {
        cout << "\nUnesite rijec: " << endl;
        cin >> str;
        vecStr.push_back(str);

        cout << "Ako zelite jos pritisnite 'y'" << endl;

        cin >> c;
  }while (c=='y' || c=='Y');

  writeToFile("asd.dat", vecStr);
  vecStr.clear();

  readFromFile("asd.dat", vecStr);
  showAll(vecStr);


getch();
return;

}


Samo treba koristiti operatore >> i << umesto one nebuloze sa "sirovim" pisanjem.
[ filmil @ 26.05.2004. 16:42 ] @
... i povrh toga, objekti moraju da znaju da se „zapišu“ i „iščitaju“ uz pomoć operatora << i >>. Za jednostavne objekte to nije problem, ali kada imaš međuzavisnosti, stvari se komplikuju.

f
[ Dragi Tata @ 26.05.2004. 16:52 ] @
Naravno. Za složenije slučajeve treba koristiti biblioteke kao što je Boost serialization library

http://www.rrsd.com/boost/

ili nešto slično.

Inače, u poređenju sa Javom, C++ ima statički objektni model u kome ima malo mesta za refleksiju, serijalizaciju i slične stvari. To ima svoje nedostatke, ali i prednosti (efikasnost, type safety...).

[ Reljam @ 26.05.2004. 16:54 ] @
Na koj nacin je C++ objektni model vise type-safe od .NETovog? Brzi, da. Type-safe, ne.
[ Dragi Tata @ 26.05.2004. 17:07 ] @
Hehe, ne sećam se da sam spomenuo .NET, ali kad se već javljaš, evo jedan prost primer: uz pomoć refleksije, možeš lako da pristupiš privatnim članovima klase.
[ Dragi Tata @ 26.05.2004. 17:19 ] @
I da ne zaboravim. Dynamic method invocation (podržavaju ga i Java i .NET) ume da bude zgodna stvar, ali direktno ugrožava type safety. Ako pozoveš metod koji ne postoji, dobićeš run-time izuzetak. Kod C++a, tako nešto nije moguće - ako ga kompajler propusti, znači metod postoji.
[ Reljam @ 26.05.2004. 17:24 ] @
To nije type-safety issue. I u C++u ti mozes da pristupis private clanovima sa malo kopanja po memoriji.

.NET je cak i vise type safe. Ti u C++u mozes da uradis ovo:

A *a = new A;
[... par hiljada linija koda i nekoliko poziva dalje...]
B *b = (b*) a;

i da tako b-u dodelis pointer na a iako ta dva nemaju nikakve veze (prilikom derefenciranja b, stvar puca). Lose kastovanje je mnogo veci problem od pozivanja private metoda na silu.

Type-safety se odnosi na sprecavanje nehoticnih gresaka. Ako neko zeli namerno da zaobidje tu sigurnost u svom programu, to je njegova stvar.
[ Dragi Tata @ 26.05.2004. 17:59 ] @
.NET ima bolji run-time type safety (baci izuzetak umesto da prsne kod lošeg kastovanja), ali je compile-time type safety slabiji. Dinamička invokacija metoda je jedan primer, a nedostatak type-safe kontejnera je još ozbiljniji problem (mada bi to trebalo da bude sređeno kad stignu genericsi).
[ Reljam @ 26.05.2004. 18:29 ] @
Ja sve vreme racunam na genericse... ;) .NET 2.0 je lepa stvar.

U svakom slucaju, sa genericsima, type safety u .NETu je bolji nego u C++u, i naravno refleksija omogucava gomilu novih scenarija. Naravno, sve je to na ustrp performansi, tako da treba izabrati pravi alat za pravu priliku.
[ hninel @ 03.06.2004. 20:24 ] @
Da se malo vratimo na temu...

Rijesio sam problem tako da cu pisati i citati iz file-a da ne koristim ios_base::binary, jer mi nikako ne vraca ispravno podatke.

Imam slijedeci code
Code:
template <typename T>
vector <T> RWdata<T>::readFromFile(string filename)
{
  vector <T> tmp;
  T opV;
 ifstream in(filename.c_str());
 in.seekg(0, ios_base::end);// postavi pointer na pocetak file-a
 int sizeOfFile = in.tellg(); 
// pointer ide na kraj i vraca velicinu file-a

  in.seekg(0, ios_base::beg);// vrati pointer na pocetak
    if (!in) 
    {
    cerr << "\nNemogu da otvorim fajl: " << filename;
             return tmp;
    }
     if (sizeOfFile)// Ako file ima ikakvu velicinu tj. ako ima objekata
    {
// Ovdje ima problem:
// Ucitava jedan vise objekat u vector (zadnji objekat u nizu); 
// Kroz petlju prolazi jednaput vise  nego sto ima objekata u file-u

          while (in)
        {    in >> opV; 
             tmp.push_back(opV);
        }
             } 
            else // u suportnom je prazan
    {
         cout << "\nFajl je prazan\n";
    }
     in.close();
    return tmp;
}


Ovdje imam problem jer mi ucitava jedan vise objekat u vector i to zadnji ucitani. U cemu je stvar...

Hvala unaprijed.

/////