moikka,
Kuinka voidaan tietueiden funktioiden kanssa keskustella?
Tarkoitan sitä että pitäisi pystyä käyttämään Asiakas-tietueessa Tilaus-tietueen funktiota TilausValikko().
Kiukkuu mulle tälläistä virhettä kokoajan:
unresolved external symbol "public: void __thiscall TILAUS::TilausValikko(void)" (?TilausValikko@TILAUS@@QAEXXZ)
Tarkoitus päästä asikakkaan poiston jälkeen poistamaan myös tilaus.
ohjelmani rakenne:
main()--->päävalikko
Asiakas--->tietue--->asiakas.cpp
Tilaus--->tietue--->tilaus.cpp
eli jos ymmärrätte, niin viite-eheys olis tässä tarkoituksena.
struct ASIAKAS {----->tämä ihan omana headerinä char address[21]; char postcode[6]; char city[21]; char asnimi[31]; char astunnus[7]; }; #include <iostream> using namespace std; #include <stdio.h> #include <string.h> #include <stdlib.h> #include <fstream> #include "TILAUS.H" #include "ASIAKAS.H" TILAUS tietue;// /*tässä tehty TILAUS-tyyppinen tietue-muuttuja*/ struct ASIAKAS asiakas; FILE *fileptr; /****tässä paljon muitakin funktioita********/ void delete_asnimi() { strcpy(asiakas.astunnus, " " ); fwrite(&asiakas, sizeof(asiakas), 1, fileptr); //tietue.TilausValikko(); /***********kuinka saadaan toisen tietueen funktiot käyttöön***********/ /*tarkoitus päästä Tilaus-tietueen TilausValikko()-funktioon ja sieltä valikosta valita PoistaTilaus()-funktio.*/ }
turpo16 kirjoitti:
Kuinka voidaan tietueiden funktioiden kanssa keskustella?
Tarkoitan sitä että pitäisi pystyä käyttämään Asiakas-tietueessa Tilaus-tietueen funktiota
Tietueille ei voi tehdä omia siäisiä funktioita, mutta luokille voi.
funktiomäärittely
Tilaus::TilausValikko(void)
kertoo, että TilausValikko() funktio kuuluu luokalle nimeltä Tilaus. Tällaisia funktiomäärittelyjä et voi tehdä structeille. Kyseisen luokan Toteutus voisi olla seuraavan lainen.
class Tilaus { public: void TilausValikko(void); //määritellään julkinen metodi }; Tilaus::TilausValikko(void) { //...funktion toteutus }
Kannatan tutustumista luokkiin ja c/c++ kielen perustietorakenteisiin. Esimerkiksi jonkin oppaan avustuksella, joita varmasti netistä löytyy riittämiin.
C++:ssa tietueeseen voidaan kirjoittaa alkioiden attribuuttien lisäksi jäsenfunktioita.
struct cPiste { int x,y; void tulosta() const; }; void cPiste::tulosta() const { printf("(%d,%d)\n",x,y); }
Structeihin voi laittaa funktioita yms, mutta ne näkyvät muille public-tyyppisiä. Private/Protected on luokkien ominaisuuksia.
void delete_asnimi() { strcpy(asiakas.astunnus, " " ); fwrite(&asiakas, sizeof(asiakas), 1, fileptr); tietue.TilausValikko(); //ei noteeraa koko lausetta cout<<"meneeko tanne "<<endl;//tää kyllä tulostuu } int get_choice() { int c=0; printf("\n\n ------ MENU ------ \n\n"); printf("Valitse ja paina Enter\n\n"); printf(" 1. Lisaa asiakas\n"); printf(" 2. Etsi asiakas\n"); printf(" 3. Nayta kaikki asiakkaat \n"); printf(" 4. Paivita asiakkaan tietoja\n"); printf(" 5. Poista asiakas\n"); printf(" 0. Lopeta\n\n"); printf(" Valinta > "); scanf(" %d", &c); return c; } [c/koodi] /*ekana ollaan ASIAKAS-tietueessa ja sieltä kun poistetaan asiakas, pitäisi päästä TILAUS-tietueen TilausValikko()-metodiin, jonka kautta voidaan taas poistaa kyseisen asiakkaan tilaus.*/ /*ajatuksena tehdä niinkuin c++:ssa onnistuu eli koostaminen*/ /*main():sta onnistuu pomppiminen mitenpäin vain, mulla main()-funktiossa vain päävalikko*/
Vaihda homma kokonaan C-kieleen, paljon helpompi ymmärtää koodia.
Esimerkiksi:
#include <stdio.h> #include <stdlib.h> #include <string.h> // #include "allegro.h" /* Älä välitä tästä jos et käytä Allegroa */ typedef struct tietue { char nimi[25]; int arvo; } TIETUE; typedef struct tietue2 { char nimi[25]; int arvo; struct tietue2 *seur; } listaTIETUE; void luo(void); listaTIETUE *poista(char *, listaTIETUE*); void poistaminen(void); void listaakaikki(void); void luo(void) { TIETUE persoona; FILE *tiedosto; char jatko[8]; tiedosto = fopen("data", "ab"); if(tiedosto==NULL) { clrscr(); printf("\nAvaus ei onnistunut!\n"); getch(); clrscr(); exit(1); } do { clrscr(); printf("Anna nimi: "); fgets(persoona.nimi, 24, stdin); persoona.nimi[strlen(persoona.nimi)-1]='\0'; printf("Anna arvo: "); scanf("%d%*c", &persoona.arvo); fwrite(&persoona, sizeof(persoona), 1, tiedosto); printf("Jatketaanko? (k/e): "); scanf("%s%*c", jatko); } while (jatko[0]=='k' || jatko[0]=='K'); fclose(tiedosto); } int main(void) { listaTIETUE *henkilo, *eka = NULL; int mode; // allegro_init(); // install_keyboard(); // fade_out(3); // set_gfx_mode(GFX_AUTODETECT, 320, 200, 0, 0); // fade_in(default_palette, 3); // textout_centre(screen, font, "This program is protected...", SCREEN_W / 2, (SCREEN_H - 8) / 2, makecol(255, 0, 0)); // readkey(); // fade_out(3); // clear_bitmap(screen); // fade_in(default_palette, 3); // allegro_exit(); do { clrscr(); printf("Tämä on testi...\n\n"); printf("1 Lisää tietue...\n"); printf("2 Poista tietue...\n"); printf("3 Näytä tietueet...\n"); printf("0 Lopeta...\n\n"); printf("Valitse toiminto? "); scanf("%d%*c", &mode); switch (mode) { case 1: luo(); break; case 2: poistaminen(); break; case 3: listaakaikki(); break; case 0: clrscr(); exit(0); break; default: ; } } while (mode != 0) ; while (henkilo!=NULL) { eka = henkilo->seur; free(henkilo); henkilo = eka; } return 0; } listaTIETUE *poista(char *nimi, listaTIETUE *eka) { listaTIETUE *henkilo, *edellinen; int eri,loysi=0; henkilo = eka; edellinen = NULL; while (henkilo!=NULL) { eri = strcmp(henkilo->nimi, nimi); if (!eri) { if (!edellinen) { clrscr(); printf("Poistetaan listalta nimi \"%s\"\n", nimi); eka = henkilo->seur; free(henkilo); henkilo = eka; loysi=1; getch(); } else { clrscr(); printf("Poistetaan listalta nimi %s\n", nimi); edellinen->seur = henkilo->seur; free(henkilo); henkilo = edellinen->seur; loysi=1; getch(); } clrscr(); printf("OK\n"); getch(); } else { edellinen = henkilo; henkilo = henkilo->seur; } } if (loysi==0) { clrscr(); printf("Poistettavaa: \"%s\" ei löytynyt\n", nimi); getch(); } return eka; } void poistaminen(void) { TIETUE persoona; listaTIETUE *henkilo, *eka = NULL; FILE *tiedosto; size_t maara; char nimi[35]; tiedosto = fopen("data", "rb"); maara = fread(&persoona, sizeof(persoona), 1, tiedosto); if (maara != 0) { while (maara == 1) { henkilo = (listaTIETUE*)malloc(sizeof(listaTIETUE)); strcpy(henkilo->nimi, persoona.nimi); henkilo->arvo = persoona.arvo; if (eka == NULL) { eka = henkilo; henkilo->seur = NULL; } else { henkilo->seur = eka; eka = henkilo; } maara = fread(&persoona, sizeof(persoona), 1, tiedosto); } clrscr(); printf("\nMinkä niminen nimi poistetaan? "); fgets(nimi, 34, stdin); nimi[strlen(nimi) - 1] = '\0'; eka = poista(nimi, eka); henkilo = eka; tiedosto = fopen("data", "wb"); while (henkilo != NULL) { strcpy(persoona.nimi, henkilo->nimi); persoona.arvo = henkilo->arvo; fwrite(&persoona, sizeof(persoona), 1, tiedosto); henkilo = henkilo->seur; } } fclose(tiedosto); } void listaakaikki(void) { TIETUE persoona; listaTIETUE *henkilo, *eka=NULL; FILE *tiedosto; size_t maara; tiedosto = fopen("data", "rb"); if (tiedosto == NULL) { clrscr(); printf("Tiedostoa ei loytynyt.\n"); getch(); } else { clrscr(); printf("\nKaikki tiedostossa olevat tietueet:\n\n"); maara=fread(&persoona, sizeof(persoona), 1, tiedosto); if (maara != 0) { while(maara==1) { henkilo=(listaTIETUE*)malloc(sizeof(listaTIETUE)); strcpy(henkilo->nimi, persoona.nimi); henkilo->arvo = persoona.arvo; if (eka==NULL) { eka = henkilo; henkilo->seur = NULL; } else { henkilo->seur = eka; eka = henkilo; } maara=fread(&persoona, sizeof(persoona), 1, tiedosto); } while (henkilo!=NULL) { printf("Nimi: %-16s Arvo: %-7d\n", henkilo->nimi, henkilo->arvo); henkilo = henkilo->seur; } getch(); } } }
Kannattaa vilkaista binääriä: http://www.freewebs.com/dungeon86/ohjelmat/struct.exe
kiitos kovasti tästä koodista ja avustasi. siis en tee tästä
copy paste versiota, eli yritän vielä räpeltää tota aikaisempaa tekelettäni, ja olisin kovasti kiitollinen jos saisin siihen ongelmaani avustusta Teiltä, jotka osaavat koodia jo paremmin. Jos sinua kiinnostaa olla henk. kohtainen
avustajani? mahdollisuus mukavaan "rivien mukaan" saatavaan korvaukseen.
ps. kun tulee jumi jossain kohtaa koodia, niin jotenkin sitä vaan pyörittelee sitä jumia ja eikä pääse millään ratkaisuun.
Enpä jaksa tuohon dungeon86:n koodiin perehtyä, mutta suhteellisen sotkuiselta näyttää, ei millään pahalla. Jos tuo olisi siistimmin kirjoitettu ja edes jossakin määrin kommentoitu, tuon kahlaisi läpi alle minuutissa ja siitä voisi asiaa osaamatonkin helpommin oppia.
Minusta on aivan turha väittää, että C olisi jotenkin selkeämpi kuin C++. Jos ohjelma on C:tä, se kääntyy ihan hyvin myös C++:na, joten on täysin ohjelmoijasta kiinni, miten selkeää koodi on. Sitä paitsi C++:n luokat ovat usein huomattavan helppo tie tehdä asioita, jotka C:llä vaatisivat paljon enemmän tilaa.
Ja ei millään pahalla, dungeon86, mutta en menisi sinuna (ilmeisesti puolisen vuotta C:llä koodanneena) sanomaan, mikä kieli / ohjelmointitapa / tms on hyvä / huono. Eri ihmiset hallitsevat eri asioita hyvin, joten jos sinusta jokin on sekavaa / vaikeaa, se voi monen muun mielestä olla aivan helppoa ja selkeää, tai päinvastoin.
moi,
entäpä toi minun apuni, jota tässä olen pyydellyt jo jonkun aikaa, siis noi yllä mainitut koodin pätkät ja kysymykset
"ala turpo16" . Olisko joku niin ystävällinen ja perehtyisi näihin minun ongelmiini?
Esim. "turpo16 [04.02.2005 13:09:53" kohdan kysymyksiin olis kiva saada asiantuntevilta vastauksia.
No paha tuohon on tuolta pohjalta sanoa mitään. Mistä tiedät, ettei ohjelma mene siihen funktioon? Laitapa sen toisen funktion alkuun joku cout << "Toinen funktio";
jos et ole vielä niin tehnyt. Jollakin tavalla väärin kuitenkin sitä funktiota ilmeisesti käytät.
Minulla ainakin tämän koodin tulostus on "10, 11
", eli toimintaperiaate funktioiden kanssa on tämä (sama, jonka rutkis jo esittikin:
#include <iostream> using std::cout; // Struktuurin määrittely struct TTyyppi_A { int A, B; void Aseta(); void Printtaa(); }; // Toinen struktuuri, joka sisältää ensimmäisen struct TTyyppi_B { TTyyppi_A Jasen; void Aseta(); void Printtaa(); }; // Funktio, joka asettaa A:ksi 10 ja B:ksi 11. void TTyyppi_A::Aseta() { this->A = 10; this->B = 11; } // Funktio, joka tulostaa luvut "A, B" void TTyyppi_A::Printtaa() { cout << A << ", " << B; } // Nämä kutsuvat jäsenenä olevan A-tyypin vastaavia funktioita void TTyyppi_B::Aseta() { Jasen.Aseta(); } void TTyyppi_B::Printtaa() { Jasen.Printtaa(); } int main() { TTyyppi_B L; L.Aseta(); L.Printtaa(); return 0; }
kiitos kaunis sinulle. Nyt sain homman pelaamaan. Tätä olen jo pari päivää pyöritellyt, eli todella kaunis kiitos sinulle: ). Olet aina ollut asiallinen ja todella ammattitaitoista apua antava "putkan" käyttäjä.
Homma ratkes siihen kun laitoin kaikki structit samaan headeriin ja näköjään järjestykselläkin on väliä kuinka ne on asetettu sinne.
Tuo järjestys on tosiaan tietyssä määrin merkityksellinen. Jos eri structien funktiot käyttävät kaikki toisiaan, hommasta selviää näin:
// Kerrotaan, että on olemassa struct-tyypit A_struct ja B_struct struct A_struct; struct B_struct; // Määritellään sisällöt struct A_struct { // Tämän voi määritellä, koska ylempänä on kerrottu, että B_struct on olemassa B_struct B_tyyppinen_struct; void JokuFunktio(); }; struct B_struct { A_struct *A_struct_pointer; void JokuFunktio(); }; // Funktiot void A_struct::JokuFunktio() { // Tätä voi kutsua, koska B_structin määrittely on ylempänä. B_tyyppinen_struct.Jokufunktio(); } void B_struct::JokuFunktio() { cout << "void B_struct::JokuFunktio() kutsuttu.\n"; }
Ei ole mierkitystä, missä tiedostossa mikäkin palanen on, jokaisen rivin tai vaikka jokaisen sanan voi halutessaan laittaa vaikka omaan tiedostoonsa, kunhan ne menevät oikeaan järjestykseen includeissa. Esikääntäjä vain kokoaa sen kaiken enemmän tai vähemmän samaan kasaan, eli #include <tiedosto>
liittää kyseisen tiedoston siihen kohti koodia.
/* kuinka saisin ton num-muuttujan sijoitettua asiakas.astunnus-kenttään, niin, että se myös näkyy listauksessa?*/ char astun[7]; long asnro; long numero; ifstream inputfile("tunnus1.txt"); // tarkistetaan onko tiedosto olemassa if ( !inputfile ) { cout << "Tiedoston tunnus1.txt avaus ei onnistunut" << endl; } else { char nro[7]; while ( inputfile.getline(asiakas.astunnus,7)) { cout<<"Asiakastunnus on. "<<asiakas.astunnus<<endl;//nyt merkkijono numero = atol(asiakas.astunnus); cout<<"Asikastunnus on: "<<numero<<endl;//nyt long-tyyppinen numero=numero + 1; cout<<"Asikastunnus on: "<<numero<<endl;//nyt kasvatettu yhdella itoa(numero,asiakas.astunnus,10); cout<<"Asikastunnus on: "<<asiakas.astunnus<<endl;//nyt taas merkkijonona //kuinka saan nro-muuttujan tiedot tietueen asiakas.astunnus-kenttään } } inputfile.close(); ofstream numba ("tunnus1.txt"); if (numba.is_open()) { numba << asiakas.astunnus<<endl; cout<<"astunnus nyt: "<<asiakas.astunnus<<endl; numba.close(); }
Jaa, minkähän num-muuttujan? Jos kysymys oli kuitenkin tuosta nro-muuttujasta, voit kopioida tiedot vaikka memory.h:sta löytyvällä memcpy-funktiolla: memcpy(asiakas.astunnus, nro, 7);
, jossa 7 on kopioitavien tavujen määrä. Ihmettelen kuitenkin, miksi tuon muuttujan haluaisit kopioida, kun et ole edes laittanut siihen mitään.
P.S. Koodin voisi sisentää selvemminkin :)
memory.h ei ole standardia; mieluummin string.h.
joo, kiiti taas kovasti. olin jo illalla hiukka väsy, eli annoin vähän hätäisesti ton koodin pätkän näytille. mutta sain taas apua, käyttäen tota mencpy-funktiota pääsin haluttuun tulokseen.
long astun; long asnro; char apunro[7]; ifstream inputfile("tunnus1.txt"); // tarkistetaan onko tiedosto olemassa if ( !inputfile ) { cout << "Tiedoston tunnus1.txt avaus ei onnistunut" << endl; } else { char nro[80]; while ( inputfile.getline(nro,80)) { astun = atof(nro); asnro=astun; if(asnro==astun) asnro = asnro+1; cout <<"asiakastunnus: "<< asnro << endl; } } inputfile.close(); ofstream numero ("tunnus1.txt"); if (numero.is_open()) { numero << asnro<<endl; numero.close(); } itoa(asnro,apunro,10); memcpy(asiakas.astunnus, apunro,7);
Aihe on jo aika vanha, joten et voi enää vastata siihen.