En lathund för stränghantering för asp/vb
Förord
För att kunna skriva effektiva program måste man ofta på olika sätt manipulera det indata man får på olika sätt, t e x plocka ut delar av en text, lägga ihop strängar, jämföra strängar och så vidare. Det här dokumentet kommer att handla om hur man i Visual Basic 6 kan jobba med strängar på olika sätt. Jag kommer bygga upp det hela kring de funktioner för stränghantering som finns inbyggda i Visual Basic och på vissa ställen lägga in små tips som man kan använda för att underlätta jobbet. Varje funktion kommer förklaras med minst ett exempel. Jag bifogar även en ASCII-tabell också för enkelhetens skull. Ett tips är att på Dos-prompten skriva charmap.exe - då kommer en lista upp som du kan använda dig av. Trevlig läsning!Innehåll
»»
»
»
»
»
»
»
»
»
»
»
»
»
»
»
»
»
»
1. Lite små fakta innan vi börjar med funktionerna
1.1. $De allra flesta funktioner som tas upp i detta dokument har två varianter. Antingen skriver man dem med $ på sluter, tex. str$, eller utan, tex str.
Skillnaden är att om du utesluter dollartecknet så returnerar det i själva verket en variant istället för en string. Detta spelar kanske inte så stor roll i små system, men i det långa loppet så sparar man mycket tid på att använda dollartecknet. Jag kommer i fortsättningen att INTE skriva ut dollartecknet på någon funktion, men rekommenderar att det används!
1.2. Konkatenering
Konkatenering är ett fint ord för att lägga ihop strängar.
Ett exempel på konkatenering är
Ex.
Dim sPejg As String
Dim sPejg2 As String
sPejg = "Lena"
sPejg2 = " är glad"
sPejg = sPejg & sPejg2
MsgBox sPejg 'Blir "Lena är glad"
Viktigt att tänka på när man håller på att lägga ihop strängar är skillnaden på & och +.
Titta på de två fallen:
Dim sPejg As Double
Dim sPejg2 As Double
Dim spejg3 As String
sPejg = 1
sPejg2 = 2
spejg3 = sPejg & sPejg2
MsgBox spejg3 ' Blir 12
spejg3 = sPejg + sPejg2
MsgBox spejg3 ' Blir 3
Observera alltså att om man lägger ihop två tal till en sträng så måste man tänka på om man vill ADDERA dem eller KONKATENERA dem.
1.3. Att jämföra strängar
Det finns en mängd så kallade aritmetiska operatörer som används när man ska göra jämförelser.
Dessa är
= är lika med
< är mindre än
<= är mindre än eller lika med
> är större än
>= är större än eller lika med
<> är skilt ifrån
2. Asc och Chr
Asc och Chr är två funktioner som används för att konvertera tecken från ASCII format till vanlig text och vice versa. Varje alfanumeriskt tecken motsvaras av ett ASCII-tecken (se längst bak för tabell). Asc(string) Konverterar medskickat tecken till asciikod
Chr(nummer) Konverterar medskickad ascii-kod till tecken
Ex:
sPejgan = Asc("A") ' Blir 65
sPejgan = Asc("a") ' Blir 97
sPejgan = Asc("Apple") ' Blir 65, tar alltså bara första bokstaven!
sPejgan = Chr(65) ' Blir "A"
sPejgan = Chr(97) ' Blir "a"
sPejgan = Chr(34) ' Blir " " ", dvs så ett så kallat citationstecken
Detta innebär att följande två uttryck ger samma resultat i en textruta, nämligen "Lena"
Text1.Text = """Lena"""
Text2.Text = Chr(34) & "Lena" & Chr(34)
3. Left, Mid & Right
Det finns tre mycket användbara funktioner för att på ett enkelt sätt plocka ur delar ur en sträng. Left(string, length)
Right(string, length)
Båda de ovanstående funktionerna tar 2 argument, string och length. String är strängen som det skall plockas delar ur och length är hur många tecken som skall plockas ut. Skillnaden på left och right är att left plockar från början av strängen och right plockar bakifrån.
Ex:
sPejgan = "Pellesoft är en mycket trevlig sajt"
msgbox left(sPejgan, 9). ' Blir Pellesoft.
Motsvarande kan alltså, fast baklänges, göras med right:
sPejgan = "Pellesoft är en mycket trevlig sajt"
msgbox right(sPejgan, 12). ' Blir trevlig sajt.
Mid(string, start[, length])
Som ni ser så tar funktionen mid emot ett extra argument, start. Denna funktion används om man vill plocka delar ur en sträng, men inte nödvändigtvis från början eller slutet.
Ex.
sPejgan = "Pellesoft är en mycket trevlig sajt"
msgbox mid(sPejgan, 11,5). ' Blir är en.
4. Len
En annan mycket trevlig funktion är Len, som räknar ut antalet tecken i en sträng.Len(string)
Denna funktion tar endast emot ett argument, string. String är i detta fallet den sträng/variabel som vi vill veta längden på. Detta kan tex vara texten i en textbox (text1.text) eller en variabel.
Ex.
sPejgan = "Pellesoft"
Msgbox len(sPejgan) ' Blir 9.
5. Val
Val är en funktion som man använder när man vill göra om en textsträng i form av ett tal, tex värdet i en textbox, till ett tal. Ex:
sPejgan = 4 + Val("34") ' Blir 4 + 34 = 38
sPejgan = Val(Text1.Text) ' Blir värdet i text1-rutans text
Val läser från början av strängen och översätter siffra för siffra tills vi stöter på ett icke numeriskt tecken.
Ex:
SPejgan = Val("345Pejgan") ' Blir 345
6. Str
Str används för att konvertera andra datatyper till strängar. Funktionen tar inte emot några andra argument än det som skall konverteras till en sträng:Ex:
sPejgan = Str(459) ' Blir " 459"
sPejgan = Str(-459.65) ' Blir "-459.65"
sPejgan = Str(Date) ' Blir "2001-04-02"
sPejgan = Str(Time) ' Blir "17:08:05"
En nackdel med str är att den reserverar en plats i strängen för ett eventuellt minustecken (för negativa tal). Det innebär att strängen blir ett tecken längre än vad som faktiskt finns där om talet är positivt. Tex. blir talet 34 tre tecken långt eftersom den sparas som " 34". Istället kan man då använda….
7. Format
För att kunna ha full koll på strängarna kan man använda Format. I sin allra enklaste form fungerar format på samma sätt som Str med undantag för att den inte sparar plats för det där minustecknet som inte finns. Konverterar man talet 34 till en sträng med funktionen Format så blir strängen bara två tecken lång.
sText = Format(12) ' Blir "12"
Förutom att fungera som Str fast lite annorlunda så kan man göra massor med format. Man kan formatera en sträng nästan hur som helst nämligen!
Format(expression[, format[, firstdayofweek[, firstweekofyear]]])
Argumentet expression är alltså obligatoriskt, men undantar man de andra argumenten så fungerar format som jag skrev ovan.
De andra argumenten, format, firstdayofweek och firstweekofyear
Firstdayofweek talar om vilken som är den första dagen på veckan. Kan kanske verka onödigt, om man inte tänker på att i vissa länder så anses söndag vara starten på veckan!
vbUseSystem 0 Använder NLS API inställningen.
VbSunday 1 Söndag (default)
vbMonday 2 Måndag
vbTuesday 3 Tisdag
vbWednesday 4 Onsdag
vbThursday 5 Torsdag
vbFriday 6 Fredag
vbSaturday 7 Lördag
Firstweekofyear talar om vilken vecka som skall anses vara årets första. Denna används för att tala om ifall vi ska anse att årets första vecka är den vecka som innehåller 1:a jan, om det är den vecka som har minst 4 dagar på nya året eller om vi ska ta den första HELA veckan på året.
vbUseSystem 0 Use NLS API setting.
vbFirstJan1 1 Start with week in which January 1 occurs (default).
vbFirstFourDays 2 Start with the first week that has at least four days in the year.
vbFirstFullWeek 3 Start with the first full week of the year.
Det sista argumentet är kanske det roligaste: format.
Med denna kan man tala om hur den sträng vi får tillbaka ska se ut.
Det finns en rad fördefinierade format att använda, här kommer några exempel.
Se hjälpen eller annan litteratur för en komplett lista:
Formatsträng Betydelse
"General Number" Talet blir som det står utan formatering
"Currency" Omvandlar talet till valuta med tusentalsavdelare om det behövs, negativa tal innanför parenteser och två siffror efter kommatecknet. Lägger även till ändelsen "kr". Tex: 1 000,30 kr.
"Fixed" Skapar en sträng av angivet tal med två siffror efter ett kommatecken och åtminstone en siffra före kommatecknet.
"Standard" Visar siffrorna med tusentalsavdelare och två decimaler.
"Percent" Skapar en sträng där talet som ska konverteras och formateras multipliceras med 100, lägger till två decimaler och avslutar strängen med ett procenttecken (%).
"Scientific" Presenterar talet med hjälp av exponenter. Till exempel: 1,00E+03
"Yes/No" Tilldelar mottagande variabeln strängen "No" om talet som ska formateras är lika med noll, annars får strängen värdet "Yes".
"True/False" Tilldelar mottagande variabeln strängen "False" om talet som ska formateras är lika med noll, annars får strängen värdet "True".
"On/Off" Tilldelar mottagande variabeln strängen "Off" om talet som ska formateras är lika med noll, annars får strängen värdet "On".
Förutom de som tagits upp ovan kan man skapa egna format med hjälp av vissa formattecken, tex dessa:
Formattecken Används för:
0 Siffra. Finns det ingen siffra på den platsen i talet som ska formateras skrivs det dit en nolla.
# Siffra. Finns det ingen siffra på den platsen i talet som ska formateras skrivs det ingenting.
% Multiplicerar talet med hundra och lägger till ett procenttecken på angiven position.
@ eller & Tecken.
< Formaterar om en sträng till att bara innehålla små bokstäver.
> Formaterar om en sträng till att enbart innehålla stora bokstäver.
Här är lite exempel:
sPejgan = Format(1, "Percent") 'sPejgan = "100,00%"
sPejgan = Format(1, "ddddd") 'sPejgan = "1899-12-31"
sPejgan = Format(08112211,"00-000000") 'sPejgan = "08-112211"
sPejgan = Format(1,"Currency") ' sPejgan = "1,00 kr"
sPejgan = Format(1,"Yes/No") 'sPejgan = "Yes"
8. String & Space
String används för att tex. skapa en sträng bestående av en upprepning av samma tecken.String(number, character)
Funktionen tar emot två argument, number och character. Number är antal tecken och character är vilket tecken som det skall innehålla.
Ex:
sPejgan = string(15,"A"). ' Blir "AAAAAAAAAAAAAAA".
Observera att oavsett hur många tecken du skriver i character, så tar den bara det första:
sPejgan = String(5, "A") ' Blir "AAAAA".
sPejgan = String(5, "AQZRTERE") ' Blir "AAAAA".
SPejgan = Right("000000" & 250, 6) ' Blir "000250"
Man kan även använda sig av ascii-koden direkt:
sPejgan = String(5, 42) ' Blir "*****".
Funktionen Space gör samma sak, med skillnaden att det alltid blir blanksteg
Space(number)
Ex.
SPejgan = Space(5) 'Blir " "
9. Ltrim,rtrim och trim
Dessa tre funktioner används för att sålla bort blanksteg i början, slutet eller både och av en sträng.LTrim(string) Tar bort blanksteg i början av en sträng
RTrim(string) Tar bort blanksteg i slutet av en sträng
Trim(string) Tar bort blanksteg både i början och i slutet av en sträng
Ex:
Spejgan = " Lena ".
Ltrim(sPejgan) ' Blir "Lena "
Rtrim(sPejgan) ' Blir " Lena"
Trim(sPejgan) ' Blir "Lena"
10. StrReverse
En lite rolig funktion som finns är möjligheten att vända en sträng baklänges, strReverse.StrReverse(string1)
String1 är alltså strängen som skall bli baklänges.
Ex:
sPejgan = "PEJGAN".
SPejgan = StrReverse(sPejgan) ' Blir "NAGJEP"
11. Ucase och Lcase
Strängjämförelser i Visual Basic är känslig för stora och små bokstäver. Det innebär att nedanstående kodsnutt kommer skriva ut "TRUE" på skärmen:
If "anna" > "Anna" Then
MsgBox "TRUE"
End If
Detta beror på att ASCII-koden för "a" är större än ASCII-koden för "A". (Det finns iof olika sätt att jämföra strängar, av vilka en del inte är känsliga på detta sättet, de tar vi upp senare!) Ett bra sätt för att undvika missförstånd är att använda sig av funktionerna Ucase och Lcase.
Ucase(string) Konverterar värdet i string till STORA BOKSTÄVER
Lcase(string) Konverterar värdet i string till små bokstäver
Ex:
sPejgan = "Pejgan"
sPejg = "pejgan"
Om man jämför dessa:
If sPejgan = sPejg then
…
Endif
Så får man inte en träff eftersom "P" inte är samma sak som "p".
Om man däremot använder
If Ucase(sPejgan) = Ucase(sPejg) then
…
Endif
Så får man träff.
12. Instr och InstrRev
Instr används för att leta reda på om en viss text finns i en sträng. InStr([start, ]string1, string2[, compare])
Denna funktion är lite mer komplicerad än de vi tagit upp tidigare. Funktionen tar emot en rad argument: start är på vilken position sökningen skall starta, string1 är den sträng vi ska söka i, string2 är det vi ska söka efter och compare är ett frivilligt argument som talar om vilken typ av sökning vi ska göra. Detta behöver inte skickas med om vi inte ska göra någon speciell typ av sökning.
Typerna är följande:
Konstant Värde Kort beskrivning
VbUseCompareOption -1 Använder sig av en inställning som heter OptionCompare som man kan sätta i en modul. Default är binär jämförelse
VbBinaryCompare 0 Gör en binär jämförelse: A < B < E < Z < a < b < e < z < À < Ê < Ø < à < ê < ø
VbTextCompare 1 Gör en jämförelse ungefär som den ovan men med nedanstående skillnad (A=a) < ( À=à) < (B=b) < (E=e) < (Ê=ê) < (Z=z) < (Ø=ø)
VbDatabaseCompare 2 Kan bara användas med Microsoft Access. Bygger på information som finns i databasen.
Resultat
Om InStr returnerar
String1 inte innehåller något värde 0
String1 innehåller Null Null
String2 inte innehåller något värde start
String2 innehåller Null Null
String2 inte hittas 0
String2 hittas i string1 Den position där string2 hittades.
Start > string2 0
Ex:
sPejgan = "Pellesoft är en mycket trevlig sajt"
sSok = "Pelle"
msgbox instr(1,sPejgan,sSok) ' Resultatet blir 1
sSok = "sajt"
msgbox instr(1,sPejgan,sSok) ' Resultatet blir 32
sSok = "Pejgan"
msgbox instr(1,sPejgan,sSok) ' Resultatet blir 0
ssok = "pellesoft"
msgBox InStr(1, sPejgan, ssok, vbBinaryCompare) ' Resultatet blir 0
ssok = "pellesoft"
MsgBox InStr(1, sPejgan, ssok, vbTextCompare) ' Resultatet blir 1
Motsvarande funktion finns för att söka från slutet av en sträng:
InstrRev(string1, string2[, start[, compare]])
Argumenten som står inom [] är frivilliga, dvs de behöver inte skickas med. Start är på vilken position vi ska börja leta baklänges från, om vi inte skickar med något börjar den söka från slutet. Compare är vilken typ av sökning vi ska göra, se ovan.
Ex:
sPejgan = "Pellesoft är en mycket trevlig sajt"
sSok = "Pelle"
msgbox instr(1,sPejgan,sSok) ' Resultatet blir 1
ssok = "pellesoft"
msgBox InStr(1, sPejgan, ssok, vbBinaryCompare) ' Resultatet blir 0
ssok = "pellesoft"
MsgBox InStr(1, sPejgan, ssok, vbTextCompare) ' Resultatet blir 1
Observera att vi fortfarande får position räknar från början!
Skillnaden är att om vi har en sträng där söktexten finns med flera gånger så får vi den SISTA positionen där den finns
Ex:
SPejgan = "Pejgan är snäll, Pejgan är glad"
SSok = "Pejgan"
Msgbox instrRev(sPejgan,sSok) ' Resultatet blir 18, inte 1
ssok = "Pejgan"
MsgBox InStrRev(sPejgan, ssok, 7) ' Resultatet blir 1
13. Strcomp
Så kan vi väl titta på ett lite enklare(?) sätt att jämföra strängar: Strcomp.Strcomp(string1,string2,compare)
String1 & string2 är strängar vi jämför, compare är sättet vi jämför (se instr ovan).
Ex:
Dim sPejgan As String
Dim spejg2 As String
sPejgan = "Lena"
spejg2 = "Thomas"
Select Case StrComp(sPejgan, spejg2, vbTextCompare)
Case 0
' spejgan = spejg2
Case -1
' spejgan < spejg2
Case 1
'spejgan > spejg2
End Select
Dvs: Om sträng1 = sträng2 så får vi 0
Om sträng1 är mindre än sträng2 så får vi -1
Om sträng1 är större än sträng2 så får vi 1
På detta sätt får man en enkel men effektiv jämförelse!
14. Replace
Replace är en funktion som precis det den säger. Den byter ut tecken i en sträng mot något annat.Replace(expression, find, replacewith[, start[, count[, compare]]])
Expression är strängen vi ska söka i, find är det vi söker efter, replacewith det vi vill sätta dit istället. Till detta finns 3 frivilliga argument: start är vart i strängen vi ska börja leta(default är från starten). Count är hur många träffar vi ska byta ut (default är alla). Compare är vilken typ av jämförelse vi ska göra, se instr ovan.
Ex:
sPejgan = "Pellesoft är en mycket trevlig sajt med många trevliga människor"
sPejgan = Replace(sPejgan, "trevlig", "mysig", 1, 1, vbTextCompare)
MsgBox sPejgan
' Blir "Pellesoft är en mycket mysig sajt med många
trevliga människor"
sPejgan = Replace(sPejgan, "trevlig", "mysig", 1)
MsgBox sPejgan
' Blir "Pellesoft är en mycket mysig sajt med många
mysiga människor"
OBS! För att förstå användandet av nedanstående funktioner, filter, join & split, krävs en viss förståelse av begreppet arrayer. Detta tas INTE upp i denna "kurs".
15. Filter
Ett annat sätt att söka, ungefär som instr och instrrev ovan, är filterFilter söker igenom en array efter en viss sträng och returnerar en endimensionell array med de värden som stämmer eller inte stämmer beroende på vad man skickar med för värden i include.
Filter(InputStrings, Value[, Include[, Compare]])
Inputstrings är en array med värden att söka i, value är vad vi ska söka efter, include sätter man till TRUE om man vill söka efter alla värden som matchar value och false om man vill ha alla som inte matchar. Compare anger vilket sätt man vill söka på, se instr ovan.
Ex:
Dim aPejg() As String
Dim bPejg() As String
Dim sPejgan As String
sPejgan = "Pellesoft,Altavista,Evreka,Aftonbladet,VbOnline"
aPejg() = Split(sPejgan, ",")
bPejg() = Filter(aPejg(), "v", True, vbTextCompare)
For i = 0 To 3
MsgBox bPejg(i)
Next ' Får träffarna Altavista,Evreka,Vbonline
16. Split och Join
Split är en funktion som används för att ta ut delar ur en lista separerad med tex komma.
Split(expression[, delimiter[, count[, compare]]])
Funktionen tar emot en mängd argument: expression är strängen som vi ska dela på, delimiter är vilket tecken som fungerar som "avskiljare". De frivilliga argumenten är count, som talar om hur många delar av strängen vi ska returnera, samt compare som fungerar på samma sätt som i instr ovan. Om man inte skickar med en count så returnerar den hela listan uppdelad. I detta fall lägger man dem i en array för att sedan hantera den vidare därifrån.
Ex:
Dim aPejg() As String
Dim sPejgan As String
sPejgan = "Lena,Maria,Susanne,Nyström"
aPejg() = Split(sPejgan, ",")
MsgBox aPejg(0) ' Blir Lena
Tvärtemot split fungerar funktionen join. Den tar alltså delar av en array och lägger ihop den i en sträng, separerad med valfritt skiljetecken.
Join(list[, delimiter])
List är namnet på den array vi ska använda och delimiter är det tecken vi ska använda som skiljetecken. Vi använder oss av samma exempel som ovan:
sPejgan = Join(aPejg, ";")
MsgBox sPejgan ' Blir Lena;Maria;Susanne;Nyström
17. "Jokrar" eller Wildcards
Detta kanske inte faller in direkt under vanlig stränghantering, men är praktiska när man tex gör utsökningar ur databaser. Jokrar kan användas när vi inte vet exakt vad vi söker efter. Det finns en rad jokrar som fungerar på olika sätt:
? Vilket tecken som helst
* 0, 1 eller flera tecken
# Vilket nummer som helst
[charlist] Vilket tecken som helst som finns i charlist
[!charlist] Vilket tecken som helst som INTE finns i charlist.
Ett känt exempel på detta är när man söker efter filer som man inte vet vad de heter, man vet bara vilken filtyp det är tex:
*.txt, visar alla filer som slutar på .txt
Pejgan*.txt visar alla filer vars namn börjar på Pejgan och har filtypen .txt , ex Pegan1.txt, Pejgan2.txt, PejganP.txt, PejganPejgan.txt
Pejgan?.txt däremot visar bara de filer som börjar på Pejgan, sedan har 1 tecken till i namnet och som slutar på .txt, ex Pejgan1.txt, Pejgan2.txt, PejganP.txt men INTE PejganPejgan.txt
Pejgan#.txt fungerar som Pejgan?.txt fast det måste vara en siffra. Pejgan1.txt går bra, men PejganP.txt går inte bra.
Bilaga: Ascii-tabell (Windows default)
0 32 [space] 64 @ 96 `
1 33 ! 65 A 97 a
2 34 " 66 B 98 b
3 35 # 67 C 99 c
4 36 $ 68 D 100 d
5 37 % 69 E 101 e
6 38 & 70 F 102 f
7 39 ' 71 G 103 g
8 * * 40 ( 72 H 104 h
9 * * 41 ) 73 I 105 i
10 * * 42 * 74 J 106 j
11 43 + 75 K 107 k
12 44 , 76 L 108 l
13 * * 45 - 77 M 109 m
14 46 . 78 N 110 n
15 47 / 79 O 111 o
16 48 0 80 P 112 p
17 49 1 81 Q 113 q
18 50 2 82 R 114 r
19 51 3 83 S 115 s
20 52 4 84 T 116 t
21 53 5 85 U 117 u
22 54 6 86 V 118 v
23 55 7 87 W 119 w
24 56 8 88 X 120 x
25 57 9 89 Y 121 y
26 58 : 90 Z 122 z
27 59 ; 91 [ 123 {
28 60 < 92 \ 124 |
29 61 = 93 ] 125 }
30 62 > 94 ^ 126 ~
31 63 ? 95 _ 127
128 €160 [space] 192 À 224 à
129 €161 ¡ 193 Á 225 á
130 €162 ¢ 194 Â 226 â
131 €163 £ 195 Ã 227 ã
132 €164 ¤ 196 Ä 228 ä
133 €165 ¥ 197 Å 229 å
134 €166 ¦ 198 Æ 230 æ
135 €167 § 199 Ç 231 ç
136 €168 ¨ 200 È 232 è
137 €169 © 201 É 233 é
138 €170 ª 202 Ê 234 ê
139 €171 " 203 Ë 235 ë
140 €172 204 Ì 236 ì
141 €173 205 Í 237 í
142 €174 ® 206 Î 238 î
143 €175 ¯ 207 Ï 239 ï
144 €176 ° 208 Ð 240 ð
145 €177 ± 209 Ñ 241 ñ
146 €178 ² 210 Ò 242 ò
147 €179 ³ 211 Ó 243 ó
148 €180 ´ 212 Ô 244 ô
149 €181 µ 213 Õ 245 õ
150 €182 214 Ö 246 ö
151 €183 · 215 × 247 ÷
152 €184 ¸ 216 Ø 248 ø
153 €185 ¹ 217 Ù 249 ù
154 €186 º 218 Ú 250 ú
155 €187 " 219 Û 251 û
156 €188 ¼ 220 Ü 252 ü
157 €189 ½ 221 Ý 253 ý
158 €190 ¾ 222 Þ 254 þ
159 €191 ¿ 223 ß 255
Var denna artikeln användbar?
Om du gör någon intressant (eller kanske något konstigt fel) på grund av detta material så skicka gärna det med ett mail eller bifoga en länk till mig så presenterar jag detta som ytterligare exempelfiler för kursen. Om detta innehållet är felaktigt eller du lärt dig fler finesser så skriv gärna en rad eller varför inte en egen kurs baserat på dina erfarenheter. Sänd gärna in dina tips till denna artikel./Lena Nyström aka Pejgan
0 Kommentarer