/ 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
En anden petitesse: strchr() eller flere i~
Fra : Bertel Lund Hansen


Dato : 06-08-03 11:22

Hej alle

Hvad er bedst:

while (strchr("\"<>",*pos)) ++pos;

eller

if (*pos=='\"' || *pos=='<' || *pos=='>') ++pos;

Det kan lyde som et petitessespørgsmål, og det er det også, men
det drejer sig om hvilken vane jeg skal tillægge mig eller
beholde.

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

 
 
Kent Friis (06-08-2003)
Kommentar
Fra : Kent Friis


Dato : 06-08-03 12:22

Den Wed, 06 Aug 2003 12:21:46 +0200 skrev Bertel Lund Hansen:
>Hej alle
>
>Hvad er bedst:
>
> while (strchr("\"<>",*pos)) ++pos;
>
>eller
>
> if (*pos=='\"' || *pos=='<' || *pos=='>') ++pos;
>
>Det kan lyde som et petitessespørgsmål, og det er det også, men
>det drejer sig om hvilken vane jeg skal tillægge mig eller
>beholde.

Hvis du nu du er igang laver en

#define SEPARATORS "\"<>"

og så bruger den, så er programmet nemmere at udvide den dag du får
brug for to mere.

(Så kan du selv regne ud hvilken løsning der virker bedst med det
forslag).

Mvh
Kent
--
IE is the only thing capable of making Netscape look good
- D. Spider in comp.os.linux.advocacy

Bertel Lund Hansen (06-08-2003)
Kommentar
Fra : Bertel Lund Hansen


Dato : 06-08-03 13:03

Kent Friis skrev:

>Hvis du nu du er igang laver en

>#define SEPARATORS "\"<>"

Klart nok, dem har jeg mange af, denne her havde jeg blot
overset.

>(Så kan du selv regne ud hvilken løsning der virker bedst med det
>forslag).

Tænke, tænke ...

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

Jens Axel Søgaard (06-08-2003)
Kommentar
Fra : Jens Axel Søgaard


Dato : 06-08-03 13:55

Kent Friis wrote:
> Den Wed, 06 Aug 2003 12:21:46 +0200 skrev Bertel Lund Hansen:
>
>>Hej alle
>>
>>Hvad er bedst:
>>
>> while (strchr("\"<>",*pos)) ++pos;
>>
>>eller
>>
>> if (*pos=='\"' || *pos=='<' || *pos=='>') ++pos;
>>
>>Det kan lyde som et petitessespørgsmål, og det er det også, men
>>det drejer sig om hvilken vane jeg skal tillægge mig eller
>>beholde.
>
>
> Hvis du nu du er igang laver en
>
> #define SEPARATORS "\"<>"
>
> og så bruger den, så er programmet nemmere at udvide den dag du får
> brug for to mere.

Hvorfor ikke tage skridtet fuldt ud og lave en makro,
så man kan se hvad der sker:

#define SEPARATORS "\"<>"

/* SKIP_SEPATORS( char *pos )
Increase pos until *pos is a char not in SEPARATORS
*/
#define SKIP_SEPARATORS(pos) (strchr((SEPARATORS),*(pos))) ++(pos)

...
SKIP_SEPARATORS(pos);
...

(ikke testet)

--
Jens Axel Søgaard


Igor V. Rafienko (06-08-2003)
Kommentar
Fra : Igor V. Rafienko


Dato : 06-08-03 14:05

[ usenet@jasoegaard.dk ]

[ ... ]

> Hvorfor ikke tage skridtet fuldt ud og lave en makro, (...)


Helt fantastisk. _Flere_ gode forslag?





ivr, d'uh!
--
<html><form><input type crash></form></html>

Soeren Sandmann (06-08-2003)
Kommentar
Fra : Soeren Sandmann


Dato : 06-08-03 17:07

Bertel Lund Hansen <nospamfor@lundhansen.dk> writes:

> while (strchr("\"<>",*pos)) ++pos;
>
> eller
>
> if (*pos=='\"' || *pos=='<' || *pos=='>') ++pos;

Den sidste variant er betydeligt mere læselig end den første. Det er
muligvis en vanesag, men jeg var nødt til at studere den første
variant mere end én gang før det gik op for mig hvordan den virkede.
Det er ret usædvanligt at benytte strchr() til at søge efter variable
tegn i en konstant streng.

