C++ läsa svenska tecken Linux

Permalänk
Medlem

C++ läsa svenska tecken Linux

Hej!

Jag läst på en tråd att detta skulle funka här på sweC

#include <iostream> #include <locale> using namespace std; int main() { locale swedish("swedish"); locale::global(swedish); char a = 'å'; char b = 'ä'; char c = 'ö'; cout << a << b << c << endl; return 0; }

Jag får iaf bara att å,ä, ö inte funger får följande:

tmp.cpp:10:11: warning: multi-character character constant [-Wmultichar] char a = 'å'; ^ . . .

Va är problemet? enligt en kompis så fungera det kanon bra också (i windows miljö).

Sedan har jag googlat lite och kommit fram till att det kanske är en lösning men ej:

#include <iostream> #include <locale> using namespace std; int main() { locale swedish("sv_SE.UTF-8"); locale::global(swedish); char a = 'å'; char b = 'ä'; char c = 'ö'; cout << a << b << c << endl; return 0; }

Har även testa locale swedish("sv_SE.UFT8");
Har även testa med wchar_t istället för char.

Någon som kan berätta hur jag kan lösa detta i linux?
Tack för svar!

Visa signatur

Смерть -это решение всех проблем. Нет человека - нет проблемы
Comp1: Ubuntu 16.04 Comp2: Arch Linux
Comp3: Ubuntu Server 16.04 Comp4: Centos 6.5
Comp5: Linux mint 16 Comp6: Raspberry pi (olika OS hela tiden)
Phone: Motorola Google Nexus 6

Permalänk
Medlem
Permalänk
Hedersmedlem

Jag vet inte vad ditt slutmål är vilket gör det lite vanskligt att ge tips, men för att få ditt exempel att fungera med en minimal förändring så bör du kunna använda wchar_t och wcout enligt:

#include <iostream> #include <locale> using namespace std; int main() { locale swedish("swedish"); locale::global(swedish); wchar_t a = L'å'; wchar_t b = L'ä'; wchar_t c = L'ö'; wcout << a << b << c << endl; return 0; }

Det finns mer att säga och läsa om `wchar_t` och multibyte-tecken, så ditt inlärningsmaterial kanske har mer info om hur det är tänkt att ni ska hantera det på den nivå ni är i er kurs.

Jag rekommenderar också att inte dra in hela namnrymden `std` globalt, utan i stället kvalificera anropen när de sker, eller eventuellt dra in vissa objekt explicit med exempelvis `using std::wcout;` och `using std::endl;`. Det är bra att redan från start behöva tänka på varifrån funktioner och konstanter kommer.

Visa signatur

Nu med kortare användarnamn, men fortfarande bedövande långa inlägg.

Permalänk
Medlem

Grundproblemet: En char är en byte (signed eller unsigned) medans 'å' representeras av flera bytes, därav multibytecharacter-varningen. Du kan helt enkelt inte lagra representationen av 'å' i en char.

Visa signatur

Citera mig för svar.
Arch Linux

Permalänk
Medlem
Skrivet av Dimman:

Grundproblemet: En char är en byte (signed eller unsigned) medans 'å' representeras av flera bytes, därav multibytecharacter-varningen. Du kan helt enkelt inte lagra representationen av 'å' i en char.

Det där beror väl helt på encoding? Kör man Windows-1252 ASCII så finns å ä och ö representerade i singlebytes. Förutsatt att inputten hanteras som korrekt ascii med korrekt code-page borde det fungera fint.

Visa signatur

Fractal Design Define R5 | MSI Z97-GD65 Gaming | MSI Geforce GTX 970 Gaming 4G | Intel i5 4690k | Cooler Master Hyper 212 EVO | EVGA Supernova G2 750W | 2x8GB Corsair Vengeance Low Profile DDR3 1600Mhz | Samsung 850 EVO | Seagate 1TB SATA3.5

Permalänk
Medlem
Skrivet av Tobberoth:

Det där beror väl helt på encoding? Kör man Windows-1252 ASCII så finns å ä och ö representerade i singlebytes. Förutsatt att inputten hanteras som korrekt ascii med korrekt code-page borde det fungera fint.

