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?
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++?
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!)
Ö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.
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.
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.
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?
#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ä
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.
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.
Ö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.
Öh, ihan kiva mut saisko vielä vihiä miten mun kannattaa se
tehdä niin, että saisin generoitua numerojärjestyksessä asiakastunnukset.
Jos vaikka laittaisit globaalin muuttujan, jossa pitäisit seuraavaa vapaata numeroa? Sitten voisit korottaa yhdellä ja ottaa luvun aina, kun tarvitset uuden.
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.
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...
Aihe on jo aika vanha, joten et voi enää vastata siihen.