Kent Friis (06-08-2003)
Kommentar
Fra : Kent Friis


Dato : 06-08-03 18:11

Den 06 Aug 2003 18:06:45 +0200 skrev Soeren Sandmann:
>Bertel Lund Hansen <nospamfor@lundhansen.dk> writes:
>
>> while (strchr("\"<>",*pos)) ++pos;
>>
>> eller
>>
>> if (*pos=='\"' || *pos=='<' || *pos=='>') ++pos;
>
>Den sidste variant er betydeligt mere læselig end den første. Det er
>muligvis en vanesag, men jeg var nødt til at studere den første
>variant mere end én gang før det gik op for mig hvordan den virkede.
>Det er ret usædvanligt at benytte strchr() til at søge efter variable
>tegn i en konstant streng.

Det har jeg brugt mange gange.

Når antallet af konstante tegn er fx. 25, så er det absolut den nemmeste
måde.

Mvh
Kent
--
Indlæringskurven til Linux er stejl, til tider lodret... Men for katten
hvor er udsigten på toppen dog fantastisk
- Michael G. Vendelbo i dk.snak

Bertel Lund Hansen (06-08-2003)
Kommentar
Fra : Bertel Lund Hansen


Dato : 06-08-03 18:23

Soeren Sandmann skrev:

1)
>> while (strchr("\"<>",*pos)) ++pos;
>> eller

2)
>> if (*pos=='\"' || *pos=='<' || *pos=='>') ++pos;

>Den sidste variant er betydeligt mere læselig end den første. Det er
>muligvis en vanesag, men jeg var nødt til at studere den første
>variant mere end én gang før det gik op for mig hvordan den virkede.
>Det er ret usædvanligt at benytte strchr() til at søge efter variable
>tegn i en konstant streng.

Hm. Jeg har mine programmeringsvaner fra mig selv, men den metode
forekommer mig ganske logisk. Nu blev jeg imidlertid nødt til at
teste det, og det overraskede mig. En mio. kørsler med to
forskellige rutiner gav:

1):   5'500
2):   1'733

Strengen var lang, men der blev kun tjekket med 3 tegn. Med tjek
med 17 tegn:
1)   19'897
2)    2'950

Tyder det ikke på at strchr() er en dyr funktion?

Og jeg der synes at 1) er meget nemmere at læse ...

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

Soeren Sandmann (06-08-2003)
Kommentar
Fra : Soeren Sandmann


Dato : 06-08-03 19:34

Bertel Lund Hansen <nospamfor@lundhansen.dk> writes:

> Tyder det ikke på at strchr() er en dyr funktion?

Grunden til at jeg anbefalede 2) er at jeg synes det er lettere at
læse, ikke at det er hurtigere.

At det er hurtigere, er naturligvis rart nok, men hvis hastighed er
målet, så er mikrooptimeringer af denne type nærmest ubrugelige,
medmindre du har målt at programmet bruger meget tid lige netop her.

Det er i hvert fald en dårlig vane at vælge noget der er mindre
læseligt frem for noget man tror er mere effektivt (af de grunde som
alle kender til hudløshed).

Hvorfor er strchr() dyrere? Der kan være alle mulige grunde:

- strchr() læser fra hukommelsen, mens if-konstruktionen kun
sammenligner indholdet af et register med konstanter

- der er overhead forbundet med funktionskaldet

- oversætteren kan ikke optimere hen over funktionskald

- find selv på flere.

Ekstraopgave for hurtige elever: Find på grunde til at strchr() kan
være hurtigere end en stor if-konstruktion.

> Og jeg der synes at 1) er meget nemmere at læse ...

Så brug 1). Det er i hvert fald rigtigt nok, som Kent Friis skrev, at
metode 1) skalerer bedre til mange af hinanden uafhængige tegn.

Niels Dybdahl (06-08-2003)
Kommentar
Fra : Niels Dybdahl


Dato : 06-08-03 18:45

> Hvad er bedst:
>
> while (strchr("\"<>",*pos)) ++pos;
>
> eller
>
> if (*pos=='\"' || *pos=='<' || *pos=='>') ++pos;

