Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: C++: tietovirta

Sivun loppuun

timok16 [10.11.2004 17:14:36]

#

tiedosto, jonka sisällä alla oleva teksti:

100006 lisa tilaus lisa tilaus 22300 Tilaus

haen yksittäisen rivin tiedot koodilla, mutta saan vain 31 merkkiä pitkän tulosteen näytölle, mihkä hävii loppuosa tekstistä?

koodini joka hakee kyseisen rivin menee näin:

fstream inputfile("asiakasrekisteri.txt",std::ios::in);
	if(inputfile.is_open())
	{
	int x, tunniste;
	string astun_;
	string nimi_;
	string lahios_;
	string postinro_;
	string postip_;
	string line;
	istringstream iss;
	cout<<endl <<"Anna asiakastunnus(6 merkkia): ";
	cin>>tunniste;
	cout<<endl;
	x=0;
	while(tunniste != x)
	{
	getline(inputfile, line);
	if(inputfile.eof())
	{
	cerr<<"Ei loytynyt!\n";
	return 1;
	}
	iss.str(line);
	iss>> x;
	}
	iss >>nimi_>>lahios_>>postinro_>>postip_;
	cout<<endl;
cout<<x<<" "<<nimi_<<" "<<lahios_<<" "<<postinro_<<" "<<postip_<<endl;
	}

jatkan vielä, kuinka saan kyseisen rivin poistettua tiedostosta jos niin haluan?

Metabolix [10.11.2004 17:38:29]

#

Käytä tänne kirjoittaessasi C:n kooditagia, jotta koodistasi saisi selvää. Ohjeet.

En osaa tuohon sen kummempaa sanoa, mutta kokeile vaikka lukea se rivi manuaalisesti. Ennen kuin kysyt, mitä se tarkoittaa: lue siis merkki kerrallaan kunnes vastaan tulee \r (0x0d) tai \n (0x0a). Yhden merkin saa luettua ifstream-olion get-funktiolla:

char c;
inputfile.get(c);

Kuten olen ennenkin täällä todennut, en tunne noita string-luokkia, mutta eikö tuossa ole virhe sikäli, että tuolla syötetiedostolla postinumeroksi tulisi tuo toinen "lisa", siis neljäs tekstinpätkä rivillä?

P.S. Mikä ihmeen c++ visual? Tarkoitatko Visual C++?

timok16 [10.11.2004 19:41:54]

#

iss >>a>>b>>c>>d>>e>>f>>g>>h>>k>>l>>n;
kiitti vihjeestä, mut ratkee näin kun laitan vaan tarpeeksi
monta muuttujaa peräkkäin, niin saan koko rivin näytölle.
ei näköjään merkitystä minkä nimisiä muuttujat ovat.
kunhan vaan ovat stringejä.
sit vielä kuinka saan poistettua ton tiedostosta???
kyllä tarkoitin Visual c++; (onko nyt oikein!)

Meitsi [10.11.2004 20:21:36]

#

Öh, etkai vaan laita niinku että jokaisessa muuttujassa on yksi merkki? Siis merkkijonon saa laittamalla char:in kooksi tekstin pituuden+1 (koska viimeinen merkki on nollabitti \0)

char merkkijono[101];

Tuo tekisi 100 merkkiä pitkän merkkijonomuuttujan.

timok16 [10.11.2004 20:37:54]

#

mut kun noin se alko pelaamaan, siis tossa koodissa yksi
merkki(string a) vastaa tiedostossa olevaa yhtä merkkijonoa
ja kun on tarpeeksi monta string muuttujaa niin kaikki merkkijonot, jotka ovat tiedostoon kirjoitettu tulostuu näytölle, siis se rivi mitä haetaan tunnusnumero mukaan.
en tiedä selventääkö tämä yhtään!!!
Mut kuinka mä saan poistettua ton rivin tiedostosta, eli
kun haen sen koneen muistiin ja näytölle, niin kuinka sen sit sais pois, jos haluun niin tehdä, tai vielä mukavampaa,
et muutan jotain tietoa siellä ja tallennan sit uudestaan.

Metabolix [11.11.2004 07:51:57]

#

Se >> pysähtyy jokaiseen whitespaceen.

Poisto onnistuu vaikka niin, että luet tiedot muistiin ja kirjoitat koko tiedoston uusiksi. Parempi tapa voi olla se, että nimeät tiedoston uudestaan ja kopioit siitä rivi kerrallaan tavaraa oikeannimiseen tiedostoon ja jätät haluamasi kohdan kopioimatta.

Kirjoitettavaan tiedostoon käytetään ofstream-oliota ifstreamin sijaan, ja avaustapa on usein ios::trunc.

timok16 [13.11.2004 17:56:16]

#

int poista;
  cout<<"\nMikä poistetaan?";
  cin.ignore(80,'\n');
  cin>>poista;
  fstream kohde;
  kohde.open(temp,ios::in | ios::out | ios::ate |ios::binary); //tempin avaus kirjoitusta varten
  lukukirjoitus.s:og(0);
  while (lukukirjoitus.read((char *) &ti, sizeof ti))
  {
     if (ti.id == poista)
     {
        cout << "\nTieto poistettu!";
        continue;
     }
     kohde.write((char *)&ti, sizeof ti );
  }
  kohde.close();
  lukukirjoitus.close();
  remove (tied);
  rename(temp, tied);

