Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

Linux reverse string polskie znaki polska czcionka

Ostatnio zmodyfikowano 2022-06-30 16:29
Autor Wiadomość
OfEl
Temat założony przez niniejszego użytkownika
Linux reverse string polskie znaki polska czcionka
» 2022-06-30 09:55:10
jeden z waszych użytkowników zauważył, że przy wypisywaniu string wspak nie pokazują się polskie znaki
reverse string polskie znaki polska czcionka
użytkownik @pekfos odpowiedział, że do opcji kompilatora wystarczy dopisać -fexec-charset=852
i wszystko fajnie tylko nie działa to pod kontrolą systemu linux
Moje pytanie brzmi jak to można rozwiązać pod unix/linux
Podejmowałem różna próby zamieniając napis na bity czy na kod ASCI z marnym efektem

std::locale{"pl_PL.utf-8"}

C/C++
#include <iostream>
#include <cstring>
#include <bitset>
#include <cstdlib>
#include <vector>
#include <algorithm>
#include <climits>

using namespace std;

int main()
{
   
cout << std::locale( "" ).name();
   
cout << "\n";
   
std::string rex( "król" );
   
std::string rev;
   
std::copy( rex.crbegin(), rex.crend(), std::back_inserter( rev ) );
   
for( const auto & ch: rex ) std::cout << ch;
   
   
std::cout << '\n';
   
for( const auto & ch: rev ) std::cout << ch;
   
   
std::cout << "\n\n";
   
   
return 0;
}

C/C++
#include <iostream>
#include <cstring>
#include <bitset>
#include <cstdlib>
#include <vector>
#include <algorithm>
#include <climits>

using namespace std;

template < typename T >
std::ostream & operator <<( std::ostream & os, const std::vector < T > & v ) {
   
for( T const & i: v ) {
       
os << i << " ";
   
}
   
return os;
}
template < size_t N >
std::string bitset_to_string( std::bitset < N > bits ) {
   
static_assert( N % CHAR_BIT == 0 );
   
std::string result;
   
for( size_t p = 0; p < N / CHAR_BIT; ++p ) {
       
char next = 0;
       
for( size_t r = 0; r < CHAR_BIT; ++r ) {
           
size_t index = N -( CHAR_BIT * p ) - r - 1;
           
size_t pos = CHAR_BIT - r - 1;
           
if( bits[ index ] )
               
 next |=( 1 << pos );
           
       
}
       
result.push_back( next );
   
}
   
return result;
}
int main()
{
   
std::string rex = "król";
   
vector < bitset < 8 >> v;
   
cout << rex << "\n";
   
for( std::size_t i = 0; i < rex.length(); ++i ) {
       
v.push_back( std::bitset < 8 >( rex[ i ] ) );
       
std::cout << std::bitset < 8 >( rex[ i ] ) << ' ';
   
}
   
cout << "\n\n";
   
std::reverse( v.begin(), v.end() );
   
cout << v << '\n';
   
   
for( const auto & el: v ) {
       
cout << bitset_to_string( el ) << " ";
   
}
   
cout << '\n';
   
return 0;
}

napisałem też w RUST
jedno rozwiązanie działa pod unix/linux/windows
link_do_online_kompilatorow
compile_rust_online

C/C++
use std::io;

fn main() {
   
let rex = "król";
   
println !( "{}", rex );
   
println !( "{}", rex.chars().rev().collect::< String >() );
   
io::stdin().read_line( & mut String::new() ).unwrap();
}

Może ktoś wie jak to zrobili czarodzieje z RUST.
Bardzo chętnie uzupełniłbym swoją wiedzę
Proszę się też nie śpieszyć z odpowiedzią
Z góry serdecznie dziękuję za odpowiedź.

wystarczy, przy założeniu że jeden znak to jeden bajt.
czy może mi to ktoś wyłożyć łopatologicznie lub wskazać materiały lub hasła pod jakimi mam szukać




P-179578
DejaVu
» 2022-06-30 10:34:39
Przekonwertuj std::string na std::wstring i rób reverse na std::wstring.
P-179579
OfEl
Temat założony przez niniejszego użytkownika
» 2022-06-30 16:08:00
znalazłem nawet coś u was Unicode w WinAPI ale to wszystko pod windows
i na stackoverflow i tam jest odnośnik do geeksforgeeks i tam jest coś na The MIT License (MIT), ale z tym będę się musiał dopiero zmierzyć
P-179580
DejaVu
» 2022-06-30 16:13:28
Generalnie Twój problem to taki, że w UTF-8 polski znak jest reprezentowany de-facto przez dwa znaki. Jak odwracasz 'std::string' to w praktyce odwracasz kolejność bajtów, ponieważ metoda nie posiada logiki do interpretacji, że litera zajmuje więcej niż jeden bajt. Problem ten rozwiąże Ci przykładowo std::wstring, ponieważ wchar_t zajmuje od 2 do 4 bajtów pamięci (w zależności od kompilatora i bibliotek) i tym samym rozwiązuje problem obliczenia chociażby poprawnej długości tekstu lub też wyciągania pojedynczych liter, odwracania tekstu itp.

C/C++
std::string tekst1 = "król"; //tu zostanie zapisany UTF-8 lub inne kodowanie w zależności od tego jak zapiszesz plik (pod Linuxem prawie zawsze jest to UTF-8). (długość tekstu = 5 znaków dla UTF-8, 4 znaki dla ISO...)
std::wstring tekst2 = L"król"; // tu zostanie zapisany tekst jako Unicode (długość tekstu = 4 znaki zawsze)
P-179581
OfEl
Temat założony przez niniejszego użytkownika
» 2022-06-30 16:27:17
Administrator @DejaVu problem rozwiązany dziękuję za wyjaśnienie i naprowadzenie
Ekspert C++ @pekfos dziękuję za wyjaśnienie i podany przykład

I found the solution on the website riptutorial Conversion to std::wstring
C/C++
#include <iostream>
#include <cstring>
#include <codecvt>
#include <locale>
#include <algorithm>

using namespace std;

using convert_t = std::codecvt_utf8 < wchar_t >;
std::wstring_convert < convert_t, wchar_t > strconverter;

std::string to_string( std::wstring wstr )
{
   
return strconverter.to_bytes( wstr );
}

std::wstring to_wstring( std::string str )
{
   
return strconverter.from_bytes( str );
}


int main()
{
   
std::string rex = "król";
   
cout << rex << '\n';
   
std::wstring input_wstr = to_wstring( rex );
   
wcout << input_wstr << '\n';
   
std::reverse( input_wstr.begin(), input_wstr.end() );
   
cout << to_string( input_wstr ) << "\n";
   
return 0;
}
P-179582
pekfos
» 2022-06-30 16:29:02
wystarczy, przy założeniu że jeden znak to jeden bajt.
czy może mi to ktoś wyłożyć łopatologicznie lub wskazać materiały lub hasła pod jakimi mam szukać
To się odnosiło do kodu źródłowego. "wystarczy dopisać -fexec-charset=852" żeby spełnić te założenie na GCC i konsoli Windowsowej w typowej polskiej konfiguracji.

Na linuksie jest łatwiej, możesz pisać w UTF-8 na konsolę i jak nie masz czegoś skonfigurowanego po swojemu, to powinno zadziałać. Ale UTF-8 jest kodowaniem zmiennej długości i nie możesz zrobić std::reverse() na std::string. std::wstring typowo używa UTF-16, co też jest kodowaniem zmiennej długości, ale dla większości znaków jedna wartość odpowiada jednemu znakowi.
C/C++
#include <iostream>
#include <locale>
#include <codecvt>


int main()
{
   
std::string str = "zażółć gęślą jaźń";
   
std::cout << str << '\n';
   
std::cout << "źle: " << std::string( str.rbegin(), str.rend() ) << '\n';
   
   
// Konwersje z C++11
   
typedef std::wstring_convert < std::codecvt_utf8 < wchar_t >> Converter;
   
std::wstring wstr = Converter().from_bytes( str );
   
std::cout << Converter().to_bytes( std::wstring( wstr.rbegin(), wstr.rend() ) ) << '\n';
}
P-179583
« 1 »
  Strona 1 z 1