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
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?
Tänk på att i utf8 är en bokstav inte alltid 1 byte, ibland är det 2. Detta gäller åäö.
å = {0xc3, 0xa5} -> Å = {0xc3, 0x85}
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.
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.
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
}
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.
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.
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.
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;
}
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
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.