[Решено]C++ перекодировка из cp866 в cp1251 (Перекодировка строки или файла из cp866 в cp1251)

Модератор: Модераторы разделов

Аватара пользователя
ffldove
Сообщения: 480
Статус: Keep It Simple, Stupid
ОС: RFRemix 14

[Решено]C++ перекодировка из cp866 в cp1251

Сообщение ffldove »

Есть некая программа на C++, в нем из файла считывается и преобразуется строка в формате string, как можно ее из cp866 преобразовать в cp1251?
Средство должно быть кросплатформенное и собираться под MinGW.
I learned something today
Спасибо сказали:
watashiwa_daredeska
Бывший модератор
Сообщения: 4038
Статус: Искусственный интеллект (pre-alpha)
ОС: Debian GNU/Linux

Re: [Решено]C++ перекодировка из cp866 в cp1251

Сообщение watashiwa_daredeska »

Конкретно из cp866 в cp1251 можно обойтись элементарным массивом на 256 char'ов и функцией:

Код: Выделить всё

char translate(char const* table, char c) {
  return table[(unsigned char)c];
}
Спасибо сказали:
Аватара пользователя
eddy
Сообщения: 3321
Статус: Красный глаз тролля
ОС: ArchLinux

Re: [Решено]C++ перекодировка из cp866 в cp1251

Сообщение eddy »

Пример на С (правда, декодирует в КОИ-8):

Код: Выделить всё

#include <stdio.h>
#include <string.h>

unsigned char c[3][128]={
"─│┌┐└┘├┤┬┴┼▀▄█▌▐░▒▓⌠■∙√≈≤≥ ⌡°²·÷═║╒ё╓╔╕╖╗╘╙╚╛╜╝╞╟╠╡Ё╢╣╤╥╦╧╨╩╪╫╬©юабцдефгхийклмнопярстужвьызшэщчъЮАБЦДЕФГХИЙКЛМНОПЯРСТУЖВЬЫЗШЭЩЧЪ",
"???????????????????????????????? ???????Ё©??????°??????·ё???????АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюя",
"АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмноп░▒▓│┤╡╢╖╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀рстуфхцчшщъыьэюяЁё??????°∙·√??■ "};

char encode(const int ch, const int i){ //returns encoding letter
    char ret;
    if (ch == 13) ret = 10;
    else
    if (ch < 128) ret = ch;
    else
    ret = c[i][ch%256 - 128];
    return ret;
}

int recognize(FILE* f){ //asks to recognize encoding
    char* ans=(char*) malloc(128);
    int i,ch,ii;
    if (f==NULL){
    printf("Cannot open file\n");
    exit(4);
    }
    printf("\n");
    for (i=0; i<3; i++){
    ch=fgetc(f);
    ii=0;
    while(ch != EOF){
        if (ch>127){
        ++ii;
        if (ii<256) putchar(encode(ch,i));
        else
            break;
        }
        ch=fgetc(f);
    }
    rewind(f);
    printf("\n\nIs it right?[n]\n");
    scanf("%s",ans);
    if(strcmp(ans,"y")==0 || strcmp(ans,"yes")==0) return i;
    }
    printf("\n\t\t\tUndefined codepage!!!\n\n");
    return 0;
}

int main(int argc, char** argv){
    int x,i,l;
    char name[128];
    FILE *f, *f1, *f2;
    if(argc<2){
    printf("\nError! Need at least 1 argument!!!\n");
    exit(1);
    }
    int global=0; //asks to recognize only once
    if(strcmp(argv[1],"cp1251")==0 || strcmp(argv[1],"CP1251")==0){
    --argc; ++argv;
    global=1;
    x=1;
    }
    if(strcmp(argv[1],"-r")==0 && global != 1){
    printf("Recognize first file\n");
    --argc;    ++argv;            //analog of shell's "shift"
    global=1;
    f=fopen(argv[1],"r");
    x=recognize(f);
    fclose(f);
    }
    for (i=1; i<argc; i++){
    f=fopen(argv[i],"r");
    if (global==0) x=recognize(f);
    sprintf(name, "enc.%d", i);
    f1=fopen("tmp_encode","w");
    l=fgetc(f);
    while(l!=EOF){
        fputc(encode(l,x),f1); //this is encoding itself
        l=fgetc(f);
    }
    fclose(f1);
    fclose(f);
    unlink(argv[i]);//rename tmp->argv[i]
    if(link("tmp_encode",argv[i])<0)
        printf("error moving file %s\n",argv[i]);
    unlink("tmp_encode");
    printf("File %s is done\n",argv[i]);
    }
    printf("\nAll files are processed!!!\n");
}


Но лучше подключить enca.
RTFM
-------
KOI8-R - патриотичная кодировка Изображение
Спасибо сказали:
Аватара пользователя
ffldove
Сообщения: 480
Статус: Keep It Simple, Stupid
ОС: RFRemix 14

Re: [Решено]C++ перекодировка из cp866 в cp1251

Сообщение ffldove »

Всем спасибо, понял в чем моя ошибка в решение этой задачи.
С самого начала я пытался найти готовую функцию или библиотеку работы с кодировками. Но как оказалось гораздо проще самому написать функцию преобразования кодировки.
Вот что получилось (возможно что то можно сделать кошернее, но опыта пока мало, так что что получилось то получилось.):

Код: Выделить всё

int n=0, simv_int; //Счетчик и цифровое значение символа
char simv; //Символ в char
string kon=" "; //Для сравнения в while, возможно можно убрать, но не знаю пока еще как
//строка храниться в типе string и после преобразования я в конец записываю символ пробела (чтобы видеть конец строки, в самой строке пробелов быть не может), хотя можно заменить на любой другой символ

while (str_kon[n]!=kon[0]){ //проверка конца строки
  simv_int=str_kon[n]; //получение кода символа
  simv=str_kon[n]; //преобразование символа в char
  if (simv_int>-129 && simv_int<-80){ //проверка русских символов от "А" до "п"
    str_kon_1251+=simv+64;
  }
  else if (simv_int>-33 && simv_int<-16){ //проверка русских символов от "р" до "я"
    str_kon_1251+=simv+16;
  }
  else{ //остальные символы
    str_kon_1251+=simv;
  }
I learned something today
Спасибо сказали:
Аватара пользователя
Portnov
Модератор
Сообщения: 1786
Статус: Матёрый линуксоид
ОС: Debian testing/unstable

Re: [Решено]C++ перекодировка из cp866 в cp1251

Сообщение Portnov »

man 3 iconv и далее по ссылкам.
Работа: Ubuntu 9.10
Дом: Debian testing/unstable и на всякий случай winxp в virtualbox.
Для разнообразия: моя домашняя страница -http://iportnov.ru
Спасибо сказали:
Аватара пользователя
ffldove
Сообщения: 480
Статус: Keep It Simple, Stupid
ОС: RFRemix 14

Re: [Решено]C++ перекодировка из cp866 в cp1251

Сообщение ffldove »

Portnov писал(а):
15.07.2010 15:51
man 3 iconv и далее по ссылкам.

Рассматривал этот вариант, но слишком громоздко показалось.
I learned something today
Спасибо сказали:
mas
Сообщения: 1
ОС: WinXP

Re: [Решено]C++ перекодировка из cp866 в cp1251

Сообщение mas »

Что лучше переписать так

Код: Выделить всё

void cp866_cp1251( string &s ) {
    for( char *c=(char*)s.c_str(); *c!=0; ++c ) {
        if( *c>-129 && *c<-80 )
            *c += 64;
        else if( *c>-33 && *c<-16 )
            *c += 16;
    }
}
Спасибо сказали:
Аватара пользователя
Denjs
Сообщения: 1685
ОС: SuSe 10.2

Re: [Решено]C++ перекодировка из cp866 в cp1251

Сообщение Denjs »

Qt низя пользовать по условиям задачи? QTextCodec все умеет и все может.
Любое конвертирование через юникод. Сначала в юникод потом куда угодно - в/из любой из полуторадесятков поддерживаемых кодировок.
QDroid - Среда исполнения и фреймворк для QtScript.
OTPD - Открытые драйвера промышленных принтеров чеков и этикеток (кроссплатформенная подсистема печати).
Спасибо сказали:
Аватара пользователя
eddy
Сообщения: 3321
Статус: Красный глаз тролля
ОС: ArchLinux

Re: [Решено]C++ перекодировка из cp866 в cp1251

Сообщение eddy »

Denjs писал(а):
06.12.2010 16:28
Любое конвертирование через юникод. Сначала в юникод потом куда угодно - в/из любой из полуторадесятков поддерживаемых кодировок.

Проще уж использовать libenca, чем мучиться с юникодом :)
RTFM
-------
KOI8-R - патриотичная кодировка Изображение
Спасибо сказали:
Аватара пользователя
Denjs
Сообщения: 1685
ОС: SuSe 10.2

Re: [Решено]C++ перекодировка из cp866 в cp1251

Сообщение Denjs »

eddy писал(а):
06.12.2010 19:46
Denjs писал(а):
06.12.2010 16:28
Любое конвертирование через юникод. Сначала в юникод потом куда угодно - в/из любой из полуторадесятков поддерживаемых кодировок.

Проще уж использовать libenca, чем мучиться с юникодом :)

"Мучитьцца?" да прекратите вы. с Qt работать - одно удовольствие.
QDroid - Среда исполнения и фреймворк для QtScript.
OTPD - Открытые драйвера промышленных принтеров чеков и этикеток (кроссплатформенная подсистема печати).
Спасибо сказали: