Juu elikkäs, mite tulisi tehdä oma funktio parseri? Eli parseri joka ottaisi talteen funktion argumenteille syötetyn datan. Eli jos käyttäjä antaa komennon char *komento = "tiedot('kansio','a')" niin parseri katsoo eka että mikä funktio on kyseesttä eli "tiedot" jos "tiedot" funktio löytyy niin katsotaan mitä dataa sen argumennteihin on laitettu. Jos taas "tiedot" funktiota ei löydy, niin tuloestetaan vaikka "Komentoa ei ole olemassa" tai jos funktio on mutta argumentit on väärin niin "Virheelinen argumentti".
Edit1: Nytten pitäisi saada tehtyä oma eli sscanf kokeilin, mutta se ei bugaa vähän tässä, eli oma pitäisi tehdä.
Vai että ollaan omaa ohjelmointi-/skirptikieltä teossa. Valitettavasti asia ei ole aivan noin suorapiirteinen. Jaa rivi osiin (tokeneihin) jonka jälkeen ala tarkistamaan riviä osa kerrallaan. Näiden osien perusteella sitten tarkistat, onko rivi laillinen. Jos noin kunnianhimoista projektia alkaa tekemään, ei näin helppoja asioita pitäisi kysyä. Tämä kun on helpoimmasta päästä. ;)
En ole suoranaisesti omaa kieltä tekemässä. Pitäisi saada tehtyä pieni kielitulkki vain. Eli kyseessä on vain parista funktiosta. Itse yritin tehdä tuota flex:in avulla, mutta päädyin sitten "oma" ohjelmoimaan. Pitää vielä kai sitte yrittää koodata tuota parseria.
Ovatko komennot aina muotoa "nimi(a,b,c)", jossa "nimi" on komennon nimi ja "a", "b" ja "c" ovat parametreja (niitä voi tietysti olla eri määrä). Tällaisten komentojen tunnistukseen ei tarvita kovin monimutkaista järjestelmää.
Ensimmäinen vaihe voisi olla selvittää komennon nimi. Tämä onnistuu tutkimalla merkkejä alusta alkaen, kunnes tulee vastaan aloitussulku. Tätä ennen tuleva osuus on komennon nimi. Jos vielä viimeinen merkki on lopetussulku, komento on muuten kunnossa, mutta pitää vielä tutkia parametrit.
Myös parametrit saa selville käymällä merkkejä läpi yksi kerrallaan. Jos vastaan tulee pilkku tai lopetussulku, parametrit on käyty läpi. Hieman vaikeampi tilanne on, jos parametrien sisällä voi olla pilkkuja tai sulkuja. Tällöin täytyy pitää kirjaa heittomerkeistä (onko merkkijono kesken).
Tarvittava koodi voi olla aika pitkä, mutta se muodostuu yksinkertaisista osista. Eli jos mietit järkevästi, miten tuollaisen komennon pystyy tunnistamaan merkkejä tutkimalla, homman pitäisi onnistua.
joo o, mite saan char d[1] siirettyä esim char* a:lle? Eli jos d = "(g)" niin sitten g sijainti on merkki jonossa [1]. Eli eikös se saada niin et siiretään d[1] a:lle. Sitten a = "g", mutta tämä ei onnistu char* a = d[1]. Miten tämä tulisi tehdä oikein?
Jos muuttuja a on pelkkä yksi merkki, määrittele se "char a". Sitten aikanaan voit kirjoittaa "a = d[1]", jolloin merkkijonon d kohdassa 1 oleva merkki (eli merkkijonon toinen merkki) kopioituu muuttujaan a. Siis yksi char-muuttuja on yksi merkki, ja kun tällaisia on useampia peräkkäin, muodostuu merkkijono.
Vielä yksi juttu. Miten saan lisättyä char muuttujaan aina tekstiä? Itse koitin
sprintf (tuloskomento,tuloskomento+"%s",vkomento[i]);
Funktiolla strcat voi lisätä merkkijonon toisen perään. Sama onnistuu myös funktiolla sprintf vähän pidemmin.
strcat(tuloskomento, vkomento); sprintf(tuloskomento, "%s%s", tuloskomento, vkomento);
Muista huolehtia, että merkkijonoissa on tarpeeksi tilaa.
Nää charrit taitaa olla liitoutuneita jotenki muo vastaan, ei oikein tahdo toimia.
char *vkomento; vkomento = "k(a)"; char tuloskomento[1000]; int i = 0; while(i < strpituus(vkomento)){ if(vkomento[i] != "("){ sprintf(tuloskomento, "%s%s", tuloskomento, vkomento[i]); } i++; } cout << tuloskomento;
Antti, sprintf-funktion toiminta ei taida olla määritelty, jos sillä yrittää kirjoittaa tekstin itseensä. Pitäisi mieluummin etsiä tekstin loppukohta ja jatkaa siitä:
sprintf(&teksti[strlen(teksti)], "%s", jatkoteksti);
kayttaja-3842, suosittelen tutustumista osoittimiin, merkkijonoihin ja (s)printf-funktioon jonkin oppaan kanssa. %s tarkoittaa tekstiä (char*), yksi merkki olisi vain %c. (Ja mikä on tuo strpituus, eikö valmis funktio strlen sopisi?)
Heittomerkkien sisällä on merkki, lainausmerkkien sisällä on merkkijono. Eli 'a' ja "a" ovat kaksi eri asiaa. Merkkijonon lopussa on aina nollamerkki, jolloin "a" muodostuu merkeistä 'a' ja '\0'. Merkkejä voi vertailla C:n tavallisin keinoin (==
, !=
jne.), mutta merkkijonoja täytyy vertailla merkki kerrallaan (esim. funktiolla strcmp). Ehkä helpointa on ajatella, että merkki on yksi muuttuja ja merkkijono on taulukko (niin kuin asia onkin).
Metabolix: Hyvä huomautus, ei kannata ottaa mallia edellisestä viestistäni. Tässä tapauksessa tuo tekeleeni ehkä toimii, jos hyvin käy, mutta jos kaksi viimeistä parametria vaikka vaihtaa toisinpäin, niin voi tapahtua kummia.
Jos teet C:llä tälläisten merkkijonojen kanssa puljaaminen on ymmärrettävää, mutta jos teet C++:lla, en ymmärrä miksi pitää lyödä päätä kiveen. Siinä tapauksessa tutustu std::string-luokkaan. Niiden käsittely on paljon turvallisempaa, helpompaa ja aloittelijalle loogisempaa.. ;)
Mutta jos teet C:llä niin tämä posti on hyödytön.
Tein tälläseen nopeen testin, mutta ei oikein tahdo toimia toi ehto tuolla
if(tuloskomento == "print"){ cout << "Loyty"; }else{ cout << "Ei loytynyt"; }
vaikka tuloskomento = "print"
#include <iostream> #include <string.h> using namespace std; int strpituus(char * teksti) { int a,aika = 0; while(teksti[a] != '\0') { a++; aika++; } return aika; } char * TULKKI_parseri(char* komento){ /* Paresri */ char *vkomento; vkomento = komento; char tuloskomento[1000]; char tulosargumentit[1000]; string scan; string scan2; int i = 0; bool funktio_tunnistus = false; while(i < strpituus(vkomento)){ scan = vkomento[i]; if(scan != "("){ sprintf(&tuloskomento[i], "%c",vkomento[i]); }else{ funktio_tunnistus = true; int a_ja = i+1; int alku = 0; i = strpituus(vkomento)+1; while(a_ja < strpituus(vkomento)){ scan2 = vkomento[a_ja]; if(scan2 != ")"){ sprintf(&tulosargumentit[alku], "%c",vkomento[a_ja]); }else{ a_ja = strpituus(vkomento)+1; } alku++; a_ja++; } } i++; } /* Parseri loppuu */ if(tuloskomento == "print"){ cout << "Loyty"; }else{ cout << "Ei loytynyt"; } }
Käyttö
#include <iostream> #include <string.h> #include "tulkki.h" using namespace std; int main(int argc,char *argv[]){ TULKKI_parseri("print(moi)"); system("PAUSE"); return 0; }
Mikset voisi vaan ottaa käyttöön tuota Mazzimon mainitsemaa std::string-luokkaa, koska käytät C++:aa?
kayttaja-3842 kirjoitti:
if(tuloskomento == "print"){
Et voi vertailla char-taulua noin (niitä vertaillaan strcmp-funktiolla). Ota ne std::stringit käyttöön, niitä voi.
Regexp, capturing matches.
"(.*?)\((.*?))\)" tms. eli eka capturing group on kaikki ennen ekaa ( ja toka () sisällä oleva. Sen jälkeen spilttaa tokan ryhmän , ja saa erilliset argumentit.
String-luokkaa käyttäessä tuo on todellakin paljon helpompaa, katso vaikka:
// *** Tulkki.h #include <iostream> #include <fstream> #include <string> using namespace std; extern void Tulkki(string komento) { if (komento.compare(0, 9, "writeline") == 0) { int Aloitus = komento.find("("); int Lopetus = komento.find(")"); cout << komento.substr(Aloitus + 1, Lopetus - (Aloitus + 1)); } }
Ja käyttö:
#include <iostream> #include "Tulkki.h" using namespace std; int main() { Tulkki("writeline(Toimiiko?)"); return 0; }
Paljon helpompaa ja selkeämpää.
Lue lisää string-luokasta täältä.
Aihe on jo aika vanha, joten et voi enää vastata siihen.