Avatar billede learner Praktikant
09. oktober 2012 - 18:51 Der er 19 kommentarer og
1 løsning

brugen af strlen() og æøå mv

Hejsa

Jeg har oplevet nogen fejl og har lige fundet ud af hvorfor.

echo strlen(trim('sæt t.højre for dør i gården, bank på!'))
// skriver 43

Men tæller jeg, så er der vist kun 38 tegn

Hvilken anden funktion kan jeg bruge til at tælle antal tegn med? Gerne en funktion som virker med æøåö osv.

På forhånd tak for hjælpen
Avatar billede moddi100 Seniormester
09. oktober 2012 - 18:59 #1
Funktionen virker skam præcist efter hensigten, det er blot dig som giver funktionen forkert input :)

Filens kodning kan nemlig resultere i at æøå ikke opfattes korrekt, sørg for at filen er i UTF-8 formatet.

Alternativt kan du også gøre det i koden:

echo strlen(utf8_decode(trim('sæt t.højre for dør i gården, bank på!')));
Avatar billede scootergrisen Nybegynder
09. oktober 2012 - 19:14 #2
Brug mb_strlen() i stedet for strlen().

Jeg har skrevet noget om det her : http://scootergrisen.dk/htmlgrisen/kode_strenge.php#multibyte_funktioner

Kræver at du bar mbstring installeret. Hvis ikke du har det så kør PHP installationen igen og tilvælg mbstring.

Det fordi når du gemmer din fil som UTF-8 så fylder tegn som Æ 2 byte. Men strlen() opfatter 1 byte som 1 tegn så det går galt.

Der finder i øvrigt mange af de her erstatningsfunktioner til strenge hvor du tilføjer mb_ foran funktionsnavnet.
Avatar billede olebole Juniormester
09. oktober 2012 - 19:41 #3
<ole>

Der er mange alternativer ... f.eks:

$str = 'Øl, ål og røreæg';
$len = count(str_split($str));

/mvh
</bole>
Avatar billede lclemens Nybegynder
09. oktober 2012 - 20:29 #4
ole,

$str = 'Øl';
$len = count(str_split($str));

$len indeholder tallet 3 hos mig. Vil du prøve igen? :-)
Avatar billede olebole Juniormester
09. oktober 2012 - 21:04 #5
@lclemens: Ja, det kan jeg da godt se! Jeg havde forestillet mig, at dokumentationen holdt vand:

If the optional split_length parameter is specified, the returned array will be broken down into chunks with each being split_length in length, otherwise each chunk will be one character in length.

Men det var nok lidt naivt. Der skulle tydeligvis have stået:

[...] otherwise each chunk will be one byte in length.
Avatar billede lclemens Nybegynder
09. oktober 2012 - 21:35 #6
Tja, man kunne jo læse begyndelsen af dokumentationen

A string is series of characters, where a character is the same as a byte.


:-)
Avatar billede olebole Juniormester
09. oktober 2012 - 21:58 #7
Nu var det dokumentationen for str_split, jeg tænkte på. Det burde ikke være nødvendigt at skulle ned i grunddokumentationen for at finde en disclaimer, som forklarer, at sproget er skrevet i et andet årtusindes paradigme - og at al dokumentation skal læses i dette lys.

I 2012 burde den slags explicit fremgå under de berørte funktioner  =)
Avatar billede lclemens Nybegynder
09. oktober 2012 - 22:09 #8
Du begår da ikke samme fejl som fandens oldemor :-)
Avatar billede olebole Juniormester
09. oktober 2012 - 22:24 #9
Substansen er, at PHP på mange områder er outdated - og at den slags væsentlige 'detaljer' naturligvis explicit bør fremgå af dokumentationen for de berørte funktioner.

Hvis man mener, det er udtryk for en dårlig undskyldning, er det måske, fordi man selv har brug for en  *o)
Avatar billede lclemens Nybegynder
09. oktober 2012 - 22:32 #10
Man kører jo heller ikke over for rødt, selv om man ikke explicit har fået fortalt, at det må man ikke i dét kryds.

:-)
Avatar billede olebole Juniormester
09. oktober 2012 - 23:08 #11
Nej, det ville da være totalt idiotisk!

Men til gengæld er der næppe nogensinde en myndighed, som vil være så tåbelig at skrive:

"Krydset kan frit passeres!"

- underforstået: "- men som færdselsloven foreskriver: Kun når der er grønt lys!"
Avatar billede olebole Juniormester
09. oktober 2012 - 23:10 #12
Forskellen på 'dokumentation' og 'snik-snak' er, at dokumentationen skal være explicit  *o)
Avatar billede olebole Juniormester
09. oktober 2012 - 23:18 #13
PS: og så er dit eksempel faktisk ret misvisende  =)

PHP er beregnet til pre processing af HTML. Multibyte tegnsæt er forlængst blevet de facto tegnsæt på WWW, så det burde i udgangspunktet kunne forventes, at sprog, som behandler webdokumenter, i er indrettet på dette.

Sagen er jo netop, at man ved 'din' lyskurv forventes at køre overfor rødt, mens man alle andre steder holder tilbage. Derfor burde du nok have sat et skilt op, som forklarede forskellen  *o)
Avatar billede lclemens Nybegynder
09. oktober 2012 - 23:47 #14
Dokumentationen gør tydeligt opmærksom på, at et tegn i en php-streng altid er én byte. Du kan altså ikke sno dig uden om.
Avatar billede olebole Juniormester
10. oktober 2012 - 00:47 #15
Som Rudy S. Kleutzner så sandt siger det: "Har man ikke pære, må man ævle!"
Avatar billede arne_v Ekspert
10. oktober 2012 - 03:57 #16
En PHP string indeholder bytes.

Derved kan en PHP string indeholder:
- tekst i single byte encoding
- tekst i multi byte encoding
- binary data

Teksten øverst i http://www.php.net/manual/en/language.types.string.php er faktisk forkert, men længere nede kommer den rigtige forklaring i http://www.php.net/manual/en/language.types.string.php#language.types.string.details så det er dokumenteret.

Visse tekst funktioner bl.a. str* virker kun med single byte encoding.

Andre tekst funktioner bl.a. mb* virker også med multi byte encoding.

Dette er dokumenteret i dokumentationen for string (se link).

str* funktioner angiver at det tager string som argument. Og flere af dem har endda hyperlink til beskrivelsen af string.

Det burde være tilstrækkeligt.

Det er ikke specielt logisk at strenge i et sprog brugt til web apps skulle være i UTF-8 encoding bare fordi output er det. Intern og ekstern brug er forskellig. UTF-8 har nogle fordele som eksternt format p.g.a. ASCII kompabiliteten. Men UTF-8 er ikke særlig god til internt brug p.g.a. den variable længde - at finde et index er O(n) fremfor O(1). ASP, ASP.NET og Java EE bruger da også UTF-16.

Var det en fejl at PHP ikke fik unicode support for 17 år siden? Ja! Men det er baseret på hvad vi ved idag. Dengang var unicode ret ny og det var langtfra åbenlyst at unicode ville slå igennem.

Kan man ændre string til at være UTF-16 idag og derved få bedre unicode support? Nej! Det ville breake alt for meget eksisterende kode.

Det var så vidt jeg ved hvad der var planlagt for PHP 6 - og kompabilitets problemerne er grunden til at PHP 6 er udskudt på ubestemt tid.

