Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: C++ tallennus

Sivun loppuun

timok16 [17.01.2005 21:15:54]

#

Miksi tää koodi ei tallenna mitään?

void Asiakas::Valikko() //VALIKKO
{
	int valinta=0, ind=0;
	Asiakas *asiakkaat[5] = {NULL};
	fstream tiedosto;
	int lue=ios_base::in|ios_base::binary;
	tiedosto.clear();//virhebittien poisto
	tiedosto.open ("Asiakkaat.dat", lue);//Luetaan tiedosto taulukkoon
	if (tiedosto.is_open())
	{
		ind = 0;
		while (tiedosto.peek() != EOF && ind < 5)
		{
			asiakkaat[ind] = new Asiakas;
			asiakkaat[ind] -> Lataa(tiedosto);
			ind++;
		}
		tiedosto.close();
	}
	cout<<"Asiakas tiedostoa ei ole"<<endl;
	do
	{
		cout<<"--ASIAKKAAT--\n\n";
		cout<<"1) Lisaa\n";
		cout<<"2) Tulosta\n";
		cout<<"3) Poista\n";
		cout<<"0) Lopeta\n\n";
		cout<<"Valinta: ";
		cin>>ws>>valinta;
		if (valinta==1)
			asiakkaat[ind]->Lisaa();
		else if (valinta==2)
			asiakkaat[ind]->Tulosta();
		else if (valinta==3)
			asiakkaat[ind]->Poista();

	}
	while (valinta!=0);

	fstream tallenna("Asiakkaat.dat", ios_base::out|ios_base::app|ios_base::binary);//Tallennetaan lopetettaessa taulukon käyttö
	if (tallenna.is_open())
	{
		int ind = 0;
		while (ind < 5 && asiakkaat[ind] != NULL)
		{
			asiakkaat[ind]->Talleta(tallenna);
			ind++;
		}
		tallenna.close();
	}
	cout<<"Tallennus ei onnistunut\n";
	for (ind = 0; ind < 5 && asiakkaat[ind] != NULL; ind++)
		delete asiakkaat[ind];
}

Linkku [17.01.2005 21:19:59]

#

Voisi kuvitella että vika on Talleta()-funktiossa.

timok16 [17.01.2005 21:30:46]

#

void Asiakas::Talleta(fstream &tdsto)const
{
	tdsto.write((char *)nimi_, sizeof nimi_);
	tdsto.write((char *)&astunnus_, sizeof (int));
}

tässä Talleta funktio

void Lataa(fstream &);
void Talleta(fstream &)const;

ja tässä headeri

sqwiik [17.01.2005 21:48:27]

#

Oletko muistanut avata fstream-muuttujan tallenna, jota käytät tallentamiseen?

timok16 [17.01.2005 22:15:24]

#

sqwiik,
en oikein ymmärrä mitä tarkoitat tuolla
fstream-muuttujan avaamisella?
ehkä jo alkaa väsy painaan!!!

sqwiik [17.01.2005 23:19:29]

#

Eikun hups, kyllähän se tiedosto avataan. Koodista kysyttävää: miten Asiakas-luokan muuttujat nimi_ ja astunnus_ on esitelty?

void Asiakas::Talleta(fstream &tdsto)const{
  // Tallennat pointterin lukuarvon, et merkkijonoa.
  tdsto.write((char *)nimi_, sizeof nimi_);
  // Castaat (ilmeisesti) int-muuttujan char-pointteriksi?
  tdsto.write((char *)&astunnus_, sizeof (int));
  // Olisiko näin parempi?
  tdsto.write(nimi_, strlen(nimi_));
  tdsto.write(&astunnus_, sizeof (int));
}

timok16 [17.01.2005 23:26:12]

#

char nimi_[31];
int astunnus_;

tässä muuttujien esittely
tdsto.write(&astunnus_, sizeof (int)); //valittaa tästä rivistä ainakin
cannot convert parameter 1 from 'const int *' to 'const char *'

sqwiik [18.01.2005 09:24:53]

#

Ah, aivan... sen sijaan että käyttäisit pelkkää fstream.write():ia (jota siis käytetään vain TEKSTIN kirjoittamiseen), kirjoita ensin astunnus_ väliaikaiseen merkkijonoon ja kirjoita se:

char tmp[7]; /* int:n max-arvo vie 5-6 merkkiä. */
sprintf(tmp, "%i", astunnus_);
tdsto.write(tmp, strlen(tmp));

Tiedoston lukemisessa pitääkin sitten taas kikkailla...
Vinkkinä: sscanf()

timok16 [19.01.2005 11:41:53]

#

class Asiakas
{
private:
	static Asiakas *asiakkaat[3];
	int apu;
	int tunnus;


public:
	int Tunnus(int);
};

Asiakas Olio;

void Asiakas::Kysy()
{
	apu=100001;
	tunnus=Olio.Tunnus(apu);
}

int Asiakas::Tunnus(int apu)
{
	int ind=0;
	while (ind < 3 && asiakkaat[ind] != NULL)
	{
		if (asiakkaat[ind]->tunnus != apu)
		ind++;
		else
			apu++;
	}
	ind++;
	return apu;
}

Tarkoitus olisi, että ohjelma generoisi aina uuden asiakastunnuksen alkaen 100001, 100002, 100003... jne.
mutta tällä koodilla tulee aina sama tunnus jokaiselle asiakkaalle (100001)
Koodissani on myös muodostimia ja kopiointimuodostimia sekä
sijoitusoperaattoreita.
Pitäiskö olla jotenkin static määritelty toi tunnus muuttuja? Miksi ei mene tonne else lauseeseen kasvattamaan apu- muuttujaa?

timok16 [20.01.2005 11:23:54]

#

saisko apua mun c++ ongelmaan???

Linkku [20.01.2005 14:04:52]

#

Noh, tallennat nykyisen asiakastunnuksen tekstitiedostoon ja kun tarvitset uuden luet vanhan tunnuksen tiedostosta ja kasvatat sitä yhdellä ja tallennat tiedostoon.

Ei hirveän toimiva "oikeissa" ohjelmissa, jos tiedosto hajoaa tai poistataan...

timok16 [21.01.2005 16:33:48]

#

Asiakas *asiakkaat[3] = {NULL};
					char apu3[31];
					int ind=0;
					cout<<"minka nimen haluat muuttaa? "<<endl;
					cin>>ws;
					cin.getline(apu3, 30);
					while(ind < 3 && asiakkaat[ind]->nimi_ != apu3)
					ind++;
					if (asiakkaat[ind]->nimi_ == apu3) //etsitty löytyi
					{
							cout<<"Nimi: "<<asiakkaat[ind]->nimi_;
					}
					else
						cout<<"Nimea ei loytynyt";

Nyt tarvis saada apua siihen kun pitäis pystyä
muuttamaan dynaamisessa taulukossa olevaa tietoa, esim
asikkaan nimi ym. kaikki perustiedot.
tää koodi menee suoraan tohon että Nimeä ei löytynyt

sqwiik [21.01.2005 16:59:18]

#

Merkkijonojen vertaaminen ei onnistu == -vertailulla (se vertaa vain tällöin osoitteita). Käytä strcmp(char*,char*)-funktiota, palauttaa 0 jos merkkijonot ovat samat.

if( strcmp(asiakkaat[ind]->nimi_, apu3) == 0){
  cout<<"Nimi: "<<asiakkaat[ind]->nimi_;
}else ...

timok16 [21.01.2005 18:18:18]

#

Kiitti, mut kun laitoin sen noin niin ohjelman testauksessa
ohjelma kaatuu aina just tohon kohtaan!!!!

sqwiik [21.01.2005 18:22:29]

#

