Войти

Показать полную графическую версию : swprintf (Linux) - неправильная работа


RedScorpio
28-05-2014, 14:45
Добрый день
Не могу добиться правильной работы 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
Дополнительно про Linux (если имеет значение)
RHEL 6.5 i686

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

RedScorpio
29-05-2014, 12:55
вроде всё сходится с описанием: нужно %ls, а не %S »
увы, %ls == %S, с ним работает точно так же, т.е. неправильно...

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

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

RedScorpio
29-05-2014, 19:43
а чтобы выводить char*, нужен %s
По крайней мере %s отработал (по моему мнению) правильно. »
Это был самый первый вариант, который я попробовал :-)
У меня (GCC, как я уже говорил) он тоже работает неправильно

pva
29-05-2014, 20:59
пробовал так:

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

RedScorpio
30-05-2014, 10:58
У меня получается так (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
RedScorpio, делаю так:
1. Копиру код, заменяю %S на %s
а чтобы выводить 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
Вот оно что! во всём виноват

-fshort-wchar

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

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




© OSzone.net 2001-2012