Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Программирование и базы данных (http://forum.oszone.net/forumdisplay.php?f=21)
-   -   swprintf (Linux) - неправильная работа (http://forum.oszone.net/showthread.php?t=282814)

RedScorpio 28-05-2014 14:45 2356813

swprintf (Linux) - неправильная работа
 
Добрый день
Не могу добиться правильной работы swprintf под Linux

Код:

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

int main() {
    FILE *fileOut;
    wchar_t wcBuffer[264];
    char *cBuffer = "string";

    printf("\n\tTest module (swprinf)\n");

    if ((fileOut = fopen("testfile.txt", "wb")) == NULL) {
        printf("\tCan't open file \"testfile.txt\"");
        return -1;
    }

// Case 1
    memset(wcBuffer, 0x00, sizeof(wcBuffer));
#ifdef __linux
    swprintf(wcBuffer, 260, L"Test_string_1");
#else
    swprintf(wcBuffer, L"Test_string_1");
#endif
    fwrite(wcBuffer, sizeof(wcBuffer), 1, fileOut);

// Case 2
    memset(wcBuffer, 0x00, sizeof(wcBuffer));
#ifdef __linux
    swprintf(wcBuffer, 260, L"Test_%S_2", cBuffer);
#else
    swprintf(wcBuffer, L"Test_%S_2", cBuffer);
#endif
    fwrite(wcBuffer, sizeof(wcBuffer), 1, fileOut);

    fclose(fileOut);

    return 0;
}

При компиляции под Windows все работает, как ожидается; под Linux возникает 2 проблемы:
1. Case 2. Вместо Test_string_2 в файле оказывается записан шаблон Test_%S_2
2. Case 1+2. После строки в файле оказывается "мусор" (под Windows идут аккуратные 0х00, как задумывалось)

В чем моя ошибка?
Спасибо

PS. Компиляторы:
Linux GCC 4.4.7 (3.x.x тоже испытывался), опции -Wall -fshort-wchar -O2 -m32 -s -U__STRICT_ANSI__
Windows MinGW

RedScorpio 28-05-2014 15:52 2356844

Дополнительно про Linux (если имеет значение)
RHEL 6.5 i686

pva 28-05-2014 21:41 2356997

http://linux.die.net/man/3/swprintf
вроде всё сходится с описанием: нужно %ls, а не %S

RedScorpio 29-05-2014 12:55 2357237

Цитата:

Цитата pva
вроде всё сходится с описанием: нужно %ls, а не %S »

увы, %ls == %S, с ним работает точно так же, т.е. неправильно...

pva 29-05-2014 18:35 2357392

кажется понял:
%S (хотя я такого в мануале не нашёл) и %ls ожидает wchar_t*
а чтобы выводить char*, нужен %s
По крайней мере %s отработал (по моему мнению) правильно.

Жаль, что -Wformat ничего на неправильный код не выдал.

RedScorpio 29-05-2014 19:43 2357421

Цитата:

Цитата pva
а чтобы выводить char*, нужен %s
По крайней мере %s отработал (по моему мнению) правильно. »

Это был самый первый вариант, который я попробовал :-)
У меня (GCC, как я уже говорил) он тоже работает неправильно

pva 29-05-2014 20:59 2357458

пробовал так:
Код:

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

int main() {
    static unsigned const length = 200;
    static const wchar_t wcs[] = L"asdsd";
    static const char cs[] = "gfdkgjh";
    wchar_t mem[length], correct[]=L"|gfdkgjh|asdsd|200|\n";
    int diff;

    swprintf(mem, length, L"|%s|%S|%d|\n", cs, wcs, length);
    diff = wcscmp(mem, correct);
    if (diff) { printf("failed!\n"); }
    fwrite(mem, sizeof(*mem), wcslen(mem), stdout);
    fwrite(correct, sizeof(*correct), wcslen(correct), stdout);

    return diff;
}

Код:

[andrey@localhost 1]$ gcc test.c
[andrey@localhost 1]$ ./a.out
|gfdkgjh|asdsd|200|
|gfdkgjh|asdsd|200|
[andrey@localhost 1]$ ./a.out |hexdump -c
0000000  |  \0  \0  \0  g  \0  \0  \0  f  \0  \0  \0  d  \0  \0  \0
0000010  k  \0  \0  \0  g  \0  \0  \0  j  \0  \0  \0  h  \0  \0  \0
0000020  |  \0  \0  \0  a  \0  \0  \0  s  \0  \0  \0  d  \0  \0  \0
0000030  s  \0  \0  \0  d  \0  \0  \0  |  \0  \0  \0  2  \0  \0  \0
0000040  0  \0  \0  \0  0  \0  \0  \0  |  \0  \0  \0  \n  \0  \0  \0
0000050  |  \0  \0  \0  g  \0  \0  \0  f  \0  \0  \0  d  \0  \0  \0
0000060  k  \0  \0  \0  g  \0  \0  \0  j  \0  \0  \0  h  \0  \0  \0
0000070  |  \0  \0  \0  a  \0  \0  \0  s  \0  \0  \0  d  \0  \0  \0
0000080  s  \0  \0  \0  d  \0  \0  \0  |  \0  \0  \0  2  \0  \0  \0
0000090  0  \0  \0  \0  0  \0  \0  \0  |  \0  \0  \0  \n  \0  \0  \0
00000a0
[andrey@localhost 1]$ uname -a
Linux localhost 3.14.3-2-ARCH #1 SMP PREEMPT Mon May 12 20:54:05 CEST 2014 i686 GNU/Linux

Возможно вам следует обновиться из репозитория?

RedScorpio 30-05-2014 10:42 2357651

Цитата pva:
пробовал так: »
Если Вам не трудно, попробуйте, пожалуйста, мой исходник (я специально его привел - там не статический массив char)
Цитата pva:
Возможно вам следует обновиться из репозитория? »
К сожалению, Linux не является моим штатным рабочим инструментом (установлен в VirtualBox), знаю его плохо: в интернет ходит, обновлять что-либо - не хочет

RedScorpio 30-05-2014 10:58 2357658

У меня получается так (wchar_t 2-х байтный)
Код:

[asap@RHEL65x32 Test]$ cat testfile.txt | hexdump -c
0000000  T  \0  e  \0  s  \0  t  \0  _  \0  s  \0  t  \0  r  \0
0000010  i  \0  n  \0  g  \0  _  \0  1  \0  \0  \0  T  \0  e  \0
0000020  s  \0  t  \0  _  \0  %  \0  s  \0  _  \0  2  \0  \0  \0
0000030 001 033 003  ;      \0  \0  \0 003  \0  \0  \0 204 376 377 377
0000040  <  \0  \0  \0 224 376 377 377  \  \0  \0  \0 356 376 377 377
0000050 210  \0  \0  \0 024  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0
0000060  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0
*
0000210  T  \0  e  \0  s  \0  t  \0  _  \0  %  \0  s  \0  _  \0
0000220  2  \0  \0  \0 001 033 003  ;      \0  \0  \0 003  \0  \0  \0
0000230 204 376 377 377  <  \0  \0  \0 224 376 377 377  \  \0  \0  \0
0000240 356 376 377 377 210  \0  \0  \0 024  \0  \0  \0  \0  \0  \0  \0
0000250  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0

видно, что вместо результирующего текста во второй строке - шаблон

pva 30-05-2014 21:33 2357946

RedScorpio, делаю так:
1. Копиру код, заменяю %S на %s
Цитата:

Цитата pva
а чтобы выводить char*, нужен %s
По крайней мере %s отработал (по моему мнению) правильно. »

2. собираю, запускаю, хексдамп:
Код:

[andrey@localhost 1]$ hexdump -c <testfile.txt
0000000  T  \0  \0  \0  e  \0  \0  \0  s  \0  \0  \0  t  \0  \0  \0
0000010  _  \0  \0  \0  s  \0  \0  \0  t  \0  \0  \0  r  \0  \0  \0
0000020  i  \0  \0  \0  n  \0  \0  \0  g  \0  \0  \0  _  \0  \0  \0
0000030  1  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0
0000040  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0
*
0000420  T  \0  \0  \0  e  \0  \0  \0  s  \0  \0  \0  t  \0  \0  \0
0000430  _  \0  \0  \0  s  \0  \0  \0  t  \0  \0  \0  r  \0  \0  \0
0000440  i  \0  \0  \0  n  \0  \0  \0  g  \0  \0  \0  _  \0  \0  \0
0000450  2  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0
0000460  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0
*
0000840


pva 30-05-2014 21:56 2357955

Вот оно что! во всём виноват
Код:

-fshort-wchar
wxhar_t то стал короче, в реализация wsprintf короче не стала. Нужно слинковать с соответвтующей функцией glibc, но я такой не нашёл (для 16-битного wchar_t)

RedScorpio 02-06-2014 10:36 2358799

Цитата pva:
wxhar_t то стал короче, в реализация wsprintf короче не стала. Нужно слинковать с соответвтующей функцией glibc, но я такой не нашёл (для 16-битного wchar_t) »
Да, действительно, это и есть root cause. Но мне-то нужен 16-битный wchar_t... Похоже, что придется делать "костыли", а не хотелось бы...


Время: 17:44.

Время: 17:44.
© OSzone.net 2001-