13 svar
102 visningar
Mollyhej 499
Postad: 4 jan 18:03

omvandla till små bokstäver med svenska tecken

Hej jag gör ett program som bland annat ska omvandla ett ord med bokstäver till samma ord fast med små bokstäver och jag vill kunna behandla svenska bokstäver också (Å Ä Ö). 

Detta använder jag mig av i min Main funktion så det ska gälla över hela programmet

setlocale(LC_ALL, "sv_SE.UTF-8");

och detta är min funktion

// Detta är en funktion som gör alla bokstäver små
// Skrivet av: Molly Mähler Boije (mobo2400)
// Skapades: 04/01-2026, Uppdaterades: 04/01-2026
// Kurs: Introduktion till programmering, C++
// Uppgift: Projekt, Contacts

#include "kontakt.h"
#include <iostream>
#include <string>

std::string sma_bokstaver(std::string& ordet)
{
    std::string sma_bokstaver_ordet = "";

    for (unsigned char bokstav : ordet)
    {
        // Om bokstaven är mellan stora A till stora Z
        if (bokstav >= 'A' && bokstav <= 'Z')
        {
            bokstav = bokstav + 32; // gör stor bokstav till liten
            // Alternativt: bokstav = tolower(bokstav);
        }
        else
        {
            // Behåll redan små svenska tecken
            if (bokstav == 228 || bokstav == 229 || bokstav == 246)
            {
                bokstav = bokstav; 
            }

            // Konvertera stora svenska bokstäver till små
            if (bokstav == 196) // Ä -> ä
                bokstav = 228;

            if (bokstav == 197) // Å -> å
                bokstav = 229;

            if (bokstav == 214) // Ö -> ö
                bokstav = 246;
        }

        // Lägg till bokstaven i resultatsträngen
        sma_bokstaver_ordet += bokstav;
    }

    return sma_bokstaver_ordet;
}

men den funkar inte som den ska

Laguna 31846
Postad: 4 jan 18:20

Jag ser inte felet, men prova att lägga in en sats som skriver ut värdet på bokstav, t.ex. innan du testar mot A och Z . Då ser du om det faktiskt kommer 196 och sådant.

Bra att du postat läsbar kod.

Vad är det som inte fungerar?

D4NIEL 3381
Postad: 4 jan 23:32 Redigerad: 4 jan 23:41

Tänk på att i utf8 är en bokstav inte alltid 1 byte, ibland är det 2. Detta gäller åäö.

å = {0xc3, 0xa5} -> Å = {0xc3, 0x85}

sictransit 2968 – Livehjälpare
Postad: 4 jan 23:44 Redigerad: 4 jan 23:45

Stämmer fint! Ibland är de tre eller fyra också. Därför skriver man aldrig den här typen av funktioner själv, utan man använder färdiga bibliotek. Ja, förutom som övningsuppgifter då. Det är lärorikt. 

Laguna 31846
Postad: 5 jan 10:32

Eventuellt börjar programmet använda en annan kodning om du gör setlocale(LC_ALL, "sv_SE.ISO8859-1");

Men förmodligen måste du göra den inställningen i vad det nu är du använder för att kommunicera med programmet, konsolfönster eller något sådant.

Hur ser uppgiften ut? Att göra detta med ISO8859-1, som har en byte per tecken, är en intressant övning, men att göra det med UTF-8 är onödigt krångligt, tycker jag. Då borde övningen gå ut på att använda rätt standardfunktioner i stället.

Mollyhej 499
Postad: 5 jan 10:48

Jag ska försöka förklara kort vad det inte är som fungerar:

Jag har en kontakt-bok i en txt fil som jag läser in i en vektor med en egengjord struct för att lagra namn, adress, personnummer etc i en enda datatyp. En plats i vektorn är en hel struct, alltså en hel kontakt.

Jag vill nu söka igenom hela vektron efter en speciell kontakt och skriva ut dess information.

Först fixade jag så att det gick och söka efter en kontakt så länge man skrev exakt rätt, exempelvis om man ska söka efter "Eva Eriksson" så måste man skriva "Eva" och inte "eva". Men jag ville att det även skulle funka om man söker efter "eva".

Därför gör jag denna små bokstäver funktion. Funktionen funkar ifall ordet bara är skrivet med bokstäver mellan a-z, alltså funkar konverteringen fint mellan stora och små bokstäver här.

Programmet funkar även med Å Ä Ö samt å ä ö men endast om hela ordet skrivs korrekt. Exempelvis om man har en kontakt som bor på "Stamvägen" funkar det fint om man skriver exakt "Stamvägen". Men skriver man "stamvägen" funkar det inte, trots att ä redan är litet. Samma visa för "Östersund"; "Östersund" funkar "östersund" funkar inte.