strchr udgaven indeholder et funktionskald som koster en del. Nogle
compilere laver en inline udgave af strchr, hvilket eliminerer
funktionskaldet. Men stadig består strchr af et loop gennem tegnene, mens
den anden er et 'udfoldet' loop, hvilket er hurtigere end det tilsvarende
loop.
strchr udgaven vil ofte indeholde 1-6 jumps, calls og returns per chara, som
alle kan flushe pipelinen, mens den anden indeholder 1-2 jumps.
Den anden udgave kunne implementeres af compileren som tabelopslag, hvilket
ville være endnu hurtigere. Det er nok ikke sandsynligt at compileren gør
det ved 3 værdier, men ved mange kunne det være en mulighed.

Så nummer 2 er hurtigere og mere letlæselig.

Niels Dybdahl.




Christian Larsen (06-08-2003)
Kommentar
Fra : Christian Larsen


Dato : 06-08-03 19:00

Bertel Lund Hansen <nospamfor@lundhansen.dk> wrote in
news:tgl1jvkqk0vfbpsdtkng6cpal1s7jtifmu@news.stofanet.dk:

> Hej alle
>
> Hvad er bedst:
>
> while (strchr("\"<>",*pos)) ++pos;
>
> eller
>
> if (*pos=='\"' || *pos=='<' || *pos=='>') ++pos;
>

Jeg ved ikke om det har nogen relevans, men så vidt jeg kan se, giver de
to linjer ikke samme resultat. Den første skip'er en sekvens bestående
af et eller flere af tegnene, mens den anden blot skip'er ét tegn. Det
kunne selvfølgelig ændres ved at udskifte if/while.

-Christian

Bertel Lund Hansen (06-08-2003)
Kommentar
Fra : Bertel Lund Hansen


Dato : 06-08-03 20:16

Christian Larsen skrev:

>Det kunne selvfølgelig ændres ved at udskifte if/while.

"If" var en svipser. Der skulle stå "while".

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

Martin M. Pedersen (11-08-2003)
Kommentar
Fra : Martin M. Pedersen


Dato : 11-08-03 17:21

Hej,

"Bertel Lund Hansen" <nospamfor@lundhansen.dk> wrote in message
news:tgl1jvkqk0vfbpsdtkng6cpal1s7jtifmu@news.stofanet.dk...
> while (strchr("\"<>",*pos)) ++pos;
> if (*pos=='\"' || *pos=='<' || *pos=='>') ++pos;

Vær opmærksom på at de to ikke ækvivalente. strchr() inkluderer også det
afsluttende '\0' i strengen den søger i, og løkken kan således køre henover
terminatoren i en NUL termineret streng.

mvh.
Martin



Bertel Lund Hansen (11-08-2003)
Kommentar
Fra : Bertel Lund Hansen


Dato : 11-08-03 22:05

Martin M. Pedersen skrev:

>> while (strchr("\"<>",*pos)) ++pos;
>> if (*pos=='\"' || *pos=='<' || *pos=='>') ++pos;

>Vær opmærksom på at de to ikke ækvivalente. strchr() inkluderer også det
>afsluttende '\0' i strengen den søger i, og løkken kan således køre henover
>terminatoren i en NUL termineret streng.

Hvis du havde ret, skulle den øverste linje scanne hele
computerens hukommelse hver gang. Desuden passer det dårligt med
at strchr() skal returnere NULL hvis tegnet ikke findes i
strengen.

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

Martin M. Pedersen (11-08-2003)
Kommentar
Fra : Martin M. Pedersen


Dato : 11-08-03 22:22

"Bertel Lund Hansen" <nospamfor@lundhansen.dk> wrote in message
news:511gjvkg5qq1cordlct67lp86k2hmqkj2k@news.stofanet.dk...
> Martin M. Pedersen skrev:
>
> >> while (strchr("\"<>",*pos)) ++pos;
> >> if (*pos=='\"' || *pos=='<' || *pos=='>') ++pos;
>
> >Vær opmærksom på at de to ikke ækvivalente. strchr() inkluderer også det
> >afsluttende '\0' i strengen den søger i, og løkken kan således køre
henover
> >terminatoren i en NUL termineret streng.
>
> Hvis du havde ret, skulle den øverste linje scanne hele
> computerens hukommelse hver gang. Desuden passer det dårligt med
> at strchr() skal returnere NULL hvis tegnet ikke findes i
> strengen.

