#c #linux
При попытке чтения символов сначала функцией getchar() а потом getwchar() (или наоборот - сначала getwchar() а потом getchar()) вторая функция возвращает EOF. #include#include #include #include #include main (int ac, char *av[]) { printf ("locale: %s\n",setlocale(LC_ALL,"")); int c1 = 5, c2 = 6; wint_t wc1 = 998, wc2 = 999; int fd; errno = 10000; if (av[1]) { printf ("getchar()...getwchar()\n"); c1 = getchar(); c2 = getchar(); // freopen("/dev/tty","r",stdin); // fd = dup(0); // fclose(stdin); // stdin = fdopen(dup2(fd,0),"r"); // clearerr(stdin); // fflush(stdin); wc1 = getwchar(); wc2 = getwchar(); } else { printf ("getwchar()...getchar()\n"); wc1 = getwchar(); wc2 = getwchar(); // freopen("/dev/tty","r",stdin); // fd = dup(0); // fclose(stdin); // stdin = fdopen(dup2(fd,0),"r"); // clearerr(stdin); // fflush(stdin); c1 = getchar(); c2 = getchar(); } printf ("errno = %d [%m]\n",errno); printf ("c1=%x c2=%x wc1=%x wc2=%x\n",c1,c2,wc1,wc2); } avp@avp-xub11:~/src/ig/web-agent$ ./a.out locale: ru_RU.UTF-8 getwchar()...getchar() 1234 errno = 29 [Недопустимая операция смещения] c1=ffffffff c2=ffffffff wc1=31 wc2=32 avp@avp-xub11:~/src/ig/web-agent$ От наличия вызова setlocale() ситуация (принципиально) не меняется. Из всех придуманных мной попыток наладить переключение, удается только freopen(), но это не может быть нормальным решением проблемы, т.к. уже буферизованные данные пропадают. В windows проблема не наблюдается, но там другая (однобайтная) локализация: locale: Russian_Russia.1251 Как решить данную задачу?
Ответы
Ответ 1
Нашел кое-что не обнадеживающее в man fwide if stream has no orientation yet; in this case the next I/O operation might change the orientation (to byte oriented if it is a char I/O operation, or to wide-character oriented if it is a wide-char‐ acter I/O operation). Once a stream has an orientation, it cannot be changed and persists until the stream is closed. Похоже проблема просто (без хаков структур из libio.h (пока не очень понятно в какой момент, сорсы libc надо читать)) не решается. Или сделать свои аналоги семейства getwchar() ??? Или аналоги под другим именем ? Пока вопрос не закрываю, жду советов. UPDATE Читать libio стало лень, написал свое. Может кому-нибудь пригодится. Если остальной код интересен, могу выложить куда-нибудь. /* ucsutf.h avp 2012 Функции для UTF-8 и Unicode (ASCII&Cyrillic), независимые от setlocale() */ #ifndef UCSUTF_H #define UCSUTF_H #include// возвращает ucs из utf-8 в памяти extern int utf8_to_ucs (const char *utf, int *step, int *err); // записать ucs в кодировке utf-8 в память, возвращает к-во записанных байт extern int ucs_to_utf8 (int uc, char *b); // аналоги ctype для ucs (ascii & cyrillic) extern int isAlpha (int ucs); extern int isLower (int ucs); extern int isUpper (int ucs); extern int toLower (int ucs); extern int toUpper (int ucs); // длина utf-8 символа (по первому байту) extern int utf8_chrlen (const char *utf); // convert символ utf-8 в памяти (по месту), возвращают к-во байт extern int utf8_toUpper (char *s, int *err); extern int utf8_toLower (char *s, int *err); struct getucs { u_int ucs, // m.b. EOF nc, // прочитано из stream байт в bytes[] err; // 0 if OK, при ошибке - err == nc char bytes[8]; }; extern int utf8_fgetc (struct getucs *uc, FILE *stream); // ucs из utf-8 stream #endif /* ucsutf.c avp 2012 Функции для UTF-8 и Unicode (ASCII&Cyrillic), независимые от setlocale() */ #include #include #include #include #include #include "ucsutf.h" /* utf-8 схема error: 0xFF, 0xFE 1111 110x , 1111 10xx , 1111 0xxx , 1110 xxxx , 110x xxxx , 10xx xxxx 10xx xxxx , 10xx xxxx , 10xx xxxx , 10xx xxxx , 10xx xxxx 10xx xxxx , 10xx xxxx , 10xx xxxx , 10xx xxxx 10xx xxxx , 10xx xxxx , 10xx xxxx 10xx xxxx , 10xx xxxx 10xx xxxx */ // значимые биты из первого байта UTF-8 static int mask[5] = { 0x01, 0x03 ,0x07 ,0x0F ,0x1F}; /* Некая замена fgetwc() не зависит от setlocale() и ПОЗВОЛЯЕТ использовать fgetc() и др. Возвращает UCS from stream UTF-8 characters or EOF если преобразование UTF-8 -> UCS невозможно возвращает EOF и устанавливает errno в EILSEQ Также заполняет структуру getucs прочитанными байтами */ int utf8_fgetc (struct getucs *uc, FILE *f) { uc->nc = uc->err = 0; int c, n = 5; if (feof(f)) c = EOF; else if ((c = fgetc(f)) != EOF) { uc->bytes[uc->nc++] = c; if (c > 127) { if ((c & 0xc0) == 0x80 || c == 0xff || c == 0xfe) { c = EOF; uc->err = 1; } else { while (n && (c & (1< bytes[uc->nc++] = c) & 0xc0) != 0x80) { uc->err = uc->nc; c = EOF; break; } ucs <<= 6; ucs |= (c & 0x3f); } if (c != EOF) c = ucs; } } } if (uc->err) errno = EILSEQ; return uc->ucs = c; } .... ....
Комментариев нет:
Отправить комментарий