/ Forside / Teknologi / Udvikling / C/C++ / Nyhedsindlæg
Login
Glemt dit kodeord?
Brugernavn

Kodeord


Reklame
Top 10 brugere
C/C++
#NavnPoint
BertelBra.. 2425
pmbruun 695
Master_of.. 501
jdjespers.. 500
kyllekylle 500
Bech_bb 500
scootergr.. 300
gibson 300
molokyle 287
10  strarup 270
Hvordan nemmest....
Fra : Nuller


Dato : 08-12-03 22:22

Hello....


Jeg har lavet et program der laver en streng. Denne streng indeholde
information, som jeg ønsker at decifrere. Forklaring følger:

Strengen kan betragtes som en "kommando" streng, dvs der kan feks stå
følgende:

ABCD OPQ 123

Jeg har forsøgt med switch.. case, men da C ikke understøtter direkte strcmp
på switch niveau, droppede jeg dette.

Har så forsøgt med if, men for at det skal virke har jeg brugt strng[x]
altså karakterpladsen som test i if sætningen.

Men jeg synes at dette er noget rod, da testen nødvendigvis først må teste
på første karakter, dernæst næste osv.

Hvad gør en professionel der har forskellige kommandoer der skal fortolkes?
Og Hvordan?


N




 
 
Bertel Brander (08-12-2003)
Kommentar
Fra : Bertel Brander


Dato : 08-12-03 23:16

Nuller wrote:

> Hello....
>
>
> Jeg har lavet et program der laver en streng. Denne streng indeholde
> information, som jeg ønsker at decifrere. Forklaring følger:
>
> Strengen kan betragtes som en "kommando" streng, dvs der kan feks stå
> følgende:
>
> ABCD OPQ 123
>
> Jeg har forsøgt med switch.. case, men da C ikke understøtter direkte strcmp
> på switch niveau, droppede jeg dette.
>
> Har så forsøgt med if, men for at det skal virke har jeg brugt strng[x]
> altså karakterpladsen som test i if sætningen.
>
> Men jeg synes at dette er noget rod, da testen nødvendigvis først må teste
> på første karakter, dernæst næste osv.
>
> Hvad gør en professionel der har forskellige kommandoer der skal fortolkes?
> Og Hvordan?
>

Jeg ved ikke hvad en professionel ville gøre, men man kunne lave:

enum CommandType
{
ABCD_CMD,
FOO_CMD,
BAR_CMD,
UNKNOWN_CMD
};

struct
{
CommandType Command;
const char * const Text;
}CommandList[] =
{
{ABCD_CMD, "ABCD"},
{FOO_CMD, "FOO"},
{BAR_CMD, "BAR"}
};


Og så lave en funktion der slår op i CommandList og returnerer en
CommandType, denne kunne bruges i din switch, f.ex

CommandType FindCommand(const char *const whatever)
{
for(int i = 0; i < sizeof(CommandList)/sizeof(CommandList[0]); i++)
if(!strcmp(whatever, CommandList[i].Text)
return CommandList[i].Command;

return UNKNOWN_CMD;
}

switch(FindCommand(Text))
{
case ABCD_CMD:
break;
...
}

/b


Mogens Hansen (09-12-2003)
Kommentar
Fra : Mogens Hansen


Dato : 09-12-03 16:47

"Nuller" <nuller@goej.net> wrote:

[8<8<8]
> Hvad gør en professionel der har forskellige kommandoer der skal
fortolkes?

Det første jeg ville erkende er det er en parsningsopgave og derfor kigge
efter værktøjer/design til parsning.

Desuden ville jeg erkende at hvis man kan sende kommandoer til et program,
kan man principielt modtage vilkårligt sludder. Derfor skal parsningen være
robust, og der bør ikke være ikke runtime uverificerede antagelser om at
kommandoen nok ikke er længere end 16 (vælg selv et passende magic number)
tegn.

Idet jeg antager at du programmerer i C++, er det oplagt at kigge på
* funktionen strtok (også C)
* Boost.Tokenizer
* Boost.Regex
* Boost.Spirit

Boost bibliotekerne finder du på www.boost.org.
De er under alle omstændigheder værd at kigge på.

Personligt vil jeg foretrække Spirit, fordi det er simpelt at bruge (når man
har lært det) og kraftfuldt når udvalget af kommandoer ændrer sig.

> Og Hvordan?

<C++ kode>
#include <iostream>
#include <string>
#include <boost/spirit/core.hpp>
#include <boost/bind.hpp>
#include <boost/ref.hpp>

using namespace std;
using namespace boost;
using namespace boost::spirit;

// The functions which does the "real" work

enum tag_sub_abcd
{ OPQ,
RST
};

void foo()
{
cout << "FOO command executed" << endl;
}

void bar()
{
cout << "BAR command executed" << endl;
}

void abcd(tag_sub_abcd sub_abcd, int value)
{
cout << "ABCD command executed" << endl;

switch(sub_abcd) {
case OPQ: {
cout << " OPQ sub command executed" << endl;
}
break;

case RST: {
cout << " RST sub command executed" << endl;
}
break;
}

cout << " value: " << value << endl;
}

// Helper functions and function objects for the parser

template <typename T>
class do_assign_actor
{
public:
do_assign_actor(T& t_arg, const T& value_arg) :
t(t_arg), value(value_arg) {}

void operator()(const char* /*begin*/, const char* /*end*/) const
{ t = value; }

private:
mutable T& t;
const T value;
};

template <typename T>
inline do_assign_actor<T> assign(T& t_arg, const T& value_arg)
{
return do_assign_actor<T>(t_arg, value_arg);
}


class skip_arg
{
public:
typedef void (*func_type)();
skip_arg(func_type func_arg) :
func(func_arg) {}
void operator()(const char* /*begin*/, const char* /*end*/) const
{ func(); }

private:
func_type func;
};

// The command parser

struct cmd_parser : public grammar<cmd_parser>
{
cmd_parser(bool& cont_arg) :
cont(cont_arg) {}

template <typename ScannerT>
struct definition
{
definition(cmd_parser const& self)
{
cmd_abcd_p
= strlit<>("ABCD")
>> +space_p // followed by one or more spaces
>> ( strlit<>("OPQ") [assign(cmd_adcb_param_1, OPQ)]
| strlit<>("RST") [assign(cmd_adcb_param_1, RST)]
)
>> +space_p
>> int_p [assign(cmd_adcb_param_2)]
>> end_p // allow nothing after the integer
;

cmd_foo_p
= strlit<>("FOO")
>> end_p // allow nothing after the command
;

cmd_bar_p
= strlit<>("BAR")
>> end_p // allow nothing after the command
;

cmd_quit_p
= ( chlit<>('q')
| chlit<>('Q')
)
>> *anychar_p
;

cmd_p
= cmd_abcd_p [bind(abcd, ref(cmd_adcb_param_1),
ref(cmd_adcb_param_2))]
| cmd_foo_p [skip_arg(foo)]
| cmd_bar_p [skip_arg(bar)]
| cmd_quit_p [assign(self.cont, false)]
;
}

rule<ScannerT> cmd_p, cmd_abcd_p, cmd_foo_p, cmd_bar_p, cmd_quit_p;
tag_sub_abcd cmd_adcb_param_1;
int cmd_adcb_param_2;

rule<ScannerT> const& start() const
{ return cmd_p; }
};

bool& cont;
};


int main()
{
string str;
bool cont = true;
cmd_parser cmd_p(cont);
while (cont && getline(cin, str)) {
parse_info<> info = parse(str.c_str(), cmd_p, nothing_p);

if (!info.full) {
cout << str << endl;
fill_n(ostream_iterator<char>(cout), info.stop-str.c_str(), ' ');
cout << "^\n"
<< "Parsing failed\n" << endl;
}
}
}
<C++ kode/>

Pas på linier, der er wrappet rund af news-programmet!

Det burde virke på de mange platforme med mange compilere.

Bemærk at programmet er komplet med hensyn til:
* vilkårlig størrelse kommando
* fejlhåndtering
* ved out-of-memory situation
* ved fejl i kommandoen

Venlig hilsen

Mogens Hansen







Nuller (09-12-2003)
Kommentar
Fra : Nuller


Dato : 09-12-03 22:41

> Det første jeg ville erkende er det er en parsningsopgave og derfor kigge
> efter værktøjer/design til parsning.

Var også min tanke, men da jeg er en meget lidt øvet C-Programmør, fandt jeg
det nemmere at spørge hér.

> Desuden ville jeg erkende at hvis man kan sende kommandoer til et program,
> kan man principielt modtage vilkårligt sludder. Derfor skal parsningen
være
> robust, og der bør ikke være ikke runtime uverificerede antagelser om at
> kommandoen nok ikke er længere end 16 (vælg selv et passende magic number)
> tegn.

Også på dette punkt kan jeg kun nikke anerkendende.

> Idet jeg antager at du programmerer i C++, er det oplagt at kigge på
> * funktionen strtok (også C)
> * Boost.Tokenizer
> * Boost.Regex
> * Boost.Spirit

Nej, desværre programmere jeg ikke C++ endnu.
Er desværre aldrig nået videre til C++, da jeg er småbørns-familie-fader, og
programmering er een af mine fritids-sysler.
Mit kendskab til C startede på Amiga, da der kom Lattice C version 5.0 til
den.
C++ på Amiga var dengang vist et fy-ord, for der nåede ikke rigtigt at komme
nogen ordentlig C++ kompiler mens jeg brugte den.
Jo Lattice blev da godt nok til SAS/C og SAS/C++, men personligt brød jeg
mig ikke om at benytte C++ delen, da denne var en underlig overbygning til
SAS/C der blev oversat til standard C. Og dette tog med datidens langsomme
processor for lang tid.
Købte endda det originale Lattice C program dengang, og opdaterede også til
SAS/C++ 6.5 siden hen.
Men pludselig stod jeg med kone, hus og barn, og Amiga'en døde langsomt.
Men nu er jeg begyndt at kode lidt igen, denne gang på PC, og denne gang har
det et formål, da jeg skal bruge det til at styre noget hardware ifbm en af
mine andre hobby'er.
Men da denne hardware er nogen ældre ISA-kort, kører programmet følgelig
også på en gammel computer, der ligeledes køre med dos.
Har i den forbindelse overtaget en komplet original Borland C++ 3.1 til
dette formål. Og dette virker også ganske udemærket.
Og jo, lidt C++ benytter jeg da i koden, men dette kun fordi det var nemmere
end i standard C. Eks. bruger jeg funktioner med samme navn men med
forskellige argument type.

Men ellers er jeg ren novice på C++ området. En del bøger omkring skift fra
C til C++ er jeg også kommet i besiddelse af, men har endnu ikke nået at få
læst særligt meget i dem endnu.
Så ind til videre klarer jeg mig i ren C.


> Boost bibliotekerne finder du på www.boost.org.
> De er under alle omstændigheder værd at kigge på.
>
> Personligt vil jeg foretrække Spirit, fordi det er simpelt at bruge (når
man
> har lært det) og kraftfuldt når udvalget af kommandoer ændrer sig.

Har nu hentet disse, men det er en stor mundfuld at sætte sig ind i, da
denne pakke er enormt stor. Men jeg kan godt se mulighederne i dette.
Og jeg vil helt sikkert studere det, når tid melder sig.

> <C++ kode>
> #include <iostream>
> #include <string>
> #include <boost/spirit/core.hpp>
> #include <boost/bind.hpp>
> #include <boost/ref.hpp>
---CUT---

Men umiddelbart ligner det da Un*x kode mht skråstregs opdelt Dir's.
Vil dette virke på Vindues PC'er? Eller for den sags skyld DOS?
Amiga ville sikkert gerne acceptere dette, da den også benyttede skråstreg
for Dir's.

Mht koden. Jeg kan godt følge dig, selv om jeg for at få fuld forståelse,
skal nær-studere det gennemgående.

Men tak til Jer begge for Jeres svar.

N



Bertel Brander (09-12-2003)
Kommentar
Fra : Bertel Brander


Dato : 09-12-03 23:36

>
>><C++ kode>
>>#include <iostream>
>>#include <string>
>>#include <boost/spirit/core.hpp>
>>#include <boost/bind.hpp>
>>#include <boost/ref.hpp>
>
> ---CUT---
>
> Men umiddelbart ligner det da Un*x kode mht skråstregs opdelt Dir's.
> Vil dette virke på Vindues PC'er? Eller for den sags skyld DOS?

Ja.

/b


Mogens Hansen (10-12-2003)
Kommentar
Fra : Mogens Hansen


Dato : 10-12-03 05:36


"Nuller" <nuller@goej.net> wrote:

[8<8<8<]
> Var også min tanke, men da jeg er en meget lidt øvet C-Programmør, fandt
jeg
> det nemmere at spørge hér.

[8<8<8<]
> Nej, desværre programmere jeg ikke C++ endnu.

At kunne programmere i C er ikke en forudsætning for at programmere i C++.

> Er desværre aldrig nået videre til C++, da jeg er småbørns-familie-fader,

Ja, det kan jeg godt følge

> Men da denne hardware er nogen ældre ISA-kort, kører programmet følgelig
> også på en gammel computer, der ligeledes køre med dos.

Strengt taget kan man godt finde en computer med ISA slots, som kan køre
MS-Windows eller Linux, og dermed få adgang til mere moderne værktøjer -
hvis man vil.
Tilgang til hardware bliver dog noget vanskelligere.

> Har i den forbindelse overtaget en komplet original Borland C++ 3.1 til
> dette formål. Og dette virker også ganske udemærket.

Det var i sin tid en af de bedste C++ compilere der fandtes, men du skal
være opmærksom på at der er sket meget med C++ siden da.
Den er formodentlig et godt stykke fra at være up to date.

[8<8<8<]
> Men ellers er jeg ren novice på C++ området. En del bøger omkring skift
fra
> C til C++ er jeg også kommet i besiddelse af, men har endnu ikke nået at

> læst særligt meget i dem endnu.

Efter min (og mange andres) mening er den bedste introduktion til moderne
C++:
Accelerated C++
Andrew Koenig, Barbara E. Moo
ISBN 0-201-70353-X
Så har du ihvertfald en reference, hvis du får brug for det en dag.

> Så ind til videre klarer jeg mig i ren C.

Fint nok.

[8<8<8<]
> Men umiddelbart ligner det da Un*x kode mht skråstregs opdelt Dir's.
> Vil dette virke på Vindues PC'er? Eller for den sags skyld DOS?
> Amiga ville sikkert gerne acceptere dette, da den også benyttede skråstreg
> for Dir's.

Ja, selvom det nok at få fat på en DOS C++ compiler, der er tilstrækkeligt
moderne.
Det er faktisk kun testet på MS-Windows med
Borland C++Builder 6.0
Intel C++ 8.0
Microsoft Visual C++ 7.1 (.NET 2003)


Venlig hilsen

Mogens Hansen



Bertel Lund Hansen (10-12-2003)
Kommentar
Fra : Bertel Lund Hansen


Dato : 10-12-03 07:33

Mogens Hansen skrev:

>Ja, selvom det nok at få fat på en DOS C++ compiler, der er tilstrækkeligt
>moderne.

Man kan i hvert fald få Borlands gratis version 5.5. Jeg ved dog
ikke om den kan køre på nævnte hardware.

--
Bertel
http://bertel.lundhansen.dk/   FIDUSO: http://fiduso.dk/

Ivan Johansen (10-12-2003)
Kommentar
Fra : Ivan Johansen


Dato : 10-12-03 08:50

Bertel Lund Hansen wrote:
> Man kan i hvert fald få Borlands gratis version 5.5. Jeg ved dog
> ikke om den kan køre på nævnte hardware.

Den kan hverken køre under DOS eller lave programmer til DOS. Det er en
ren Win32 compiler. Jeg tror den sidste compiler som kunne lave DOS
programmer var Borland C++ 5.

Ivan Johansen


Bertel Lund Hansen (10-12-2003)
Kommentar
Fra : Bertel Lund Hansen


Dato : 10-12-03 10:35

Ivan Johansen skrev:

>> Man kan i hvert fald få Borlands gratis version 5.5. Jeg ved dog
>> ikke om den kan køre på nævnte hardware.

>Den kan hverken køre under DOS eller lave programmer til DOS.

Øh ... Det er den jeg bruger, og jeg afvikler alle mine færdige
programmer i DOS-bokse under Windows 95.

--
Bertel
http://bertel.lundhansen.dk/   FIDUSO: http://fiduso.dk/

Ivan Johansen (10-12-2003)
Kommentar
Fra : Ivan Johansen


Dato : 10-12-03 11:03

Bertel Lund Hansen wrote:
> Øh ... Det er den jeg bruger, og jeg afvikler alle mine færdige
> programmer i DOS-bokse under Windows 95.

Windows og DOS er to forskellige ting. Det du kalder en DOS-boks hedder
en konsol og de programmer du laver er Windows konsolprogrammer, som
ikke kan køres i DOS.

Hvis du forsøger at køre programmet fra DOS får du at vide at det kræver
Microsoft Windows. Hvis du forsøger at udføre almindelig DOS-ting i dit
program under Windows, som at kalde interrupt 21h, vil dit program
straks blive lukket med en besked om at det har udført en ulovlig handling.

Jeg ved godt at mange ikke kan kende forskel på DOS-programmer og
Windows konsolprogrammer, men der er faktisk temmelig stor forskel.

Ivan Johansen




Bertel Lund Hansen (10-12-2003)
Kommentar
Fra : Bertel Lund Hansen


Dato : 10-12-03 11:10

Ivan Johansen skrev:

>en konsol og de programmer du laver er Windows konsolprogrammer, som
>ikke kan køres i DOS.

Du har ret. Det er for lidt jeg arbejder i ren DOS mere.

--
Bertel
http://bertel.lundhansen.dk/   FIDUSO: http://fiduso.dk/

Søg
Reklame
Statistik
Spørgsmål : 177549
Tips : 31968
Nyheder : 719565
Indlæg : 6408820
Brugere : 218887

Månedens bedste
Årets bedste
Sidste års bedste