Nej, det sidste '\0' betragtes blot som en del af strengen. Hvis jeg for
eksempel kører dette:

#include <stdio.h>
int main(void)
{
printf("%p\n", strchr("abc", '\0'));
return 0;
}

får jeg: "0x8048407" - dvs. at den har fundet '\0'. Det er også i
standarden. Dette er fra den sidste draft af C99 (men det er ikke ny
opførsel):

7.21.5.2 The strchr function
Synopsis
#include <string.h>
char *strchr(const char *s, int c);
Description
The strchr function locates the first occurrence of c (converted to a
char)
in the string pointed to by s. The terminating null character is
considered
to be part of the string.
Returns
The strchr function returns a pointer to the located character, or a
null
pointer if the character does not occur in the string.


mvh.
Martin



Bertel Lund Hansen (11-08-2003)
Kommentar
Fra : Bertel Lund Hansen


Dato : 11-08-03 23:32

Martin M. Pedersen skrev:

>Nej, det sidste '\0' betragtes blot som en del af strengen.

Ja, naturligvis.

Men du skrev før:

>løkken kan således køre henover terminatoren i en NUL termineret streng.

Det kan den bare ikke.

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

Martin M. Pedersen (11-08-2003)
Kommentar
Fra : Martin M. Pedersen


Dato : 11-08-03 23:48

"Bertel Lund Hansen" <nospamfor@lundhansen.dk> wrote in message
news:bs5gjvcceig6p5v075k3bltb5svg40a5l1@news.stofanet.dk...
> >løkken kan således køre henover terminatoren i en NUL termineret streng.
> Det kan den bare ikke.

Sagtens. Prøv dette:

#include <stdio.h>
int main(void)
{
static const char str[] = "\"\"<<>>\0\0\0>>h";
const char* pos = str;
while (strchr("\"<>",*pos)) ++pos;
printf("*pos = %c (%d)\n", *pos, *pos);
}

Den kører naturligvis henover '\0'erne og finder h'et.

mvh.
Martin



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


Dato : 12-08-03 09:07

Martin M. Pedersen skrev:

>Den kører naturligvis henover '\0'erne og finder h'et.

Nu var der lissom ikke noget \0 i den linje som din påstand
handlede om.

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

Martin M. Pedersen (12-08-2003)
Kommentar
Fra : Martin M. Pedersen


Dato : 12-08-03 15:35

"Bertel Lund Hansen" <nospamfor@lundhansen.dk> wrote in message
news:8v7hjvcnkdb36coochielvndqn0gmv85s2@news.stofanet.dk...
> Martin M. Pedersen skrev:
>
> >Den kører naturligvis henover '\0'erne og finder h'et.
>
> Nu var der lissom ikke noget \0 i den linje som din påstand
> handlede om.

Nå, jeg synes ellers det udemærket illustrerer at løkken kører hen over
NUL'er. Jeg prøver igen. Min påstand var "løkken kan således køre henover
terminatoren i en NUL termineret streng.", hvilket også dette program
illustrer:

===============
#include <stdio.h>

int main(void)
{
static const char str[] = "<<>>";

const char *pos = str;
while (strchr("\"<>",*pos)) ++pos;
printf("str=%p pos=%p skipped=%d\n", str, pos, pos-str);

return 0;
}
===============

Hos mig skriver den tilfældigvis "str=0x8048424 pos=0x804842d skipped=9",
men i princippet kunne programmet lige så godt dø af en segmentation fault
eller lignende.

mvh.
Martin





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


Dato : 12-08-03 16:06

Martin M. Pedersen skrev:

>NUL'er. Jeg prøver igen. Min påstand var "løkken kan således køre henover
>terminatoren i en NUL termineret streng.", hvilket også dette program
>illustrer:

Du har ganske ret, og jeg er overrasket. Det er sikkert derfor at
den løsning er meget langsommere end sammenligningen ét tegn ad
gangen.

Min løsning i programmet blev imidlertid at lave en makro baseret
på den hurtige metode, så jeg har allerede undgået problemet.

Tak for hjælpen.

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

Søg
Reklame
Statistik
Spørgsmål : 177580
Tips : 31968
Nyheder : 719565
Indlæg : 6409081
Brugere : 218888

Månedens bedste
Årets bedste
Sidste års bedste