Moi. voisko joku kertoa, että mitä tarkoitetaan tässä koodissa kohdalla...lukukirjoitus.s:og(0)...
onko joku oma kirjasto joka pitää olla määritelty?

timok16 [14.11.2004 17:20:08]

#

#include<iostream>
using namespace std;
#include<fstream>
#include<string>
#include <stdio.h>

void Valikko();
void Lisaa();
void Poista();
void Nayta();
int Etsi(char kuka[31]);

int main()
{
	Valikko();
	return 0;
}

void Valikko()
{
	int valinta;
	do{
	cout<<"\n ----- Valikko ------ \n";
	cout<<"\n	1) Nayta\n";
	cout<<"\n	2) Poista\n";
	cout<<"\n	3) Lisaa\n";
	cout<<"\n	0) Lopetus"<<endl;
	cout<<"\n		Valinta: ";
	cin>>ws>>valinta;
	cout<<endl;
	if (valinta==1)
		Nayta();
	if(valinta==2)
		Poista();
	if(valinta==3)
		Lisaa();
	}
	while (valinta!=0);
}

void Lisaa()
{
	//TIEDOSTOON KIRJOITUS
	//char nimi[31];
	int astun;
	cout<<"Annan asiakastunnus(6 numeroa): ";
	cin>>ws;
	//cin.getline(astun, 6);
	cin>>astun;
	int kirjoita=ios_base::out|ios_base::app|ios_base::binary;//asiakkaat tiedoston avauslippujen maaritykset
int lue=ios_base::in|ios_base::binary;
fstream tiedosto;
tiedosto.clear();//virhebittien poisto
tiedosto.open("harj.dat", kirjoita); //asiakkaat tiedoston avaus kirjoitusta varten
	if (!tiedosto.good())
	{
		cout<<"Tiedoston avauksessa virhe."<<endl;
	}
	else
	{
		tiedosto.write((char*) &astun, sizeof (int));//tarkistetaan kirjoitettavan tiedon pituus, kirjoitetaan
		cout<<"Tiedostoon kirjoitettu "<<astun<<endl<<endl;
	}
	tiedosto.close();
}

void Nayta()
{
	//TIEDOSTOSTA LUKU
	int astun;
	fstream tiedosto;
	int lue=ios_base::in|ios_base::binary;
	tiedosto.clear();//virhebittien poisto
	tiedosto.open("harj.dat", lue); //asiakkaat tiedoston avaus lukemista varten
	if (!tiedosto.good())
	{
		cout<<"Tiedoston avauksessa virhe"<<endl;
	}
	else
	{
		cout<<"Tiedoston sisalto:\n\n";
		while (tiedosto.peek() !=EOF)//luetaan tiedostoa merkki kerrallaan lopetusmerkkiin asti
		{
			tiedosto.read((char*)&astun, sizeof (int));
			cout<<astun<<endl;
		}
		tiedosto.close();
	}
}

void Poista()
{
	//TIEDOSTOSTA POISTO
	int paluuarvo=0;
	int astun;
	char vertaus[80], nimi[31];
	cout<<"\nMinka nimen haluat poistaa? ";
	cin>>ws;
	cin.getline(vertaus, 80);
	paluuarvo=Etsi(vertaus);
	if (paluuarvo==0)
	{
	fstream tiedosto;
	fstream temppi;
	int lue=ios_base::in|ios_base::binary;
	int kirjoita=ios_base::out|ios_base::app|ios_base::binary;//asiakkaat tiedoston avauslippujen maaritykset
	tiedosto.clear();//virhebittien poisto
	tiedosto.open("harj.dat", lue); //asiakkaat tiedoston avaus lukemista varten
	if (!tiedosto.good())
	{
		cout<<"Tiedoston avauksessa virhe"<<endl;
	}
	else
	{
		temppi.open("temp.dat", kirjoita);
		if (!temppi.good())
		{
			cout<<"Tiedoston avauksessa virhe"<<endl;
		}
		else
		{
			tiedosto.seekg(0);
			while (tiedosto.peek() !=EOF)
			{
				while (tiedosto.read((char*)&vertaus, sizeof (int)))
				{
					if ((strcmp(astun, vertaus))==0)
					{
						cout<<"Poistetaan "<<astun<<endl;
						continue;
					}
					else
					{
						temppi.write((char*)&vertaus, sizeof (int));
					}
				}
			}
			tiedosto.close();
			temppi.close();
			remove ("harj.dat");
		}
	}
	rename("temp.dat", "harj.dat");
	}
	else
		cout<<"Henkiloa "<<vertaus<<" ei loytynyt."<<endl;
}