Ja visst. "Representationen" syftar till hans encoding i.o.m. att han fick multibytecharacter-varningar:)

Visa signatur

Citera mig för svar.
Arch Linux

Permalänk
Medlem

I C har jag använt följande

#include <locale.h> setlocale(LC_ALL, "");

Sedan kört med wchar_t

Men är medveten om att C++ inte är exakt samma sak.
Försöker även lära mig C++ så är intresserad av lösningen på problemet.

Edit: http://stackoverflow.com/questions/16944750/c-unicode-charact...

#include <clocale> #include <iostream> using namespace std; int main() { setlocale(LC_ALL, ""); wcout << L'\u2780'; return 0; }

Permalänk
Medlem

Hmm, att sätta LC_ALL till tom sträng borde innebära samma sak som att systemet använder din default locale eller det som är satt i LC_xxx beroende på vad som efterfrågas. I normalfallet borde du då få UTF-8, men såvida du inte har en shellvariabel som overridar LC_ALL borde det kommandot vara en "NOP".

Visa signatur

Citera mig för svar.
Arch Linux

Permalänk
Medlem

Jo, fast om man inte gör det så verkar åtminstone C ge "C locale".

Edit: Hittade lite om skillnader mellan C och C++ locale
http://stdcxx.apache.org/doc/stdlibug/24-3.html

std::locale::global(std::locale(""));

Permalänk
Medlem

Det jag ska göra är att skaffa statistik till det svenska språket hur vanliga olika bokstäver är i formerna var för sig, 2 bokstäver i kombination och 3 bokstäver i kombination. Detta är till en kryptografi kurs vi läser just nu i skolan.

Så jag har en stor text skriven i svenska som jag ska läsa in och göra dessa olika saker på.

Visa signatur

Смерть -это решение всех проблем. Нет человека - нет проблемы
Comp1: Ubuntu 16.04 Comp2: Arch Linux
Comp3: Ubuntu Server 16.04 Comp4: Centos 6.5
Comp5: Linux mint 16 Comp6: Raspberry pi (olika OS hela tiden)
Phone: Motorola Google Nexus 6

Permalänk
Medlem

Är texten skapad i Windows för att sedan analyseras på Linux så brukar det tillkomma ytterligare ett problem - att avkoda windows-teckensnittet när det gäller å, ä, ö. Dessutom brukar radbrytningarna se olika ut på Windows och Linux textfiler.

Permalänk
Entusiast
Skrivet av Mejan:

Det jag ska göra är att skaffa statistik till det svenska språket hur vanliga olika bokstäver är i formerna var för sig, 2 bokstäver i kombination och 3 bokstäver i kombination. Detta är till en kryptografi kurs vi läser just nu i skolan.

Så jag har en stor text skriven i svenska som jag ska läsa in och göra dessa olika saker på.

Du har flera saker att tänka på:

  • textfilens teckenkodning (Viktigt om svenska tecken är inblandade):
    * Windows 1252
    * CP437, CP850
    * ISO-8859-1, ISO-8859-10, ISO-8859-15
    * Unicode, UTF-8 (Detta är att föredra)
    ...och radmatningsformatet:
    * DOS/Windows (CR+LF)
    * Unix (LF)

  • När textfilen läses in är det bra att tänka på hur innehållet lagras i RAM-minnet.
    Förslag: Spara den stora textfilen i unicode/UTF-8 format.
    Använd wfopen_s med mode "rt, ccs=UTF-8".
    Se kodexempel 1. (Skamlöst stulet från nätet )

  • När resultat skall skrivas ut på skärmen.
    Se kodexempel 2. (Skamlöst stulet från nätet )

Kodexempel 1: (Inläsning av UTF-8 kodad fil)

#include <locale> #include <codecvt> #include <string> #include <fstream> #include <cstdlib> int main() { const std::locale empty_locale = std::locale::empty(); typedef std::codecvt_utf8<wchar_t> converter_type; const converter_type* converter = new converter_type; const std::locale utf8_locale = std::locale(empty_locale, converter); std::wifstream stream(L"test.txt"); stream.imbue(utf8_locale); std::wstring line; std::getline(stream, line); std::system("pause"); }