Koodissasi on räikeä virhe. Tuossa kohtaa.

while(ind < 3 && asiakkaat[ind]->nimi_ != apu3)
ind++;

Tämän koodirivikaksikon jälkeen ind:n arvo on aina 3. Ja kun sen jälkeen vertaat sitä, tapahtuu muistin ylivuoto (eli viittaat muistialueen ulkopuolelle).

Korjaa: laita kaikki while-silmukkaan kuuluva aaltosulkeisiin.

timok16 [21.01.2005 22:56:37]

#

Moi,
voi olla että on vieläkin räikeitä virheitä koodissani, mutta sitä vartenhan täällä on osaavia henkilöitä antamassa neuvoa meille "tumpeloille" elikkä
toi koodi kaatuu aina tohon kun yritän hakea muutettavaa nimeä!!!
kuinka yleensäkkin tapahtuu muistissa yksittäisen tiedon poisto tiedostosta ja kuinka se sit saadaan korvaamaan vanha tieto. Esim Nimi: Matti Mattila ---> muuta sukuni Pennaseksi --> Matti Pennanen
olen jo kokeilut kikkailua tiedostonkin kaa, mut tarkoitus olis toimia niin, että tiedot ladataan ohjelman käynnistäessä koneen muistiin ja sit sitä muistia vaan "räplätään"!!!
onko mahdollista ja kumpi teidän osaajien mielestä parempi vaihtoehto?

Metabolix [21.01.2005 23:13:07]

#

timok16 [27.01.2005 17:27:33]

#

Tiedosta kiinnostunut!
onko mahdollista käyttää useampaa tietuetta(struct) samassa
ohjelmassa ja kuinka se oikein tapahtuu?
Onko samanlainen rakenne kuin Luokillakin?
Tarkoitus olisi, että olisi vain yksi main() ja 3-4 tietuetta
samassa ohjelmassa.

Deewiant [27.01.2005 19:13:42]

#

turpo16 kirjoitti:

onko mahdollista käyttää useampaa tietuetta(struct) samassa ohjelmassa ja kuinka se oikein tapahtuu?

Määrittelet vain useampia structeja.

lainaus:

Onko samanlainen rakenne kuin Luokillakin?

Kyllä, C++:ssa erona on vain se, että classit sisältävät oletuksena privatea tietoa ja structit publicia.

timok16 [27.01.2005 19:36:15]

#

tuleeko jokaiselle tietueelle oma cpp tiedosto vai tuleeko kaikki samaan main() tiedostoon?
esim.
3 tietuetta Otsikkotiedostoina
1 main()--- valikot siihen
3 cpp tiedostoa
- asiakkaat.cpp------> asiakkaat.dat
- tilaukset.cpp------> tilaukset.dat
- tuotteet.cpp ------> tuotteet.dat
onnistuuko näin?

Deewiant [27.01.2005 20:53:02]

#

Siis, simppelit kolme tietuetta:

struct Asdf {
    int a, s, d, f;
};

struct Qwerty {
    char q, w, e, r, t, y;
};

struct FooBarBaz {
    bool foo, bar, baz;
};

int main(int argc, char ** argv)
{
    Asdf asdf;
    Qwerty qwerty;
    FooBarBaz foobarbaz;

    asdf.a        = asdf.s   = asdf.d    = asdf.f = 1234;
    qwerty.q      = qwerty.w = qwerty.e /* jne */ = '\r';
    foobarbaz.foo = foobarbaz.bar = foobarbaz.baz = true;

    return 0;
}

Metabolix [27.01.2005 21:28:46]

#

Tietueet saa tunkea ihan minne haluaa, kunhan vain määrittelee ne ennen kuin käyttää niitä muuttujamäärittelyissä. Samaan tiedostoon laittaisin, jos noista ei tule kovin isoja (satojen tai tuhansien koodirivien mittaisia).


Sivun alkuun

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta