Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Программирование [игнор отключен] [закрыт для гостей] / Переменное число аргументов в функции / 19 сообщений из 19, страница 1 из 1
19.02.2020, 13:40
    #39928416
jenya7
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Переменное число аргументов в функции
Скажем так
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
void va_test(int num_args, ...)
{
    va_list valist; 
    
    va_start(valist, num_args); 
    
   for (int i = 0; i <= num_args; i++)
       int sum += va_arg(valist, int);
}



но если аргументы разных типов
va_test(4, 1, "аа" , 2, "бб" )
как мне проверить тип аргумента?
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
void va_test(int num_args, ...)
{
    va_list valist; 
    
    va_start(valist, num_args); 
    
   for (int i = 0; i <= num_args; i++)
  {
       //if  arg int
       int sum = va_arg(valist, int);
       //if arg string
       char *str = va_arg(valist, char *);
  }
}
...
Рейтинг: 0 / 0
19.02.2020, 13:57
    #39928427
OoCc
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Переменное число аргументов в функции
jenya7

так же как это сделано в printf
или вариадик темплеты.
...
Рейтинг: 0 / 0
19.02.2020, 14:00
    #39928428
Dima T
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Переменное число аргументов в функции
ИМХО по хорошему надо в структуру собрать все твои аргументы и ее передавать.
...
Рейтинг: 0 / 0
19.02.2020, 14:10
    #39928436
jenya7
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Переменное число аргументов в функции
Dima T
ИМХО по хорошему надо в структуру собрать все твои аргументы и ее передавать.

и включить в структуру тип аргумента? громоздко как то получается...
...
Рейтинг: 0 / 0
19.02.2020, 14:13
    #39928439
jenya7
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Переменное число аргументов в функции
OoCc
jenya7

так же как это сделано в printf
или вариадик темплеты.

я посмотрел на сорцы printf. отхожу от шока...
но принцип понятен - %s - означает строку, %d - означает число и так далее.
наверно нужно делать как Dima_T советует.
...
Рейтинг: 0 / 0
19.02.2020, 14:15
    #39928446
Dima T
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Переменное число аргументов в функции
jenya7
OoCc
jenya7

так же как это сделано в printf
или вариадик темплеты.

я посмотрел на сорцы printf. отхожу от шока...

и учти в printf() можно элементарно накосячить, для контроля этого в компиляторах есть специальные флаги для проверки во время компиляции.
...
Рейтинг: 0 / 0
19.02.2020, 14:22
    #39928451
Dima T
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Переменное число аргументов в функции
jenya7
Dima T
ИМХО по хорошему надо в структуру собрать все твои аргументы и ее передавать.

и включить в структуру тип аргумента? громоздко как то получается...

Если тип заранее неизвестен, то по другому никак.
В параметрах приходят только значения, а тип и размер задается заранее, во время компиляции. Т.е. вызываемая функция заранее знает какого типа ее параметры.

Как вариант не явно наполнять указывая типы, а сделать методы:
Код: plaintext
1.
2.
add(int x);
add(char* x);


и внутри каждого прописать добавления нужного типа.
...
Рейтинг: 0 / 0
19.02.2020, 14:25
    #39928453
OoCc
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Переменное число аргументов в функции
jenya7
OoCc
jenya7

так же как это сделано в printf
или вариадик темплеты.

я посмотрел на сорцы printf. отхожу от шока...
но принцип понятен - %s - означает строку, %d - означает число и так далее.
наверно нужно делать как Dima_T советует.

В твоём случае ненужна вся комплексити printf формата. Достаточно одного символа на параметр.
...
Рейтинг: 0 / 0
19.02.2020, 14:26
    #39928455
Имя пользователя1
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Переменное число аргументов в функции
Dima T
ИМХО по хорошему надо в структуру собрать все твои аргументы и ее передавать.
по хорошему тут просматривается базовый класс и подклассы для обработки разных типов.

а в функцию либо массив указателей передавать, либо сами указатели, если хочется va_*** поюзать
...
Рейтинг: 0 / 0
19.02.2020, 14:32
    #39928459
Dima T
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Переменное число аргументов в функции
OoCc
jenya7
пропущено...

я посмотрел на сорцы printf. отхожу от шока...
но принцип понятен - %s - означает строку, %d - означает число и так далее.
наверно нужно делать как Dima_T советует.

В твоём случае ненужна вся комплексити printf формата. Достаточно одного символа на параметр.

А как оно в памяти расположится? Разные типы могут быть разного размера.
...
Рейтинг: 0 / 0
19.02.2020, 14:40
    #39928466
OoCc
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Переменное число аргументов в функции
Dima T
OoCc
пропущено...

В твоём случае ненужна вся комплексити printf формата. Достаточно одного символа на параметр.

А как оно в памяти расположится? Разные типы могут быть разного размера.

так же как и printf разбирается с char и double. Строки и комплексные типы - передаются по указателю.
...
Рейтинг: 0 / 0
19.02.2020, 15:12
    #39928498
jenya7
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Переменное число аргументов в функции
я тут накропал. а если так?
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
typedef struct
{
      char *variable;
      int type;
}VAR;

void MyPrintf(int argc, ...)
{
    int i;
    int val;
    char *strp;
    VAR var;
    
    va_list valist; 
    
    va_start(valist, argc); 
    
    //first argument is a resulting string
    char *string = va_arg(valist, char *);
   
    for (i = 0; i < argc; i++)
    {
        var = va_arg(valist, VAR);
        switch (var.type)
        {
            case 1: val = *(uint8_t *)var.variable; break;
            case 2: val = *(uint16_t *)var.variable; break;
            case 3: val = *(uint32_t *)var.variable; break;
            case 4: strp = (char *)var.variable; break;
        }
        
        if (var.type < 4)
        {
            strp = loc_itoa(val);
            strcat(string, strp);
        }
        else
           strcat(string, strp);
            
    }
   
   va_end(valist); 
}
...
Рейтинг: 0 / 0
19.02.2020, 16:21
    #39928533
jenya7
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Переменное число аргументов в функции
поменял на войдовый указатель
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
typedef struct
{
    void *value;
    int type;
}VAR;

void MyPrintf(int argc, ...)
{
    int i;
    int val;
    char *strp;
    VAR var;
    
    va_list valist; 
    
    va_start(valist, argc); 
    
    //first argument is a resulting string
    char *string = va_arg(valist, char *);
   
    for (i = 1; i < argc; i++)
    {
        var = va_arg(valist, VAR);
        switch (var.type)
        {
            case VTYPE_BYTE:  val = *(uint8_t *)var.value;  break;
            case VTYPE_SHORT: val = *(uint16_t *)var.value; break;
            case VTYPE_INT:   val = *(uint32_t *)var.value; break;
            case VTYPE_STR:   strp = (char *)var.value;     break;
        }
        
        if (var.type < VTYPE_STR)
        {
            strp = loc_itoa(val);
            strcat(string, strp);
        }
        else
           strcat(string, strp);     
    }
    
   strcat(string, "\0");
   
   va_end(valist); 
}



проверяю
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
uint32_t COM_Printf(uint32_t argc, char** args)
{
  char str[128] = { '\0' };
    
    VAR vars[4];
    
    vars[0].type = 1;
    vars[0].value = (uint8_t*)1;

    vars[1].type = 4;
    vars[1].value = (char *)"aa";

    vars[2].type = 3;
    vars[2].value = (uint32_t*)1234;

    vars[1].type = 4;
    vars[1].value = (char *)"bb\r";
    

    //хочеться так но так не работает
    //MyPrintf(5, str, vars);

   MyPrintf(5, str, vars[0], vars[1], vars[2], vars[3]);
    
   USART_SendString(SYS_USART, str);
      
   return MSG_OK;
}



должен увидеть 1aa1234bb
но вижу
87bb
29491202949120
...
Рейтинг: 0 / 0
19.02.2020, 18:01
    #39928603
jenya7
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Переменное число аргументов в функции
так работает
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
void MyPrintf(int argc, ...)
{
    int i;
    int val;
    char *strp;
    VAR var;
     
    va_list valist; 
     
    va_start(valist, argc); 
     
    //first argument is a resulting string
    char *string = va_arg(valist, char *);
    
    for (i = 1; i < argc; i++)
    {
        var = va_arg(valist, VAR);
   
        switch (var.type)
        {
            case VTYPE_BYTE:  
            case VTYPE_SHORT:
            case VTYPE_INT:
              val = (int)var.value;
             break;
             
            case VTYPE_STR:
              strp = (char *)var.value; 
              break;
        }
    
        if (var.type < VTYPE_STR)
        {
            strp = loc_itoa(val);
            strcat(string, strp);
        }
        else
           strcat(string, strp);     
    }
     
   strcat(string, "\0");
    
   va_end(valist); 
}
 
uint32_t COM_Printf()
{
  char str[128] = { '\0' };
     
    VAR vars[4];
     
    vars[0].type = 1;
    vars[0].value = (void *)1;
    vars[1].type = 4;
    vars[1].value = (void *)"aa";
    vars[2].type = 3;
    vars[2].value = (void *)1234;
    vars[3].type = 4;
    vars[3].value = (void *)"bb\r";
     
   MyPrintf(5, str, vars[0], vars[1], vars[2], vars[3]);
    
   USART_SendString(SYS_USART, str);
       
   return MSG_OK;
}



напрягает инициализация и расстановка аргументов. но тут как мне кажеться упростить не удасться.
...
Рейтинг: 0 / 0
19.02.2020, 20:09
    #39928631
Dima T
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Переменное число аргументов в функции
jenya7
так работает ...

Это херь какая-то ((( Зачем передавать массив элементами ?

Есть еще куча претензий к твоему коду, завтра сформулирую.
...
Рейтинг: 0 / 0
20.02.2020, 06:38
    #39928712
Dima T
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Переменное число аргументов в функции
Код: plaintext
1.
vars[0].type = 1;


Почему 1 ? у тебя же выше имена типов определены, используй их, а не магические числа
Код: plaintext
1.
case VTYPE_BYTE:  




Как уже написал тут непонятно зачем переменное число параметров
Код: plaintext
1.
MyPrintf(5, str, vars[0], vars[1], vars[2], vars[3]);


Достаточно указателя на массив и размера
Код: plaintext
1.
void MyPrintf(VAR var, int var_size, char *str)





Зачем куча приведений? Накосячишь, а компилятор не предупредит, т.к. будет считать что так задумано. Используй union
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
typedef struct
{
   union {
      int ivalue;
      char cvalue;
      char* pcvalue;
      ....
    };
    int type;
}VAR;


Далее
Код: plaintext
1.
2.
    vars[0].type = VTYPE_INT;
    vars[0].ivalue = 1;

Код: plaintext
1.
2.
            case VTYPE_INT:   val = var.ivalue; break;
            case VTYPE_STR:   strp = var.pcvalue;     break;
...
Рейтинг: 0 / 0
20.02.2020, 09:12
    #39928745
jenya7
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Переменное число аргументов в функции
Dima T


Достаточно указателя на массив и размера
Код: plaintext
1.
void MyPrintf(VAR var, int var_size, char *str)





Первый аргумент в функции должен быть количество аргументов. И потом если указатель на массив то
void MyPrintf(VAR *var, int var_size, char *str)
Но когда я передаю указатель
MyPrintf(5, str, vars);
то не работает
не умеет var = va_arg(valist, VAR); брать аргументы по указателю.
...
Рейтинг: 0 / 0
20.02.2020, 09:43
    #39928756
Dima T
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Переменное число аргументов в функции
jenya7
Первый аргумент в функции должен быть количество аргументов. И потом если указатель на массив то
void MyPrintf(VAR *var, int var_size, char *str)
Но когда я передаю указатель
MyPrintf(5, str, vars);
то не работает
не умеет var = va_arg(valist, VAR); брать аргументы по указателю.

Зачем va_arg? У тебя фиксированное количество параметров.
Код: plaintext
1.
2.
3.
4.
void MyPrintf(VAR *var, int var_size, char *str) {
 for(int i = 0; i < var_size; i++) {
   switch (var[i].type) {
...
...
Рейтинг: 0 / 0
20.02.2020, 09:59
    #39928770
jenya7
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Переменное число аргументов в функции
Dima T
jenya7
Первый аргумент в функции должен быть количество аргументов. И потом если указатель на массив то
void MyPrintf(VAR *var, int var_size, char *str)
Но когда я передаю указатель
MyPrintf(5, str, vars);
то не работает
не умеет var = va_arg(valist, VAR); брать аргументы по указателю.

Зачем va_arg? У тебя фиксированное количество параметров.
Код: plaintext
1.
2.
3.
4.
void MyPrintf(VAR *var, int var_size, char *str) {
 for(int i = 0; i < var_size; i++) {
   switch (var[i].type) {
...


Ой. Действительно. Спасибо. Как всегда супер. :)
...
Рейтинг: 0 / 0
Форумы / Программирование [игнор отключен] [закрыт для гостей] / Переменное число аргументов в функции / 19 сообщений из 19, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]