Kodexempel 2: (Utskrift av UTF-8 kodade textsträngar)

#include <iostream> #include <io.h> #include <fcntl.h> int wmain(int argc, wchar_t* argv[]) { _setmode(_fileno(stdout), _O_U16TEXT); std::wcout << L"Testing unicode -- English -- Ελληνικά -- Español." << std::endl; }

...och glöm inte: Terminalen/konsolen som resultatet skrivs ut till också kan visa UTF-8/Unicode. Borde vara standard, men det händer att det inte är konfigurerat.

EDIT/Tillägg:
Exemplena är tänkta för Windows/.NET, men principen är densamma, och samma tre punkter att tänka på: Inläsning, bearbetning/lagrin i RAM, utmatning. Alla tre stegen skall ha rätt teckenkodning.
Sedan är det bra att man även sparar sina källkodsfiler i Unicode/UTF-8 format, så eliminerar man ännu en huvudvärk ifall strängar definieras/ skrivs ut direkt.

Visa signatur

Bästa programmen till Linux - v2.0
Linux-guide: Val av grafisk miljö. (Att välja distribution).
-
Everyone should have a SGoC in their systems (SGoC: SysGhost on a Chip)

Permalänk
Medlem

Just ja, programmet iconv kan omvandla mellan olika teckenformat. Löste någon uppgift där en fil skapad i windows skulle läsas av genom att först konvertera till UTF-8 med iconv.

Permalänk
Medlem

Ja, rent teknist sätt får jag läsa in vilken svensk text som helst så länge den är lång nog för att få korrekt statistik på bokstavs förekomster osv i svenska (fick bibeln i txt format av en kompis så jag tänkte den är lång nog). Sedan hade jag denna diskussion men en annan vän om olika standarder i Windows och Linux men jag trodde att jag kunde kopiera koden från .txt till en ny txt (skapad på Linux med UTF-8) men så simpelt var de kanske inte med andra ord.

Visa signatur

Смерть -это решение всех проблем. Нет человека - нет проблемы
Comp1: Ubuntu 16.04 Comp2: Arch Linux
Comp3: Ubuntu Server 16.04 Comp4: Centos 6.5
Comp5: Linux mint 16 Comp6: Raspberry pi (olika OS hela tiden)
Phone: Motorola Google Nexus 6

Permalänk
Medlem

Sedan rent minnes hantering har jag alltid tänkt mig en std::map som styr upp de hela där bokstaven är key:n och value är antalet uppkomsten av bokstaven. Men de borde funka med en string också, jag vill ju helst inte behöva köra getline() men de borde väl gå med typ stream >> wchar_t eller liknade eller är jag helt ute och cyklar?

Visa signatur

Смерть -это решение всех проблем. Нет человека - нет проблемы
Comp1: Ubuntu 16.04 Comp2: Arch Linux
Comp3: Ubuntu Server 16.04 Comp4: Centos 6.5
Comp5: Linux mint 16 Comp6: Raspberry pi (olika OS hela tiden)
Phone: Motorola Google Nexus 6

Permalänk

Jag skulle också köra med en map-baserad lösning (tecken -> #förekomster) och det kan du göra för två- och tre-teckens-kombinationerna också. För tvåteckensfrekvenserna kan ha en map från tecken till samma map som i första fallet. Då använder du de två senaste tecknen, det första för att hitta i vilken map du skall använda för nästa tecken.

Det blir lite pyssel att hantera white space och interpunktion om man bryr sig om det i frekvensanalysen.

Permalänk
Medlem

Ja, space kommer ju att används. Då jag ska skriva ut en random text från min frekvens analys.

Visa signatur

Смерть -это решение всех проблем. Нет человека - нет проблемы
Comp1: Ubuntu 16.04 Comp2: Arch Linux
Comp3: Ubuntu Server 16.04 Comp4: Centos 6.5
Comp5: Linux mint 16 Comp6: Raspberry pi (olika OS hela tiden)
Phone: Motorola Google Nexus 6