vsnprintf и gcc - PullRequest
       14

vsnprintf и gcc

0 голосов
/ 29 июля 2010

У меня есть следующее утверждение:

vsnprintf(target, size - 1, "%ls_%ls", str16_1, str16_2);

Почему это не работает на GCC?

Я использовал это в Windows так:

vsnprintf(target, size - 1, "%S_%S", str16_1, str16_2);

и работает как положено. В документации по gcc я обнаружил, что% S является синонимом% ls, но я не должен его использовать. Я пытался также с% S, но не работает. Я использую это в функции с переменным списком аргументов. Возможно ли не работать, потому что я изменяю переменную формата, которую я передаю va_start? Я должен найти% S и заменить его на% ls в переменной формата.

Функция выглядит примерно так:

void f(const char* format, ...){
  char* new_format = format with %S replaced with %ls;
  va_list argptr;
  va_start(args, format);
  vsnprintf(str, size-1, new_format, argptr);
}

Я проверил, и new_format правильный.

Спасибо!

Ответы [ 6 ]

8 голосов
/ 29 июля 2010

Попробуйте использовать snprintf, причина в vsnprintf. vsnprintf принимает аргумент типа va_list, а не список буквенных переменных. Например:

va_list ap;
va_start (ap, first_arg_in_this_function);
vsnprintf (buf, size, format_str, ap);
va_end (ap);

В то время как со спринтом:

snprintf (buf, size, format_str, x, y);

Используйте v*printf, когда ...

  1. Создание обёрток вокруг функций стиля printf
  2. Variadic макросы не являются опцией

В противном случае просто используйте *printf

2 голосов
/ 29 июля 2010

Я посмотрел %ls для vsnprintf и обнаружил, что это спецификатор формата для печати / форматирования строки широких символов, т. Е. wide_t *p = L"Hello world!";

Потребовалось немного воспроизведения и поиска широкого символаиспользование в C ++ (мне понравилась следующая страница: http://www.linux.com/archive/feed/51836),, но я думаю, что разобрался с вашей проблемой.

Если вы передадите строку char в %ls, то она не развернется, но если вы передаете строку wchar_t в %ls , тогда печатает.

Рассмотрим следующий пример кода I, основанный на вашей информации:

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


char       str[100];


void f (const char    *format,
        ...)
{
    va_list    args;

    va_start(args, format);
    vsnprintf(str, sizeof(str), format, args);
    va_end(args);
}




int
main ()
{
    char    *p1 = "1234";
    char    *p2 = "abcd";

    wchar_t    *pw1 = L"9876";
    wchar_t    *pw2 = L"wxyz";



    f("%d_%d", 120, 199);
    printf("numbers: %s\n", str);


    f("%s_%s", p1, p2);
    printf("char*: %s\n", str);


    f("%ls_%ls", p1, p2);
    printf("wide char* with char* input: %s\n", str);


    f("%ls_%ls", pw1, pw2);
    printf("wide char* with wide char* input: %s\n", str);


    return (0);
}

Я скомпилировал это с помощью g ++.

make newtest.exe
g++ -g -c -MD -Wall -Werror  newtest.cxx
g++ -o newtest.exe newtest.o -lc -lrt

Compilation finished at Thu Jul 29 08:54:57

Вывод ниже:

[SUSE10.1]:201> newtest.exe
numbers: 120_199
char*: 1234_abcd
wide char* with char* input: 
wide char* with wide char* input: 9876_wxyz
2 голосов
/ 29 июля 2010

Вы используете va_start неверно. В этом заявлении:

va_start(args, new_format);

Вы не имеете в виду параметр format функции f(). Второй аргумент va_start() должен относится к параметру в списке формальных параметров функции. Все остальное, скорее всего, неопределенное поведение.

Компилятор использует именованный формальный параметр в va_start(), чтобы определить, с чего начать поиск списка аргументов переменной в вызове функции. Он не знает автоматически, куда вы положили ... в список аргументов (возможно, вы ожидаете, что так и должно быть, но это не так).

0 голосов
/ 29 июля 2010

Поскольку я использую это на Mac, я нашел обходной путь:

Как "передать" переменное число аргументов в NSString's + stringWithFormat:

Кажется, что vsnprintf не может обработать 16-битную строку. Возможно, потому что wchar_t не 16 бит.

0 голосов
/ 29 июля 2010

Какой у вас тип valist? Правильный тип для аргументов списка переменных: va_list с подчеркиванием, нет?

0 голосов
/ 29 июля 2010

Использование snprintf.

...