Неправильный вызов функции с переменными параметрами - PullRequest
0 голосов
/ 21 февраля 2020

Я пытаюсь вызвать вложенную функцию с переменным количеством параметров, не получая их. И я получаю неправильный результат.

Вот моя простая программа на С ++:

extern "C" {
#include <stdio.h>
}
#include <cstdarg>

class ctty {
    public:
        ctty();
        int logger(int prior, const char* format, ...);
    private:
};

ctty::ctty(){};

int ctty::logger(int prior, const char* format, ...)
{
    va_list ap;
    va_start(ap,format);
    printf(format, ap);
    va_end(ap);
    return 0;
}

int main(int argc, char** argv)
{
    ctty tty;
    tty.logger(0, "Test %d %d %d\n", 7, 5, 5);
    return 0;
}

результат:

Test -205200 7 5

Я ожидаю результат

Test 7 5 5

Я не понимаю, что я делаю не так? Заранее спасибо.

1 Ответ

0 голосов
/ 21 февраля 2020

Вы не можете напрямую передать va_list в printf. va_list - это обертка вокруг фактического списка аргументов (независимо от его представления). Хотя C способ сделать должен использовать vprintf, в C ++ есть более безопасные альтернативы, такие как шаблоны c variadi, позволяющие создать более безопасную версию форматированной печати, например (строка вымышленного формата для краткости примера):

#include <iostream>
#include <cstdlib>

class ctty {
    public:
        ctty();

        template<typename T, typename... Args>
        int logger(int prior, const char* format, T value, Args... args);
    private:
        void logger(int prior, const char *s);
};

ctty::ctty(){};

void ctty::logger(int prior, const char *s)
{
    while (*s) {
        if (*s == '%') {
            if (*(s + 1) == '%') {
                ++s;
            }
            else {
                throw std::runtime_error("invalid format string: missing arguments");
            }
        }
        std::cout << *s++;
    }
}

template<typename T, typename... Args>
int ctty::logger(int prior, const char* format, T value, Args... args)
{
    while (*format) {
        if (*format == '%') {
                std::cout << value;
                logger(prior, format + 1, args...); 
                return 0;
            }
        std::cout << *format++;
    }
    throw std::logic_error("extra arguments provided to logger");
}

int main(int argc, char** argv)
{
    ctty tty;
    tty.logger(0, "Test % % %\n", 7.55f, "Tada!", 888);
    return 0;
} 

Эта часть вашего кода:

extern "C" {
#include <stdio.h>
}

Технически это неопределенное поведение, хотя оно может компилироваться и не оказывать неблагоприятного воздействия в некоторых случаях, оно не переносимо. Вы должны использовать заголовки C ++, например <cstdio>

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...