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

Wczytywanie polskich znaków z pliku.

Ostatnio zmodyfikowano 2016-05-11 19:01
Autor Wiadomość
pepe450
Temat założony przez niniejszego użytkownika
Wczytywanie polskich znaków z pliku.
» 2016-05-11 00:47:48
Witam mam problem z polskimi znakami wczytywanymi z pliku.
Program gdy dostanie plik bez polskich znaków działa prawidłowo ale gdy w pliku są polskie znaki jest problem jak to rozwiązać?
Pisałem w Visual Studio.
C/C++
#include"Tekst.h"
int main()
{
    Tekst T( "dane.txt" );
    T.analyze();
    T.sort();
    T.save();
    system( "pause" );
    return 0;
}
C/C++
#pragma once
#include<iostream>
#include<fstream>
#include<string>
#include<cctype>
#include<utility>
using namespace std;
class Tekst
{
    string name_of_file;
    enum
    {
        size = 26
    };
    pair < char, int > Litera[ size ];
public:
    Tekst() { };
    Tekst( string name );
    ~Tekst();
    void analyze();
    void sort();
    void show();
    void save();
};
C/C++
#include "Tekst.h"
Tekst::Tekst( std::string name )
    : name_of_file( name )
{
    char z = 'a';
    for( int i = 0; i < size; i++, z++ )
    {
        Litera[ i ].first = z;
        Litera[ i ].second = 0;
    }
}
Tekst::~Tekst()
{
   
}
void Tekst::analyze()
{
    ifstream file;
    file.open( name_of_file.c_str() );
    if( !file.is_open() )
    {
        cout << "Nie udalo sie otworzyc pliku o nazwie: " << name_of_file << endl;
        system( "pause" );
        exit( EXIT_FAILURE );
    }
    char znak;
    while( file >> znak )
    {
        if( isalpha( znak ) )
        {
            znak = tolower( znak );
            Litera[ znak - 97 ].second++;
        }
    }
}
void Tekst::sort()
{
    for( int j = 0; j < size - 1; j++ )
    for( int i = 0; i < size - 1; i++ )
    if( Litera[ i ].second < Litera[ i + 1 ].second )
    {
        swap( Litera[ i ], Litera[ i + 1 ] );
    }
}
void Tekst::show()
{
    for( auto i: Litera )
         cout << i.first << " " << i.second << endl;
   
}
void Tekst::save()
{
    ofstream file;
    string name = name_of_file + " - analiza";
    file.open( name.c_str() );
    if( !file.is_open() )
    {
        cout << "Nie udalo sie otworzyc pliku o nazwie: " << name_of_file << endl;
        cout << "Byla to proba zapisu do pliku" << endl;
        system( "pause" );
        exit( EXIT_FAILURE );
    }
    for( auto i: Litera )
    {
        file << i.first << " " << i.second << endl;
    }
}
P-148102
Matix8741
Wchar rozwiązaniem ?
» 2016-05-11 07:34:10
Nie jestem pewien czy to rozwiąże problem ale zamień wszystkie
char
 na
wchar_t
. Mam nadzieję, że jeszcze dobrze pamiętam.
P-148104
carlosmay
» 2016-05-11 11:05:47
Obsługa polskich znaków z plikiem binarnym

Nie jestem pewien czy to rozwiąże problem ale zamień wszystkie
char
 na
wchar_t
a do tego:
* ustawić polską stronę kodową dla strumieni, np. strm.imbue(std::locale("Polish_poland.852");
* std::wstring
P-148108
j23
» 2016-05-11 11:07:42
Żeby funkcje takie jak isalpha i tolower działały poprawnie z polskimi znakami diakrytycznymi, powinieneś odpowiednio ustawić locale funkcją setlocale:

C/C++
setlocale( LC_CTYPE, ".1250" ); // 1250 to strona kodowa znaków zapisanych w pliku (oczywiście może być inna)
...

while( file >> znak )
{
    if( isalpha(( unsigned char ) znak ) )
    {
        znak = tolower(( unsigned char ) znak );
        Litera[ znak - 97 ].second++;
    }
    ...

Wersja C++'owa:
C/C++
std::locale loc( ".1250" );
...

while( file >> znak )
{
    if( isalpha( znak, loc ) )
    {
        znak = tolower( znak, loc );
        Litera[ znak - 97 ].second++;
    }
    ...
P-148109
pepe450
Temat założony przez niniejszego użytkownika
» 2016-05-11 15:08:13
Podmieniłem string na wstring oraz char na wchar_t.
Ale nie wiem w którym miejscu mam ustawić locate i na jakie konkretne elementy.
Ustawiłem np. file.imbue(locale("Polish_poland.852")); to VS akceptuje ale np już to strm.imbue(std::locale("Polish_poland.852")); podkreśla.
Mój kod aktualnie wygląda tak:
https://gist.github.com​/anonymous​/be83d40789e43b6ee360fa6f27b02aed
P-148115
carlosmay
» 2016-05-11 15:30:41
C/C++
wchar_t z = L'a';

strm - ogólnie strumień. Np:

C/C++
std::wcout.imbue( std::locale( kod strony ) );
Wszystkie strumienie, w których masz zamiar korzystać z szerokich znaków trzeba ustawić na polski.

<locale> - info na temat lokalizmów
Wyszukaj także info o
std::wcin
,
std::wcout
,
std::wcerr
.
P-148116
j23
» 2016-05-11 19:01:59
Jeśli używasz znaków szerokich, wtedy nie isalpha, tylko iswalpha, nie tolower tylko towlower, i nie ifstream tylko wifstream.

Tak jak pisałem wcześniej: dla funkcji z biblioteki C musisz ustawić locale za pomocą funkcji setlocale. Ustawienie locale tylko strumieniowi file nie załatwi sprawy. Dlatego lepiej zrobić to w 100% w C++:
C/C++
void Tekst::Analyze()
{
    wifstream file;
   
    file.imbue( locale( "Polish_poland.1250" ) );
    wstring namefile = name_of_file + L".txt";
   
    file.open( namefile.c_str() );
   
    if( !file.is_open() )
    {
        wcout << L"Nie udalo sie otworzyc pliku o nazwie: " << name_of_file << L'\n';
       
        system( "pause" );
        exit( EXIT_FAILURE );
    }
   
    wchar_t znak;
   
    while( file >> znak )
    {
        if( isalpha( znak, file.getloc() ) ) // <--- funkcja z <locale> a nie z <ctype.h>
        {
            znak = tolower( znak, file.getloc() ); // <--- jw.
            //Alfabet[znak - 97].second++;  <--- w przypadku unikodu takie obliczanie indeksu jest niepoprawne, użyj std::map
        }
    }
}
P-148121
« 1 »
  Strona 1 z 1