int Etsi(char kuka[31])
{
	//TIEDOSTOSTA LUKU
	char nimi[31];
	int astun;
	fstream tiedosto;
	int lue=ios_base::in|ios_base::binary;
	tiedosto.clear();//virhebittien poisto
	tiedosto.open("harj.dat", lue); //asiakkaat tiedoston avaus lukemista varten
	if (!tiedosto.good())
	{
	cout<<"Tiedoston avauksessa virhe"<<endl;
        }
       else
       {
tiedosto.seekg(0);
while (tiedosto.peek() !=EOF)//luetaan tiedostoa merkki kerrallaan lopetusmerkkiin asti
	{
	while (tiedosto.read((char*)&astun, sizeof (int)))
	{
	while ((strcmp(astun, kuka))==0)
	{
	if ((strcmp(astun, kuka))==0)
	{
							return 0;
	}
	else
        {
							return 1;
	}
    }
}
	return 1;
        }
	tiedosto.close();
	}
}

ohjelmani valittaa näistä lauseista
while ((strcmp(astun, kuka))==0), millä korvaan strcmp:n
kun haluan antaa sille int tyypin arvon.
toimii hyvin kun käytän char-tyyppiä

Metabolix [14.11.2004 17:27:54]

#

Poista nyt hyvä ihminen tuo koodi tuosta, ei sitä kukaan tarvitse. Riittää, että laitat sen pätkän, jossa ongelma on, tuossa tapauksessa enintään viimeinen funktio, pelkkä strcmp-kohta ja selostus muuttujien tyypeistä riittäisi hyvin.

Mikä ihmeen järki on lukea int-muuttujaan kuin se olisi char-osoitin? Noh, jos on aivan pakko, niin mietipä, miten saisit sen muutettua char* -muotoon, toimisiko siis samalla tavalla kuin ennenkin?
strcmp((char *)&astun, kuka)

Etkö tiedä, että taulukko on osoitin, eli "char *kuka" on funktion kannalta sama asia kuin "char kuka[31]"? No nyt tiedät (ehkä).

sitä paitsi, vaikka kuinka lukisit tiedostosta int-muuttujaan tuolla tavalla, niin jos tiedostossa lukee 1234, int-muuttujan arvoksi ei todellakaan tule 1234 vaan noita ASCII-merkkejä vastaava kokonaisluku, 0x31323334 = 825373492.

timok16 [21.11.2004 15:41:40]

#

void Asiakas::Kysy()
{
	int apu=100001;
	cout<<"\nSYOTA HENKILON TIEDOT\n";
	cout<<"\nNimi: ";
	cin>>ws;
	cin.get(nimi_, 31).get();
	astunnus_=Olio.Tunnus(apu);

	cout<<"Osoite: ";
	cin.get(osoite_, 21);
	cout<<"Postinumero: ";
	cin>>ws>>postinro_;
	cout<<"Postitoimipaikka: ";
	cin>>ws>>postito_;
}
int Asiakas::Tunnus(int apu)
{
	int ind=0;
	int ind2=0;
	while (ind < 3 && asiakkaat[ind] != NULL)
	{
		if (asiakkaat[ind2]->astunnus_ != apu)
		ind2++;
		else
			apu++;
	}
	ind++;
	return apu;
}

tarkoitus olisi, että ohjelma antaa aina uuden tunnusnumeron, kun lisätään asiakas. alkuarvo 100001, ja sen jälkeen 100002, 100003 jne.
mutta nyt joka kerta tulee 100001.

Masfonos [21.11.2004 18:20:42]

#

Öh, määrittelet apu = 100001 ja sitten lisäät tunnuksen:

...
apu = 100001;
...
...
astunnus_ = Olio.Tunnus(apu);

Aivan varmasti tulee tunnus 100001 joka ikinen kerta kun sen sinne annat arvonakin.

timok16 [23.11.2004 19:40:10]

#

Öh, ihan kiva mut saisko vielä vihiä miten mun kannattaa se
tehdä niin, että saisin generoitua numerojärjestyksessä asiakastunnukset.

Metabolix [23.11.2004 19:51:35]

#

Jos vaikka laittaisit globaalin muuttujan, jossa pitäisit seuraavaa vapaata numeroa? Sitten voisit korottaa yhdellä ja ottaa luvun aina, kun tarvitset uuden.

tn [23.11.2004 20:22:21]

#

Metabolix kirjoitti:

Jos vaikka laittaisit globaalin muuttujan, jossa pitäisit seuraavaa vapaata numeroa? Sitten voisit korottaa yhdellä ja ottaa luvun aina, kun tarvitset uuden.

Ehkäpä kuitenkin kannattaisi käyttää staattista kenttää/muuttujaa Asiakas-luokassa tuon globaalin sijasta.

Metabolix [23.11.2004 21:29:11]

#

Ajattelin, että Asiakkaan funktio asettaisi arvoksi suoraan sen, mitä parametsiksi annettiin. Konstit on monet, mutta vähän peruskekseliäisyyttä voisi odottaa aloittelijaltakin.

Itse laittaisin koko homman niin, että kaikki Asiakkaat olisivat jonkinlaisena listana / puuna AsiakasLista-luokan sisällä, jolloin uusia asiakkaita voisi luoda jossakin tämän AsiakasListan funktiossa. En kuitenkaan tiedä koko projektin ideaa, joten...


Sivun alkuun

Vastaus

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

Tietoa sivustosta