Jag bifogar även min söka efter kontakt kod här nere för mer kontex. Så fort ett ord innehåller å, ä, ö/Å, Ä, Ö och inte skrivs exakt som det är lagrat så skickas -1 till min main funktion och texten "kontakt hittades inte" skrivs ut.

söka efter kontakt funktionen:

//detta är en funktion som ska söka efter en kontakt och hitta dess index
//skrivet av: molly mähler boije (mobo2400)
//skapades: 09/12-2025, uppdaterades: 31/12-2025
//kurs: introduktion till programmering, C++
//uppgift: projekt, contacts

#include"kontakt.h"
#include<iostream>
#include<string>
#include<vector>
#include<sstream>

int soka_efter_kontakt(std::string& borttagen_kontakt, std::vector<kontakt>& kontakt_vektor, int& start_sok_punkt)
{
    for(int index=start_sok_punkt; index<kontakt_vektor.size(); index++) //för alla index i hela vektorn
    {
       //delar upp kontakten för att undersöka ord för ord
       const kontakt& kontakt=kontakt_vektor[index]; //kopierar över kontakten vi är på
       std::string uppdelad_kontakt=kontakt.namn+" "+kontakt.adress+" "+kontakt.epost+" "+kontakt.telefonnummer+" "+kontakt.personnummer+" "+kontakt.ovrigt; //ser till att min kontakts information är uppdelad med mellanslag inför min string stream 
       std::string uppdelad_kontakt_sma_bokstaver=sma_bokstaver(uppdelad_kontakt); //gör alla boksäver små

       //delar upp borttagen_kontakt i ord för ord för att kunna söka på flera ord
       std::string borttagen_kontakt_sma_bokstaver=sma_bokstaver(borttagen_kontakt); //gör alla bokstäver små i dne borttagna kontakten
       std::stringstream borttagen_kontakt_uppdelare(borttagen_kontakt);
       std::string nyckelord;

       bool kontakt_hittad=1;

       while(borttagen_kontakt_uppdelare>>nyckelord) //medan vi läser av de enskilda orden (nyckelordet) från den borttagna kontakten
       {
            if(uppdelad_kontakt.find(nyckelord)==std::string::npos) //om vi inte hittar det sökta ordet. vad npos är och hur det funkar hittade jag här https://www.geeksforgeeks.org/cpp/stringnpos-in-c-with-examples/
            {   
                kontakt_hittad=0;
                break;
            }     
       }

       if(kontakt_hittad==1) //om kontakten hittades retunera indexet
       {
            return index;
       }
    }
    return -1; //retunerar -1 efter vi gått igenom hela vektorn och inte hittar kontakten
}
Mollyhej 499
Postad: 5 jan 10:54

Själva uppgiften säger inte explisivt att man ska göra så här som jag gör det kanske finns ett mycket enklare sätt som jag inte vet om, jag använde till en börjar tolower som är enklare man funkar inte för svenska tecken...

Detta är uppgiften och det är väll egentligen jag som tänker att jag vill göra alla bokstäver små för att kunna söka på både "eva" och "Eva" men ändå få upp den sökta kontakten

4.1 Grunduppgift

Skapa en grundläggande kontaktbok där man kan lagra och sedan ta fram information om kontakter.Den information som (minst) ska kunna lagras är

• namn,

• (post-) adress,

• e-postadress,

• telefonnummer,

• födelsedag och

• övrigt

Gränssnittet ska fungera på följande sätt. Användaren ska kunna välja vad denne vill göra, exempelvislägga till en kontakt eller hitta telefonnumret för en given kontakt. Det finns flera sätt att implementeradetta, exempelvis:

Att ha en meny där användaren får välja genom att mata in ett tal motsvarande ett av menyalternativen.

Avsluta ska vara ett av alternativen.

• Att ha ett kommandodrivet gränssnitt där användaren ger kommandon för vad som ska göras.

Den funktionalitet som ska finnas är

• att lägga till en kontakt,

• att ta bort en kontakt,

• att söka efter en kontakt.

Kontaktboken ska sparas i en fil så att den inte försvinner mellan körningarna av programmet. (Det voreen ganska meningslös kontaktbok om den inte kommer ihåg kontakterna längre än dess användare.)

För denna uppgift skall du använda minst en container.

4.2 Extrauppgift C

