Stränghantering

Inledning

Vi ska nu ta oss en närmare titt på variabeltypen string. Strängar är variabler som kan hålla textinformation. Dessa är inte begränsade i längd på något sätt utan kan växa efter behov och anpassas. Eftersom all inmatning tolkas som strängar så kan det vara bra att kunna manipulera, validera och bearbeta strängar på olika vis.

Innan vi går vidare måste vi nog nämna något kort om ASCII och unicode (UTF-8). ASCII och unicode är två olika teckenuppsättningar som används i operativsystem, filer/filformat etc. En teckenuppsättning bestämmer vilka tecken du kan använda. I äldre system var det 7-bitars eller 8-bitars ASCII som gällde. Då kunde de flesta tecken i västerländska språk användas. Speciella tecken som å,ä,ö hade ingen given plats i de gamla teckentabellerna, för att inte tala om japanska och kinsesiska tecken.

Med tiden insåg man att det behövdes en teckenuppsättning som rymmer alla tecken i världen. Dags för unicode (förenklat sett 16-bitar per tecken)! Nyare versioner av Windows använder unicode likaså programmeringsspråket C#. Detta betyder att vi kan använda å,ä,ö i t.ex. variabelnamn utan att få kompileringsfel. Koden kan skickas till andra i världen och den ser precis likadan ut hos dem.

En sträng kan vara null, dvs. inte ha något värde, vara tom vilket är samma sak som "" eller innehålla tecken. Varje tecken är av typen char och kan nås genom att indexera strängen med []-tecken. Vi börjar med ett första exempel som undersöker en inmatad sträng och skriver ut varje tecken för sig.

Exempel - Bokstäver i en sträng

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Stränghantering
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.Write("Mata in en text: ");
            string inmatat = Console.ReadLine();

            Console.WriteLine("Testen du matade in var " + inmatat.Length + " tecken lång.");

            for (int i = 0; i < inmatat.Length; i++)
            {
                Console.WriteLine("index " + i + " är " + inmatat[i]);
            }
        }
    }
}

bild

Observera att ren text ALLTID måste omges av "-tecken i programkoden. Detta har du säkert använt redan för att skriva ut fasta texter med t.ex. Console.WriteLine() (rad 12 i exemplet ovan).

Nu ska vi titta på lite ihopbyggnad av strängar. För att slå ihop strängar används tecknet +. Från matematiken har vi lärt oss att + står för addition och fungerar med tal. Inom programmering kan tecknet + användas av olika datatyper och ge andra resultat än summor. Vi tar ett exempel till.

Exempel - Slå ihop strängar

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Stränghantering
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.Write("Mata in ditt förnamn: ");
            string namn = Console.ReadLine();

            Console.Write("Mata in ditt efternamn: ");
            string efternamn = Console.ReadLine();

            string fras = "Hej " + namn + " " + efternamn;
            Console.WriteLine(fras);
        }
    }
}

bild

Detta var ett exempel på att slå ihop text från två strängar i en ny sträng (rad 18 i exemplet ovan).

En viktig grundregel är att om du använder tecknet + tillsammans med minst en variabel av typen string så blir resultatet en string. Alla övriga variabler som inte är av typen string i uttrycket kommer att behandlas som strängar via metoden .ToString(). I första exemplet ("Bokstäver i en sträng") på rad 19 finns ett lysande exempel. Här blandas variabeln i in i ett utryck och fastän i är av typen int så blir alltså resultatet en string som kan skrivas ut.

Ändra enstaka tecken i en sträng

Det kan vara svårt att som nybörjare modifiera en strängs tecken då de i C# är skrivskyddade om man försöker sig på att göra:


            string text = "Detta är en liten bit text";
            text[4] = 'A';  //Går ej!

Så går inte detta då strängar är immutable, dvs. de kan inte ändras utan att skapas om.

Vill man t.ex. byta ut alla små "e" mot stora "E" så kan man göra följande:

Exempel - Byta tecken

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Stränghantering
{
    class Program
    {
        static void Main(string[] args)
        {
            string text = "Detta är en liten bit text";
            //Gör om texten till en array av char
            char[] array = text.ToCharArray();

            //Bearbeta tecknen
            for (int i = 0; i < array.Length; i++)
            {
                if (array[i] == 'e')
                    array[i] = 'E';
            }

            //Skapa om strängen
            text = new string(array);
            Console.WriteLine(text);
        }
    }
}

bild

Vill man ändra och bygga om strängar så rekommenderas klassen StringBuilder. Den är speciellt anpassad för att just bygga om strängar och ger också en prestandaförbättring för bearbetaning av större text. Mer om denna klass i en kommande artikel.

Jämförelser mellan strängar

Hur gör vi nu om vi vill jämföra text med annan text? Vi tar ett exempel där vi matar in någon text och undersöker om det vi skrev var "kebab".


string inmatat = Console.ReadLine();
if(inmatat == "kebab")
{
     Console.WriteLine("Rätt svarat!");
}

Okej, problemet med detta är att du måste skriva EXAKT "kebab" annars tolkar programmet svaret fel, d v s du kan inte blanda stora och små bokstäver. Nu ska vi lära oss lite av strängarnas egenskaper. Om du skriver ditt variabelnamn följt av en punkt så får du upp en lista på inbyggda metoder i strängarna (se bild nedan).

bild

Här ska vi nu titta på två metoder, ToLower() och ToUpper(). Dessa metoder tar texten i den aktuella strängen och gör alla bokstäver antingen stora (upper) eller små (lower). Med hjälp av dessa funktioner så kan vi nu jämföra text utan att ta hänsyn till stora och små bokstäver, se exempel:


string inmatat = Console.ReadLine();
if(inmatat.ToLower() == "kebab")
{
     Console.WriteLine("Rätt svarat!");
}

eller


string inmatat = Console.ReadLine();
if(inmatat.ToUpper() == "KEBAB")
{
     Console.WriteLine("Rätt svarat!");
}

Båda exemplen ovan fungerar likadant. I det övre så används ToLower() på variabeln inmatat och i det nedre exemplet används ToUpper(). Viktigt att notera är att värdet i variabeln inmatat aldrig ändras utan inmatat.ToUpper() skapar en ny sträng där alla bokstäver gjorts stora.

Specialtecken i strängar

Det finns en rad tecken som är svåra att skriva i en sträng, t.ex. tecknet för ny rad, tecknet för TAB eller tecknet " som markerar början/slut på en sträng.

För att lösa detta så har i princip alla programmeringsspråk infört något som kallas för en escape-sekvens eller escape sequence på engelska. En escape-sekvens börjar med tecknet \ följt av ett annat tecken. Det finns en rad fördefinierade escape-sekvenser i C#. En del sekvenser har en mer historisk innebörd från den tiden då datorer bara hade teckenterminaler. Det närmsta vi kommer terminalfönster idag inom .NET är genom ett Console Application.

\' Enkelt citationstecken, behövas för att deklarera en char med detta tecken
\" Dubbelt citationstecken, använbart i strängar
\\ Backslash (eller omvänt snedtecken), behövs eftersom ett enkelt backslash inleder en escape-sekvens
\0 Unicode tecken 0
\a Alert, används sällan
\b Backspace (eller baksteg), används sällan
\f Form feed (sidmatning), används sällan
\n Ny rad
\r Carriage return (eller vagnsretur)
\t Horisontell tab
\v Vertikal tab
\uxxxx Unicode värde angivet hexadecimal (xxxx)
Exempel - Specialtecken

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Stränghantering
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Fil C:\\sökväg\\test.txt");
            Console.WriteLine("ett\r\ntvå\r\ntre");
            Console.WriteLine("ett\ttvå\ttre");
            Console.WriteLine("Citat \"Att vara..\"");
        }
    }
}

bild

Värt att nämna är att på rad 13 används \r\n för att skapa en radbrytning. I Console Applications räcker det med \n för radbrytning men försöker du dig på samma sak i ett grafisk program så blir du tvungen att använda \r\n för ny rad. \r\n är unicode tecknet för ny rad vilket är anledningen till att endast \n ej fungerar i t.ex. Windows Forms.

Ordagranna strängar

Det finns en mycket praktiskt sätt att ange strängar på som på engelska kallas för verbatim strings, vilket skulle kunna översättas till "ordagranna" strängar. Dessa strängar skriv som:

@"text"

När tecknet @ används så ignoreras alla escape-sekvenser och du kan skriva följande:

Exempel - Ordagranna strängar

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Stränghantering
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine(@"Fil C:\sökväg\test.txt");
            Console.WriteLine(@"ett
två
tre");
            Console.WriteLine(@"Citat ""Att vara..""");
        }
    }
}

bild

Med ordagranna strängar kan du göra riktiga nyradsbrytningar utan att få syntaxfel. Notera att citationstecknet måste anges två gånger.

Detta enkla knep kan underlätta mycket om du ska deklarera sökvägar, html eller liknande.

ToString()

Alla variabler/datatyper och objekt i C# har en metod som heter ToString(). Denna metod kan du alltid använda när du ska översätta en variabel (som inte är av typen string) till string. I vissa fall måste du kunna använda den. Ett kort exempel är i följande fall:


double ettTal = 3.1415;
string enText = ettTal.ToString();

I exemplet ovan vill jag helt enkelt översätta variabeln ettTal till string. Kanske vill jag skriva ut talet på skärmen men saken är den att i detta läget måste jag använda ToString() för att sköta översättningen. Blandar jag olika datortyper tillsammans med en bit text, t.ex:


string minstring = "Hej hopp. " + minint + "," + mindouble + "," + minbool;
..

Då kommer metoden ToString() automatiskt att användas i översättningen av minint, mindouble, minbool utan att du behöver ange det i koden.

Formattera strängar

Ett enkelt sätt att formatera strängar är att ange {n} (n är ett heltal) i en sträng och sedan använda string.Format(). Vi tar ett exempel:

Exempel - Formattering

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Stränghantering
{
    class Program
    {
        static void Main(string[] args)
        {
            string format = @"Det var en gång en kille som hette {0}. {0} hade
för vana att programmera {1}. Det tyckte {0} var kul!";

            string text = string.Format(format, "Sven", "C#");
            Console.WriteLine(text);
        }
    }
}

bild

På rad 15 formatteras strängen. Alla {0} i strängen format ersätts av parametern "Sven" och alla {1} ersätts av parametern "C#"

Denna sort byggnation av strängar ger oftare en renare kod, speciellt om man arbetar med långa strängar t.ex. html eller liknande. En annan fördel såklar är att format-strängen kan användas igen i något annat sammanhang fast då med andra värden på {0} och {1}.

Det finns ingen begränsning direkt på hur många parametrar som kan användas. Du kan t.ex. ha från {0} till .. {47} i en o samma sträng.

Ytterligare en fördel med denna sorts formattering är att du kan t.ex. formattera antalet decimaler på en double eller ange ett datum på ett annat sätt. Nästa exempel visar på olika avrudningar av ett o samma tal.

Exempel - Formattering av tal

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Stränghantering
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Decimaler:\t1\t2\t3");
            string format = "\t\t{0:0.0}\t{0:0.00}\t{0:0.000}";
            string text = string.Format(format, Math.PI);
            Console.WriteLine(text);
        }
    }
}

bild

Det är främst decimaltal och DateTime objekt som kan formatteras snabbt och enkelt med string.Format(). Vi kommer inte att fördjupa oss i alla detaljer. Det finns tabeller på nätet som i detalj visar alla olika sorters formatteringsinställningar för vanliga datatyper.

Strängformattering kan även användas direkt tillsammans med Console.WriteLine() och Console.Write(). T.ex:


            Console.WriteLine("\t\t{0:0.0}\t{0:0.00}\t{0:0.000}", Math.PI);
		..

Söka i strängar

En mycket vanlig uppgift är att avgöra om en sträng innehåller specifika ord eller kanske är utformad på ett visst sätt. Börjar vi närma oss dessa funderingar så rekommenderar vi reguljära uttryck.

Reguljära uttryck är en "språk i språket". Det är ett speciellt scriptspråk för att söka/validera eller hantera strängar som är otroligt kraftfullt. Oftast fungerar reguljära uttryck i t.ex. javaScript, Java, Perl ,PHP eller C# på liknande sätt men det finns små avvikelser mellan språken.

Vi kommer i denna artikel att nöja oss med att informera dig om att reguljära uttryck finns och att de är bra. För mer information se artikeln Reguljära uttryck

Lämna ett svar

Din e-postadress kommer inte publiceras. Obligatoriska fält är märkta *

Scroll to top