Czytanie znaków z pliku

Czytanie znaków z pliku
0

Hej,

Mam mały prosty programik i problem ze sczytywaniem znaków.
Program ma zliczać ilość wystąpienia znaku ó w kolejnych liniach w pliku z kodowaniem Utf-8, ale go nie widzi.

Już różne pomysły były wprowadzane, ale żaden z nich nie doprowadził do oczekiwanego rezultatu.

Kopiuj
int main(){

    int max, i = 0, o = 0;
    char znak;

    ifstream plik("es-es.txt");

    plik >> noskipws;

// max liczba lini w pliku
    max = 6;
//tablica przechowujaca liczbe szukanego znaku w lini n
    int * T;
    T = new int[max];
    for(int l = 0; l<max;l++)
    {
        T[l]=0;
    }

    i=0;
    while (plik >> znak)
    {
        if( znak == '\n')
            ++i;
        else if( znak == 'ó' )
        {
            ++o;
            T[i]+=1;
        }
    }

    for (int l=0; l<max; l++)
    {
        cout << T[l] << "\t";
    }

    delete T;
}
edytowany 1x, ostatnio: Rev
RE
używaj znaczników &lt;code /&gt; do oznaczania kodu źródłowego
RE
Moderator
  • Rejestracja:około 18 lat
  • Ostatnio:około rok
1

ó w UTF-8 kodowany jest jako dwa bajty: c3 b3. Nie zmieści się przez to to ó do zmiennej typu char. Spokojnie natomiast możesz szukać tych dwóch następujących po sobie bajtów. W poprawnie skonstruowanym UTF-8 ten zestaw na pewno będzie oznaczał twoją szukaną literę.

edytowany 1x, ostatnio: Rev
Shalom
  • Rejestracja:około 21 lat
  • Ostatnio:prawie 3 lata
  • Lokalizacja:Space: the final frontier
  • Postów:26433
0

char nie przechowa ci znaku UTF-8


"Nie brookliński most, ale przemienić w jasny, nowy dzień najsmutniejszą noc - to jest dopiero coś!"
RE
Moderator
  • Rejestracja:około 18 lat
  • Ostatnio:około rok
1

A od czasów C++11 istnieje obsługa UTF-8 w samej bibliotece standardowej.

Kopiuj
wifstream file("text.txt");
file.imbue(locale(locale::empty(), new codecvt_utf8<wchar_t>())); // destruktor locale zwolni nam to codecvt_utf8

wstring line;
while(getline(file, line))
    cout << count(begin(line), end(line), L'ó') << "\n"; // jeżeli podajemy znak w ten sposób to plik źródłowy również musi być zapisany w Unicode!
edytowany 1x, ostatnio: Rev
Endrju
Hmmm, a można użyć std::string oraz prefixu u8? Jakimś cudem w taki sposób ma działać UTF-8 oraz char, tylko pewnie rzeczy takie jak length będą nie takie, jak się oczekuje.
RE
Ten kod działa tak, że czytając tekst z pliku jest on zamieniany na UCS2 albo UCS4 (w zależności od tego jakiej wielkości jest wchar_t). To daje nam pewność, że każdy codepoint Unicode zmieści się w wchar_t, o ile ten ma co najmniej dwa bajty (bo UTF-8 może kodować tylko 10FFFFh codepointów). Od tego momentu kodowanie pliku już nas nie obchodzi i pracujemy normalnie. Prefix u8 odnosi się do literałów. Obecnie kompilatory działają tak, że domyślnie nie zmieniają kodowania literałów w ogóle. Jeżeli plik zapiszemy w UTF-8 to L&quot;coś&quot; również będzie w UTF-8.
Azarien
"rzeczy takie jak length będą nie takie, jak się oczekuje" - albo i oczekuje, bo znacznie częściej ważna jest liczba bajtów np. do kontroli bufora, a nie rzeczywistych znaków.
0

hm ... to znacząco utrudnia pracę
szczerze powiedziawszy program w dalszej części miał zliczać 2-gramy, 3-gramy w plikach w których dużo jest znaków różno bitowych.
Może jest jakiś work around albo inny język programowania bardziej przychylny?

Shalom
  • Rejestracja:około 21 lat
  • Ostatnio:prawie 3 lata
  • Lokalizacja:Space: the final frontier
  • Postów:26433
0

@Mielona jeśli chcesz się bawić w przetwarzanie języka naturalnego to python ;]


"Nie brookliński most, ale przemienić w jasny, nowy dzień najsmutniejszą noc - to jest dopiero coś!"
RE
Moderator
  • Rejestracja:około 18 lat
  • Ostatnio:około rok
1

Korzystając z mojego kodu możesz bez problemu wyszukiwać całe ciągi.

0

Usiadłam i postanowiłam skompilować twój kod @Rev

Ale napotkałam na kilka trudności.
Między innymi nie mogę usunąć błędu:
error C2061: syntax error : identifier 'codecvt_utf8'
oraz dla tej samej linijki
error C2665: 'std::locale::locale' : none of the 9 overloads could convert all the argument types
c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\xlocale(334): could be 'std::locale::locale(const char *,std::locale::category)'
c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\xlocale(371): or 'std::locale::locale(const std::string &,std::locale::category)'
while trying to match the argument list '(std::locale)'

_13th_Dragon
pewnie nie dopisałaś #include &lt;codecvt&gt;
0

Jak zwykle jakaś prościzna. Dzięki wielkie @_13th_Dragon

0

Plik ma około 300 tys słów. W linii nie powinno być dużo wyrazów.
W każdym razie zastanawiają mnie dwie kwestie.
Pierwsza jak wyczytywać dwa kolejne lub trzy kolejne znaki. Rozumiem że zmiana na UCS... zrobiła swoje i nie muszę się już martwić o bitowość, ale czy jest jakiś prosty sposób, jakaś funkcja, która nie kazałaby dodawać znaków i cofać się?

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.