Kunne man tilføje en ny widestring data type med tilhørende wcs( funktioner og L"..." literals? Ja! Det har andre sprog gjort (C/C++).

Vil man gøre det? Aner det ikke!
Avatar billede olebole Juniormester
10. oktober 2012 - 14:43 #17
Nej, det er efter min mening ikke tilstrækkeligt. Hvis der var tale om konsistens ville jeg måske være enig, men det er der ikke.

Lad os tage tilfældet med denne tråd: Jeg læser spørgsmålet og tænker: "Det må da være fordi, PHP ser strengen som bytes og tæller derefter".

Så får jeg tanken: "Der er da vist en streng-splitter-funktion, så man kunne tælle elementer i det resulterende array. Gad vide, om den er 'byte-safe'?".

Jeg hopper op til strengfunktionerne på php.net og finder str_split. Her finder jeg ingen 'disclaimers', men teksten i #5. Derfor tjekker jeg funktionen strlen, som spørgsmålet drejer sig om. Her finder jeg følgende, tydelige notice:

Note:

strlen() returns the number of bytes rather than the number of characters in a string.

Her ligger tanken jo snublende nær, at str_split på dette punkt adskiller sig - men det ville selvfølgelig forudsætte en passende konsistens, som ikke synes tilstede.

En eller anden i Zend synes at være af den opfattelse, at det er et stykke info, som fortjente at blive nævnt under den ene funktion. Enten har andre opdateret de øvrige strengfunktioner, eller også finder personen det - af for mig uransagelige årsager - ikke fundet det passende at bringe samme info dér.

"str* funktioner angiver at det tager string som argument. Og flere af dem har endda hyperlink til beskrivelsen af string."

Ja, jeg kan umiddelbart se to(!) med link til String: strlen og strtr. Den første har, som allerede nævnt, en 'disclaimer', og ved den sidste står tydeligt anført:

<?php
//In this form, strtr() does byte-by-byte translation
//Therefore, we are assuming a single-byte encoding here:
$addr = strtr($addr, "äåö", "aao");
?>

Hvis disse to deldokumentationer var udtryk for en konsistent holdning fra Zend, ville jeg også mene, at "Det burde være tilstrækkeligt". Men det er det ikke, og det er såmænd blot det, jeg efterlyser.

Jeg er helt med på de historiske årsager til, at PHP ikke i udgangspunktet fik Unicode support - og at det altid er svært, grænsende til umuligt, at ændre den slags, når et sprog først er blevet udbredt. Jeg er også opmærksom på, at utf-8 ikke er 'det perfekte' tegnsæt, og at det i andre sammenhænge giver andre problemer.

Min pointe er blot, at PHP's dokumentation på dette punkt ikke er tilstrækkelig konsistent. Enten bør man vælge at være eksplicit - eller også bør man lade være. Det er uhensigtsmæssigt at være det ved nogle funktioner, men ikke ved andre.

Er det tvingende nødvendigt? Det er der jo ikke meget, der er.

Vil det være mindre forvirrende for folk, der ønsker at lære PHP - og for folk, der har brug for et hurtigt opslag? Det ved jeg ikke objektivt, men jeg mener, der er god grund til at tro det.
Avatar billede arne_v Ekspert
10. oktober 2012 - 17:02 #18
Konsistens har aldrig vaeret PHP's staerke side.

PHP er klart bazaar og ikke cathedral.

Bare den kendsgerning at string funktionerne hedder xxxxxx, strxxx og str_xxx er inkonsistent.

Men saadan er det altsaa.

Folk der vil laere PHP boer klart laese om string om andre typer, saa de faar det basale paa plads.

Og jeg vil formode at folk der arbejder med PHP dagligt kan den slags.

Kan det vaere tricky for folk som kun arbejder med PHP en gang imellem og maaske har glemt lidt siden sidst? Ja da.

Men jeg synes ikke at det er specielt for PHP at man ikke repetere string koncepter under string funktioner. Java, .NET, standard C, standard C++ goer ikke. De eneste jeg kender som goer det er faktisk MS C (men det er ogsaa rigtigt grumset med str, wcs, mbs of tcs).
Avatar billede olebole Juniormester
10. oktober 2012 - 17:48 #19
Jeg arbejder dagligt med PHP, men har ikke brugt str_split i meget lang tid. Jeg tvivlede selv på, at den ville virke og slog den derfor op.

Jeg så ikke en 'disclaimer' og checkede strlen. Da jeg er vandt til PHP's håndtering af strenge, er lige den slags info ikke noget, jeg normalt kikker efter, når jeg bruger dokumentationen. Derfor gik jeg lidt naivt udfra, at når det stod ved den ene funktion, måtte den, det ikke stod ved, være 'utf-8-safe'.

Det mener jeg sådan set ikke - heller ikke ved efterrationalisering - er spor underligt. Sådan burde en dokumentation forventes at kunne bruges ... i min verden, that is  =)

"Men jeg synes ikke at det er specielt for PHP at man ikke repetere string koncepter under string funktioner. Java, .NET, standard C, standard C++ goer ikke. De eneste jeg kender som goer det er faktisk MS C (men det er ogsaa rigtigt grumset med str, wcs, mbs of tcs)."

Nej, det er ikke specielt, men én eller anden hos Zend har jo i hvertfald ment, det var hensigtsmæssigt at skrive ved to af String funktionerne.

Er det relevant for de to, må det også være det for resten. Er det ikke relevant for resten, burde det heller ikke være relevant for de to.

Det er lidt ligesom med bankrådgivere. De kan give råd - eller de kan give råd (som i 'gode råd' henholdsvis 'råddenskab'). Dokumentation bør give råd (læs: vejledning/overblik) ... ikke råd (læs: vildledning/forvirring)  *o)

Jeg ved godt, at en radikal forklaring lyder, at "Sådan er det jo". Ja, det er det jo - men mit argument er såmænd også bare, at det er ikke hensigtsmæssigt  =)
Avatar billede learner Praktikant
20. november 2014 - 10:18 #20
Tillader mig at lukke spørgsmålet
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Vi tilbyder markedets bedste kurser inden for webudvikling

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester



IT-JOB

IT & Co ApS

IT-tekniker

Vive - Det Nationale Forsknings- og Analysecenter for Velfærd

Erfaren datamanager med registerkompetencer

ALD Automotive Danmark A/S

Senior Software Engineer