[c++] Probleem met variable

Pagina: 1
Acties:

  • eppie
  • Registratie: Maart 2000
  • Niet online
(overleden)
Hallo,

Ik ben bezig met het proggen van een eigen shelletje.
Maar nou heb ik nogal een probleem waar ik niet uit kom.

Die commandline constructor krijgt bijvoorbeeld "a;b|c;d" mee.

Als ik die aanroep : pipes[count] = new Pipeline(pipe); weglaat geeft hij mooi
3 regels weer gesplitst bij de ; . Ook als ik alle strtok in Pipeline weglaat doet hij het ook goed, maar zodra die in pipeline gaat splitsen op | (ook al zijn die er niet)
dan maakt hij maar 1 nieuwe pipeline aan en stopt.


Commandline.cc
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Commandline::Commandline(char * _cmdline){

        char *cmdline = _cmdline;
        cout << "cmdline: "<<cmdline<<endl;
        char *pipe;
        pipe= strtok(cmdline, ";");
        int count = 0;
        while(pipe != NULL){
            pipes[count] = new Pipeline(pipe);
            cout << "aangemaakt"<<endl;
            pipe = strtok(NULL, ";");
            count ++;
        }
        
        
}


Pipeline.cc
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Pipeline::Pipeline(char * _pipe){

        pipe=_pipe;
        char *p;
        cout << "new pipeline" <<endl;
        p= strtok(pipe, "|");
        int count = 0;
        
        while(p != NULL){
            cout << p <<endl;
            p = strtok(NULL, "|");
            count ++;
        }
        
 
        
}


Uitvoer als commandline a;b;c binnen krijgt.

code:
1
2
3
4
5
/pub/school/s2 - $>a;b;c
cmdline: a;b;c
new pipeline
a
aangemaakt


Nu uitvoer als ik de strtok en while loop in pipeline weghaal
code:
1
2
3
4
5
6
7
8
/pub/school/s2 - $>a;b;c
cmdline: a;b;c
new pipeline
aangemaakt
new pipeline
aangemaakt
new pipeline
aangemaakt


Gewoon wel goed.
Het lijkt wel dat door die strtok in pipeline de pipe variable in commandline veranderd, maar dat lijkt mij helemaal niet te kunnen. Ben al de hele dag bezig maar kan de fout niet vinden hopelijk snappen jullie wat ik fout doe :).

Alvast bedankt.

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 23:14
Ik moet bekennen dat ik je code niet in detail doorgenomen heb, maar waarschijnlijk loop je tegen het aloude probleem met strtok() aan: het is niet thread-safe. Dat betekent dus dat je maar 1 string tegelijk kan tokenizen en hier wil je er twee tegelijk doen (terwijl je pas halverwege het splitsen op puntkomma's bent wil je de substrings al splitsen op pipes).

De technische reden dat het misgaat is natuurlijk dat de functie intern bijhoudt in welke string 'ie bezig was en dat wordt geinitialiseerd als je het eerste argument non-NULL maakt. Als je alleen de strtok calls bekijkt dan ziet je code er zo uit:
C:
1
2
3
4
strtok("a;b;c", ";");
strtok("a", "|");
strtok(NULL, ";");
strtok(NULL, ";");

Op het moment dat je voor de tweede keer strtok aanroept verdwijnt de state die je had opgebouwd. Logisch ook, want de derde en vierde aanroep zijn zo ambigue als maar kan: hoe kan strtok nu weten welke van de twee strings waar je mee bezig was je wil tokenizen?

De oplossing is om hier gewoon geen strtok voor te gebruiken, maar strsep of strtok_r te gebruiken. De tweede is een thread-safe variant op strtok en de eerste is eigenlijk een iets andere methode (maar vaak juist wat makkelijker in het gebruik).

[ Voor 13% gewijzigd door Soultaker op 12-04-2004 15:14 ]


  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 09-04 22:08
De diagnose van de TS is correct. strtok verandert de input string. Dat kan omdat hij geen OO gebruikt maar C code. De regel ' char *cmdline = _cmdline; ' is geen kopie.

std::string en boost::tokenizer hebben redelijker gedrag.

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • igmar
  • Registratie: April 2000
  • Laatst online: 12-05 15:46

igmar

ISO20022

eppie schreef op 12 april 2004 @ 14:13:
Het lijkt wel dat door die strtok in pipeline de pipe variable in commandline veranderd, maar dat lijkt mij helemaal niet te kunnen. Ben al de hele dag bezig maar kan de fout niet vinden hopelijk snappen jullie wat ik fout doe :).
Een copy & paste uit een UNIX strtok manual page :

BUGS
Never use these functions. If you do, note that:

These functions modify their first argument.

The identity of the delimiting character is lost.

These functions cannot be used on constant strings.

The strtok() function uses a static buffer while
parsing, so it's not thread safe. Use strtok_r() if
this matters to you.

Niet gebruiken dus :)