Programmet ska inte kunna kraschas (mjuk eller hård krasch) av användaren. Exempelvis, om användarenmatar in fel typ av data ska programmet be om nytt data istället för att avslutas (hård krasch) eller omkontaktbokens fil är korrupt, då ska programmet tala om for användaren att något är fel och attkontaktboken inte kunde laddas. Mjuk krasch sker när fel inmatning inte avslutar programmet helt utankörningen fortsätter, exempelvis samma (fel)meddelande skrivs ut flera gånger i en loop.

4.3 Extrauppgift A

Vid sökning ska programmet söka efter söksträngen i alla fält för kontakterna. Matchningen ska också varaokänslig för om versaler eller gemener används. Exempelvis om jag söker efter strängen ada, då skaprogrammet lista kontakterna Ada Arvidsson, Adam Allsing och Cecilia Adamsdotter. Eftersom det ska sökai alla fält ska det även lista alla kontakter som bor på Ada Lovelacesväg eller som har Adamstorp som postort.

Laguna 31846
Postad: 5 jan 12:17

tolower borde fungera om du har satt locale rätt, men frågan är som andra har påpekat huruvida man kan hantera strängarna en byte i taget.

Om du bara vill lösa problemet och inte skriva koden själv (vilket inte är trivialt), prova att googla ”icu UnicodeString foldCase indexOf c++”. Då borde du hitta något användbart som fungerar för UTF-8. 

Sitter lite tight till och med mobilen just nu. 

Laguna 31846
Postad: 5 jan 14:07

Jag hittade ett förslag här: https://stackoverflow.com/questions/26074090/iterating-through-a-utf-8-string-in-c11

(i svaret). Jag ville kopiera hit koden, men det blev väldigt konstigt formaterat.

 

Det fungerar när jag provar. Folk har gjort lättanvända hjälpfunktioner också, men jag har inte testat dem.

D4NIEL 3381
Postad: 5 jan 17:42 Redigerad: 5 jan 17:46

Ett alternativ är att använda wchar_t / wstring.

#include <iostream>

int main () {
    setlocale (LC_ALL, "sv_SE.UTF-8");
    std::wstring ws = L"Hällå wörld";
    for (wchar_t& c : ws) c = towupper (c); // <ccwtype> via <iostream>
    std::wcout << ws;
}
D4NIEL 3381
Postad: 5 jan 17:50

Vill man använda UTF8 och loopa över bytes kan man göra ungefär så här:

#include <print>

void fix_se_utf8 (std::string& s) {
    for (int j = 0; j < s.size ()-1; ++j)
        if ((unsigned char)s[j] == 0xc3) {
            if      ((unsigned char)s[j + 1] == 0xa5) s[j + 1] = 0x85;  // å -> Å
            else if ((unsigned char)s[j + 1] == 0xa4) s[j + 1] = 0x84;  // ä -> Ä
            else if ((unsigned char)s[j + 1] == 0xb6) s[j + 1] = 0x96;  // ö -> Ö
        }
}

int main () {
    std::string str{"häLLå wörld"};
    
    std::print ("   {}  | ", str);
    for (auto& ch : str) std::print ("{:2x} ", ch);
    std::print ("\n");

    for (auto& ch : str) ch = std::toupper ((unsigned char)ch);
    fix_se_utf8 (str);

    std::print ("   {}  | ", str);
    for (auto& ch : str) std::print ("{:2x} ", ch);
}

Vilket ger 

   häLLå wörld  | 68 c3 a4 4c 4c c3 a5 20 77 c3 b6 72 6c 64
   HÄLLÅ WÖRLD  | 48 c3 84 4c 4c c3 85 20 57 c3 96 52 4c 44
thedifference 581
Postad: 5 jan 18:28

Förstår jag detta rätt? Det ser konstigt ut.

       bool kontakt_hittad=1;

       while(borttagen_kontakt_uppdelare>>nyckelord) //medan vi läser av de enskilda orden (nyckelordet) från den borttagna kontakten
       {
            if(uppdelad_kontakt.find(nyckelord)==std::string::npos) //om vi inte hittar det sökta ordet. vad npos är och hur det funkar hittade jag här https://www.geeksforgeeks.org/cpp/stringnpos-in-c-with-examples/
            {   
                kontakt_hittad=0;
                break;
            }     
       }

1. Utgå från att kontakten faktiskt är hittad
2. Loopa över kontaktens uppgifter
3. Om någon uppgift inte stämmer in på sökningen, säg att kontakten inte är hittad och avbryt loopen

Det här skulle ju betyda att det enda sättet att hitta en kontakt är om varenda deluppgift innehåller sökordet.

Svara
Close