Форум программистов, компьютерный форум CyberForum.ru

Как перенести параметры из ф-ции printf() в самодельную - C++

Восстановить пароль Регистрация
 
 
Рейтинг: Рейтинг темы: голосов - 81, средняя оценка - 4.83
Uklunok
3 / 3 / 0
Регистрация: 08.05.2010
Сообщений: 135
04.06.2011, 09:22     Как перенести параметры из ф-ции printf() в самодельную #1
Ребят, подскажите как решить задачу.
Нужно перенести параметры функции printf() в самодельную ф-цию myfunk(). При условии если булева переменная Х==1. Если не равна 1, то не переносить.
Задача осложняется тем, что число параметров ф-ции может быть переменным.
Подскажите пожалуйста, буду очень признателен.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
04.06.2011, 09:22     Как перенести параметры из ф-ции printf() в самодельную
Посмотрите здесь:

как переделать с cout на printf ? C++
Как вывести printf для струкутры C++
Как реализована функция printf C++
C++ Как выделить слово в printf?
Передача ф-ции как параметра другой ф-ции C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Uklunok
3 / 3 / 0
Регистрация: 08.05.2010
Сообщений: 135
04.06.2011, 16:00  [ТС]     Как перенести параметры из ф-ции printf() в самодельную #21
Цитата Сообщение от Evg Посмотреть сообщение

Ты лучше поясни, нафига тебе это нужно. Потому что есть подозрение, что у тебя есть постановка задачи, но ты пошёл её решать неверным путём
Ну если Вам интересно, это для компилятора Vinculum II. Микроконтроллеры семейства FTDI.

Собственно, чтобы более понятно было, мне нужно добавить в этот код ( это код для примера работы с функцией printf()):
C
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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
/*
** Runtime.c
**
** Copyright © 2010 Future Devices International Limited
**
**  C Source file for Vinculum II sample application
** Main module
**
** Author: FTDI
** Project: Vinculum II
** Module: Vinculum II Sample Applications
** Requires: VOS UART USBHost
** Comments:
**
** History:
**  1 – Initial version
**
*/
 
#include "vos.h"
 
#include "UART.h"
 
#include "config.h"
#include "ctype.h"
#include "errno.h"
#include "stdarg.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
 
VOS_HANDLE      hUart;
 
vos_tcb_t       *tcbFirmware;
 
void firmware(void);
 
char *months[] = {"January", "February", "March", "April",
                  "May", "June", "July", "August",
                  "September", "October", "November", "December"};
 
void main(void)
{
    // UART configuration context
    uart_context_t uart_ctx;
 
    vos_init(10, VOS_TICK_INTERVAL, 1);
    vos_set_clock_frequency(VOS_48MHZ_CLOCK_FREQUENCY);
 
    if (vos_get_package_type() == VINCULUM_II_64_PIN)
    {
        // UART to V2EVAL board pins
        vos_iomux_define_output(32,IOMUX_OUT_UART_TXD); //UART Tx
        vos_iomux_define_input(39,IOMUX_IN_UART_RXD); //UART Rx
        vos_iomux_define_output(40,IOMUX_OUT_UART_RTS_N); //UART RTS#
        vos_iomux_define_input(41,IOMUX_IN_UART_CTS_N); //UART CTS#
    }
    else // VINCULUM_II_48_PIN
    {
        // UART to V2EVAL board pins
        vos_iomux_define_output(41,IOMUX_OUT_UART_TXD); //UART Tx
        vos_iomux_define_input(42,IOMUX_IN_UART_RXD); //UART Rx
        vos_iomux_define_output(43,IOMUX_OUT_UART_RTS_N); //UART RTS#
        vos_iomux_define_input(44,IOMUX_IN_UART_CTS_N); //UART CTS#
    }
 
    uart_ctx.buffer_size = VOS_BUFFER_SIZE_128_BYTES;
    uart_init(0, &uart_ctx);
 
    tcbFirmware = vos_create_thread(29, 0x1000, firmware, 0);
 
    vos_start_scheduler();
 
main_loop:
    goto main_loop;
}
 
unsigned short ush;
 
void firmware(void)
{
    // UART ioctl request block
    common_ioctl_cb_t uart_iocb;
    char x[4];
    char mth;
    short sh;
    char ch;
 
    // open the USB and UART interfaces
    hUart = vos_dev_open(0);
 
    // setup the UART interface
    uart_iocb.ioctl_code = VOS_IOCTL_COMMON_ENABLE_DMA;
    vos_dev_ioctl(hUart,&uart_iocb);
 
    // set baud rate
    uart_iocb.ioctl_code = VOS_IOCTL_UART_SET_BAUD_RATE;
    uart_iocb.set.uart_baud_rate = UART_BAUD_9600;
    vos_dev_ioctl(hUart,&uart_iocb);
 
    // set flow control
    uart_iocb.ioctl_code = VOS_IOCTL_UART_SET_FLOW_CONTROL;
    uart_iocb.set.param = UART_FLOW_RTS_CTS;
    vos_dev_ioctl(hUart,&uart_iocb);
 
    // set data bits
    uart_iocb.ioctl_code = VOS_IOCTL_UART_SET_DATA_BITS;
    uart_iocb.set.param = UART_DATA_BITS_8;
    vos_dev_ioctl(hUart,&uart_iocb);
 
    // set stop bits
    uart_iocb.ioctl_code = VOS_IOCTL_UART_SET_STOP_BITS;
    uart_iocb.set.param = UART_STOP_BITS_1;
    vos_dev_ioctl(hUart,&uart_iocb);
 
    // set parity
    uart_iocb.ioctl_code = VOS_IOCTL_UART_SET_PARITY;
    uart_iocb.set.param = UART_PARITY_NONE;
    vos_dev_ioctl(hUart,&uart_iocb);
 
    stdioAttach(hUart);
 
    printf("\nNo format\n");
 
    ch = -46;
    printf("Decimal signed %d\n", ch);
    printf("Decimal unsigned %u\n", -46);
    sh = -48;
    printf("Decimal signed %d unsigned %u\n", sh, -47);
 
    ush = 0xface;
    printf("Hex caps %X lower %x\n", 0xfeed, ush);
 
    fprintf(stderr, "Character %c\n", 0x41);
 
    printf("String %s and %s\n", "here", "here!");
 
    printf("Pointers %p %p %p\n", &uart_iocb, &ch, &ush);
 
    printf("Escape d-quote \" s-quote \' tab \t bslash \\\n");
 
    fwrite("--HELLO--\r\n", 11, 1, stdout);
 
    for (mth = 1; mth <= sizeof(months)/sizeof(char*); mth++)
    {
        printf("Month %d is %s\n", mth, months[mth - 1]);
    }
}
Сам исходный код ф-ции я не знаю, т.к. он в билиотеке, открытого нет. Придётся обходиться малой кровью, сам не знаю как. А если скопировать параметры из ф-ции printf() которые есть в этом когде??
В общем сильно на меня не кричите))

Добавлено через 3 минуты
Задание звучит так: реализация ф-ций с переменным числом параметров на языке "с" и передача значений в такую ф-цию.
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
04.06.2011, 16:24     Как перенести параметры из ф-ции printf() в самодельную #22
C
1
2
main_loop:
    goto main_loop;
первый раз такое вижу... бесконечный цикл с помощью меток...
Uklunok
3 / 3 / 0
Регистрация: 08.05.2010
Сообщений: 135
04.06.2011, 16:32  [ТС]     Как перенести параметры из ф-ции printf() в самодельную #23
Тут походу просто в бесконечном цикле по УАРТ передаётся информация (ф-ция printf() выводит сообщения)
Evg
Эксперт С++Автор FAQ
 Аватар для Evg
16824 / 5245 / 320
Регистрация: 30.03.2009
Сообщений: 14,125
Записей в блоге: 26
04.06.2011, 17:35     Как перенести параметры из ф-ции printf() в самодельную #24
Цитата Сообщение от Uklunok Посмотреть сообщение
Собственно, чтобы более понятно было, мне нужно добавить в этот код ( это код для примера работы с функцией printf())
Добавить что?

Цитата Сообщение от Uklunok Посмотреть сообщение
Задание звучит так: реализация ф-ций с переменным числом параметров на языке "с" и передача значений в такую ф-цию
В посте #6 есть пример. Что в нём не так?

Вообще, внятно поставленный вопрос - это уже половина ответа. А мне думается, что никто до сих пор не понял, чего конкретно ты хочешь
Jupiter
Каратель
Эксперт C++
6542 / 3962 / 226
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
04.06.2011, 19:35     Как перенести параметры из ф-ции printf() в самодельную #25
Цитата Сообщение от Uklunok Посмотреть сообщение
Задание звучит так: реализация ф-ций с переменным числом параметров на языке "с" и передача значений в такую ф-цию.
и для чего сдесь выдерание параметров из printf ?
ValeryLaptev
Эксперт C++
1004 / 783 / 46
Регистрация: 30.04.2011
Сообщений: 1,595
04.06.2011, 20:02     Как перенести параметры из ф-ции printf() в самодельную #26
Сообщение было отмечено автором темы, экспертом или модератором как ответ
Вот информация о функциях с переменным числом параметров.

Функции с переменным числом параметров
Язык C++ вслед за С позволяет писать функции с переменным числом параметров. Одним из простых примеров может служить функция, вычисляющая среднее арифметическое своих аргументов. Другой уже классический пример — функция сцепления произвольного количества строк, которая является естественным обобщением функции сцепления двух строк.
Переменный список параметров задается в заголовке функции многоточием:
C++
1
int f()
Этот заголовок не вызывает у компилятора протестов. Такая запись означает, что при определении функции компилятору неизвестны ни количество параметров, ни их типы, и он, естественно, не может ничего проверить. Количество параметров и их типы становятся известными только при вызове функции.

Однако у программиста с написанием таких функций сразу возникают проблемы. Ведь имена параметров отсутствуют! Поэтому доступ можно осуществить только одним способом – косвенным, используя указатель. Вспомним, что все параметры при вызове помещаются в стек. Если мы каким-то образом установим указатель на начало списка параметров в стеке, то, манипулируя с указателем, мы, в принципе, можем «достать» все параметры!

Таким образом, список параметров совсем пустой быть не может, должен быть прописан хотя бы один явный параметр, адрес которого мы можем получить при выполнении программы. Заголовок такой функции может выглядеть так:
C++
1
int f(int k...)
Ни запятая, ни пробел после параметра не обязательны, хотя можно их и прописать.

Есть одно обстоятельство, которое ограничивает применение таких функций: при написании функции с переменным числом параметров помимо алгоритма обработки программист должен разрабатывать и алгоритм доступа к параметрам. Так что список необъявленных параметров не может быть совсем уж произвольным – в языке C++ не существует универсальных средств распознавания элементов этого списка. Это же означает, что передача аргумента не того типа, который задумывался, или не тем способом, который подразумевался при разработке, приведет к катастрофическим последствиям – компилятор-то ничего не проверяет.

Попробуем написать функцию, вычисляющую среднее арифметическое своих аргументов. Для этого требуется решить несколько проблем
- как установиться на список параметров в стеке;
- как «перебирать» параметры;
- как закончить перебор.
Для доступа к списку параметров нам потребуется указатель, значением которого будет адрес последнего явного параметра в списке. Ответ на второй вопрос очевиден – надо изменять значение этого указателя, чтобы переместиться на следующий параметр. Отсюда следует, что указатель должен быть типизированным, поскольку с бестиповым указателем нельзя выполнять арифметические операции. Это же означает, что программист при разработке функции с переменным числом параметров должен отчетливо себе представлять типы аргументов, которые будет обрабатывать функция. Кроме того, способ передачи параметров должен быть одинаковым для всех параметров: либо все – по значению, либо все – по ссылке, либо все – по указателю.

Ответ на последний вопрос не вызывает затруднений. Это можно сделать одним из двух способов:
- явно передать среди обязательных параметров количество аргументов;
- добавить в конец списка аргумент с уникальным значением, по которому будет определяться конец списка параметров;

И тот, и другой способ имеют право на жизнь — все определяется потребностями задачи и вкусами программиста. В данном случае сначала попробуем второй способ: последним значением списка параметров будет ноль (листинг 7.7).
C++
1
2
3
4
5
6
7
8
9
10
11
Листинг 7.7.  Вычисление среднего арифметического аргументов (ноль в конце)
double f(double n, ...) //--заголовок с переменным числом параметров
{   double *p = &n;     //--установились на начало списка параметров
    double sum = 0, count = 0;  
    while (*p)      //--пока аргумент не равен нулю
    { sum+=(*p);        //--суммируем аргумент
      p++;          //--«перемещаемся на следующий аргумент
      count++;      //--считаем  количество аргументов
    }
    return ((sum)?sum/count:0); //--вычисляем среднее
}
Вызов такой функции может выглядеть таким образом:
C++
1
double y = f(1.0, 2.0, 3.0, 4.0, 0.0);
Переменная y получит значение 2.5. Так как компилятор ничего не проверяет, то попытка вызвать такую функцию с целыми аргументами f(1,2,3,0) либо вызовет аварийный останов программы (это лучший вариант), либо в приводит к неверному (но правдоподобному — в этом главная опасность) результату.

Реализация функции, которая в качестве первого параметра получает количество аргументов, на первый взгляд, не вызывает затруднений. Однако, если первый аргумент – целое число, то требуется преобразование указателя. И тут не все варианты проходят. Не будет работать такой вариант:
C++
1
2
3
4
5
6
7
double f(int n, ...)            //--количество элементов
{   int *p = &n;            //--указатель – «целый»
    double sum = 0, count = n;
    for (;n--;(double*)p++)         //--преобразование int* ->double* 
      sum+=(*p); 
    return ((sum)?sum/count:0);
}
Такой вариант тоже неработоспособен
C++
1
2
3
4
5
6
7
double f(int n, ...)            //--количество элементов
{   double *p = (double *)&n;   //--преобразование адреса
    double sum = 0, count = n;
    for (;n--;p++)          //--изменение указателя 
      sum+=(*p); 
    return ((sum)?sum/count:0); 
}
Причина кроется в том, что изменение указателя производится на столько байт, сколько в памяти занимает базовый тип. В обоих случаях мы установились не на начало списка double-параметров, а на sizeof(int) байтов «раньше» — на целую переменную. И от этого адреса происходит изменение указателя на 8 байт (sizeof(double)), что приводит к совершенно неверным результатам. Решение заключается в том, чтобы сначала изменить «целый» указатель, а потом уже его преобразовать в double *. Так всегда необходимо делать, если тип первого параметра отличается от типов отсутствующих параметров (листинг 7.8).
C++
1
2
3
4
5
6
7
8
9
10
Листинг 7.8. Вычисление среднего арифметического аргументов (количество)
double f(int n, ...)            //--количество элементов
{  int *p = &n;
    p++;                //-3-установка «целого» на double
    double *pp = (double *)p;   //--преобразование типа указателя
    double sum = 0, count = n;
    for (;n--;pp++)             //--правильное увеличение на 8
       sum+=(*pp); 
    return ((sum)?sum/count:0);
}
В строке //-3- операция p++ устанавливает указатель на первый элемент списка параметров типа double. Для дальнейшего изменения указателя на 8 мы использовали преобразование типа указателя:
C++
1
double *pp = (double *)p;
После этой строки операция pp++ будет увеличивать указатель на sizeof(double)=8, что нам и требуется.

Мы использовали способ передачи параметров по значению. В этом случае в качестве фактических аргументов можно задавать произвольные выражения. Однако можно использовать и передачу ссылки – это несколько осложняет вызов, поскольку в этом случае в списке аргументов могут прописываться только переменные. Необходимо также помнить, что все фактические аргументы должны передаваться одинаковым способом. Тогда прототип первого варианта функции выглядит так (тело функции не изменяется):
C++
1
double f(double &n, ...)
При вызове можно использовать элементы массива:
C++
1
2
double m[] = {1.0,2.0,3.0,4.0,0.0};
cout <<f(m[0],m[1],m[2],m[3],m[4])<<endl;
Эта программа выведет на экран 2.5.

Язык C++ в качестве элементов переменного списка аргументов разрешает прописывать указатели. Однако обработка такого варианта вызывает сложности – нам требуется двойной косвенный доступ, а указатель для доступа к стеку — «одноразовый». Таким образом, если передавать параметры-указатели, то в приведенной выше программе (с первым параметром-количеством) значение *рр – это не число типа double, а адрес этого числа. Тут без «обмана» компилятора не обойтись, поскольку он просто так не пропускает преобразование «одноразовой» косвенности в двойную. Но мы помним, что все типизированные указатели, независимо от типа и косвенности всегда представляют собой адрес, размер которого в Intel – 4 байта. Тогда можно использовать union (листинг 7.9).
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
Листинг 7.9. Переменный список параметров-указателей (количество)
double f(int n, ...)
{  int *p = &n;     //--«одноразовый» указатель    
    p++;                    //--«достаем» список параметровd-указателей
   union Pointer 
   {double **pp; double *kp; }; //--«подстава» указателей
    Pointer A;
    A.kp = (double *)p;         //-«обманываем» компилятора
    double sum = 0, count = n;
    for (;n--;A.pp++)       //--изменяем двойной указатель!
         sum+=(**A.pp);         //--двойной доступ!
    return ((sum)?sum/count:0);
}
Хотя по стандарту такое использование union означает undefined behaviour (неопределенное поведение), и непереносимо, но на практике (например, на платформе Intel) работает хорошо. Однако при переносе на другую платформу надо будет проверять корректность работы такой функции.

Необходимо обратить внимание на то, что изменяем мы «двойной» указатель – «одноразовый» использовать нельзя, поскольку будет изменение на sizeof(double)=8 байт, а нам требуется изменение на sizeof(double*)= 4 байта. И при суммировании используется двойной косвенный доступ. Обращение к такой функции выполняется так:
c
C++
1
out <<f(2,&a,&b)<<endl;
Аналогичная функция без счетчика аргументов может использовать в качестве признака окончания списка параметров нулевой указатель. Но в данном случае «обманывать» компилятор не требуется — в функции непосредственно используется «двойной» указатель (листинг 7.10).
C++
1
2
3
4
5
6
7
8
9
10
Листинг 7.10. Переменный список параметров-указателей (ноль в конце)
double f(double *a, ...)
{   double **p = &a;        //--берем адрес-адреса
    double sum = 0, count = 0;
    while (*p!=0)       //-- NULL – прямо в списке параметров
    { sum+=(**p);       //--выбираем значения
       count++; p++;        //--бежим по списку
    }
    return ((sum)?sum/count:0);
}
Вызов такой функции выглядит так:
C++
1
f(&a,&b,0)
Особо обратите внимание на следующее: в списке параметров 0 – это значение, а не адрес. Поэтому в теле функции проверка окончания цикла делается с одной звездочкой, а не с двумя.
Напоследок осталось рассмотреть пример, в котором список указателей переменной длины составляют указатели на char. Мы выделяем этот случай по двум причинам:
- размер данных (char) меньше, чем размер указателя (char*) – в остальных случаях размер данных больше или равен размеру указателя;
- char* — это единственный указатель, вместо которого при вызове можно задавать не адрес.

Типичной функцией, в которой можно применить переменный список параметров, является функция сцепления произвольного количества строк в одну. Заголовок такой функции может выглядеть так:
C++
1
char *f(char *s1, ...)
Функция должна сначала вычислить количество памяти, необходимой для целевой строки, а потом уже помещать туда результат сцепления. Используем тот же прием, что и в предыдущем примере – последний параметр должен быть 0 (листинг 7.11).
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Листинг 7.11. Сцепление строк (ноль в конце)
char *f(char *s1, ...)
{ char **cp = &s1;          //--адрес первого указателя
   int len = 0;     
   // цикл для определения общей длины сцепляемых строк
   while (*cp) { len += strlen(*cp); cp++; }                        
  char *s = new char[len+1];    //--память для строки
  s[0]=0;                       //-- "очищаем" строку
// цикл для сцепления строк
  cp=&s1;                       //-- опять установка на 1-й параметр
  while (*cp) 
  {  strcat(s, *cp);            //-- прицепляем первую (и следующие)
     cp++;                      //-- перемещаемся на следующую
  }     
  return s;
}
Вызов такой функции может быть таким
C++
1
char *ss = f(s1, s2, s3, 0);
где s1, s2, s3 – это либо объявленные константы, либо переменные типа char *. Ту же функцию можно вызывать и с явно прописанными константами:
C++
1
char *sd = f(“First “,“Two  “,“Three “, 0);
Очевидно, вместо параметра-указателя (ссылки) можно подставлять выражение, имеющее результатом указатель (ссылку). В частности, на месте указателя на char можно вызвать функцию, которая вводит строку с клавиатуры.

Стандартные средства

В стандарт языка входит набор макросов для работы со списками параметров переменной длины, определенный в stdarg.h. При их использовании точно так же требуется указывать в списке явный параметр, объявить и установить на него указатель и перемещаться по списку, изменяя его. В конце списка должен стоять NULL. Макросы, обеспечивающие стандартный доступ к спискам параметров переменной длины, имеют следующий формат:
C++
1
2
3
void va_start(va_list prm, последний-явный-параметр);
тип va_arg(va_list prm, тип);
void va_end(va_list prm);
Тип указателя определяется с помощью оператора typedef как va_list. Макрос va_start устанавливает указатель типа va_list на явный параметр, макрос va_arg перемещает указатель на следующий параметр, а макрос va_end обнуляет указатель. Указанные макросы используются следующим образом:
1. в теле функции с переменным числом параметров до первого использования указанных макросов должно появиться объявление объекта типа va_list, например va_list LastP; фактически это является объявлением указателя;
2. указанный объект связывается с последним явным параметром (перед многоточием) переменного списка параметров с помощью макроса va_start, например va_start(LastP,P); таким образом происходит инициализация указателя;
3. передвижение по переменному списку параметров выполняется макросом va_arg. Для этого, как указано выше, тоже необходимо явно указывать тип очередного параметра, то есть программист должен его знать в момент написания программы. Если все параметры в списке целого типа, то вызов va_arg выглядит так: va_arg(LastP,int);
4. после всей обработки ставится вызов va_end, например va_end(LastP).

В качестве примера рассмотрим реализацию функции вычисления среднего арифметического (вариант с количеством аргументов) с использованием этих макросов (листинг 7.12).
C++
1
2
3
4
5
6
7
8
9
10
11
12
Листинг 7.12. Вычисление среднего с использование стандартных средств (количество)
double f(int n, double a, ...)
{   va_list p;          //--объявление указателя
    double sum = 0, count = 0;
    va_start(p, n);         //--инициализация указателя
    while(n--)          
    { sum+=va_arg(p,double);        //--перемещение указателя 
      count++; 
    }
    va_end(p);              //--«закрытие» указателя
    return ((sum)?sum/count:0);
}
Очень похоже выглядит и вариант с нулем в конце списка (листинг 7.13).
C++
1
2
3
4
5
6
7
8
9
10
11
Листинг 7.13. Вычисление среднего стандартными средствами (ноль в конце)
double f(double a, ...)
{   va_list p;          //--объявление указателя
    double sum = 0, count = 0;
    va_start(p, a);         //--инициализация указателя
    double k = a;           //--промежуточная переменная 
    do { sum+=k;  count++;
    } while(k=va_arg(p,double));    //--пока не ноль -передвигаемся
    va_end(p);              //--«закрыли» указатель
    return ((sum)? sum/count: 0);
}
Однако в этом случае удобно использовать цикл do while, так как указатель p сразу устанавливается на слагаемое. Передвижение по списку выполняется прямо в условии цикла, что обеспечивает одновременную проверку на ноль.
Evg
Эксперт С++Автор FAQ
 Аватар для Evg
16824 / 5245 / 320
Регистрация: 30.03.2009
Сообщений: 14,125
Записей в блоге: 26
04.06.2011, 23:39     Как перенести параметры из ф-ции printf() в самодельную #27
ValeryLaptev, в твоих примерах аргументы достаются не через va_arg, а через поинтерную арифметику. За такие статьи надо к стенке ставить, потому что начинающие начитаются такой ереси и начинают быдлокоды писать
ValeryLaptev
Эксперт C++
1004 / 783 / 46
Регистрация: 30.04.2011
Сообщений: 1,595
05.06.2011, 09:59     Как перенести параметры из ф-ции printf() в самодельную #28
Цитата Сообщение от Evg Посмотреть сообщение
ValeryLaptev, в твоих примерах аргументы достаются не через va_arg, а через поинтерную арифметику. За такие статьи надо к стенке ставить, потому что начинающие начитаются такой ереси и начинают быдлокоды писать
А вы про стандартные средства не увидели?
А во-вторых, надо знать, как НА САМОМ деле реализуются стандартные средства...
И не забывайте, что гроссмейстеры постоянно внушают: конь на краю доски - плохо! Но сами-то частенько так ходят! Все зависит от конкретной ситуации...
Ибо в-третьих, профи придумали это механизм для себя любимых. Если этого не пробовать, как становиться профи...
Вы про реализацию таблицы виртуальных функций помните? Указатель на указателе сидит, и указателем погоняет!
Uklunok
3 / 3 / 0
Регистрация: 08.05.2010
Сообщений: 135
05.06.2011, 11:56  [ТС]     Как перенести параметры из ф-ции printf() в самодельную #29
Всё ребят, понял что нужно. Извините, что морочил Вам голову
Постараюсь объяснить что требуется:
Есть функция myprintf(), по сути она должна делать тоже самое что и printf(), т.е. выводить сообщение.
К примеру нам нужно вывести на экран сообщение:
C
1
2
3
4
5
int num_i; 
float num_f; 
num_i = 5; 
num_f = 10.5; 
printf(“num_i = %d, num_f = %f”, num_i, num_f);
Только вместо printf(......); должно стоять myprintf(......);
Значит нужно сделать так, чтобы ф-ция myprintf() вызывала из библиотеки stdio ф-цию printf(), вставляла туда нужные нам параметры для вывода и вывела их на экран. Прототип ф-ции находится в stdio.h а библиотека вот stdio.a.
Как это сделать не знаю.
В общем должно выглядеть так: код который я вставлял, в нём к примеру есть строка:
C
1
printf("String %s and %s\n", "here", "here!");
Я хочу чтобы было так:
C
1
myprintf("String %s and %s\n", "here", "here!");
Ну соответсвенно остальные строчки с printf тоже меняем на myprintf. И сделать не через макросы.
Вот как). Задача осложняется тем, что это не БИЛДЕР и не ВИЖАК, а компилятор микропроцессора, так что всё должно быть в очень примитивном виде (без сложных конструкций языка СИ)
Спасибо за внимание.

Добавлено через 2 минуты
Кстати в файле stdio.h прототип ф-ции выглядит так:
C
1
2
// write to stdout
int    printf(const char *fmt, ...);
grizlik78
Эксперт C++
 Аватар для grizlik78
1882 / 1414 / 101
Регистрация: 29.05.2011
Сообщений: 2,958
05.06.2011, 12:00     Как перенести параметры из ф-ции printf() в самодельную #30
Ну так в уже упомянутом посте номер 6 и есть решение вашей задачи в чистом виде. Только макросы оказались ненужными
И какие такие сложные конструкции языка?
Uklunok
3 / 3 / 0
Регистрация: 08.05.2010
Сообщений: 135
05.06.2011, 12:08  [ТС]     Как перенести параметры из ф-ции printf() в самодельную #31
Я вставлял этот код в исходник в посте 21, компилятор ругался
Может что ни так вставил?
Nameless One
Эксперт С++
 Аватар для Nameless One
5753 / 3402 / 255
Регистрация: 08.02.2010
Сообщений: 7,393
05.06.2011, 12:11     Как перенести параметры из ф-ции printf() в самодельную #32
Uklunok, ну приведи что ли сообщения компилятора.
Uklunok
3 / 3 / 0
Регистрация: 08.05.2010
Сообщений: 135
05.06.2011, 12:20  [ТС]     Как перенести параметры из ф-ции printf() в самодельную #33
Вот сделал без макросов:
C
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
#include <stdio.h>
#include <stdarg.h>
 
void my_printf(const char *format, ...) 
{
        va_list args;
 
        printf ("MYPRINTF: ");
 
        va_start(args, format);
        /* обработка формата:
         * if (*format == '%') {
         *      switch(*format) {
         *     case 'd': число
         *      case 's': строка
         *      и так далее
         * }
         */
    vprintf(format, args);
        va_end(args);
}
int main() 
{
my_printf("%d.%d %s", 10, 15, "TEST");
}
Хочу спросить: Вот заголовочный файл stdarg.h от компилятора, в нём такие строки:
C
1
2
3
4
5
6
7
8
9
10
#ifndef STDARG_H
#define STDARG_H
 
typedef short va_list;
 
#define va_start(ap, v) (ap = (va_list) & v + sizeof(v))
#define va_arg(ap, t)   (*(t *) ((ap += sizeof(int)) - sizeof(int)))
#define va_end(ap)      (ap = (va_list) 0)
 
#endif                                 /* STDARG_H */
Т.е. код господина fasked будет работать стабильно?
Сейчас попробую вставить в исходник и откомпилировать.
Nameless One
Эксперт С++
 Аватар для Nameless One
5753 / 3402 / 255
Регистрация: 08.02.2010
Сообщений: 7,393
05.06.2011, 12:24     Как перенести параметры из ф-ции printf() в самодельную #34
Цитата Сообщение от Uklunok Посмотреть сообщение
Т.е. код господина fasked будет работать стабильно?
Сейчас попробую вставить в исходник и откомпилировать.
а почему бы и нет? Код стандартной библиотеки компилятора под определенную платформу в 99% случаев должен работать правильно.
Uklunok
3 / 3 / 0
Регистрация: 08.05.2010
Сообщений: 135
05.06.2011, 12:36  [ТС]     Как перенести параметры из ф-ции printf() в самодельную #35
Одна ошибка.
C
1
[VinC.exe] : src\Runtime.c line 87: (error) C1100 undeclared identifier 'vprintf'
Залез в <stdio.h> и прототипа ф-ции vprintf() не нашёл.
Можно поменять на другую? к примеру fprintf() ???

Добавлено через 53 секунды
int fprintf(FILE *, const char *fmt, ...);
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
05.06.2011, 12:39     Как перенести параметры из ф-ции printf() в самодельную #36
Uklunok, Без vprintf придется разбивать формат строку на токены и значения соответственно тоже (ну например массив указателей на void*) и вызывать printf с нужными параметрами
Nameless One
Эксперт С++
 Аватар для Nameless One
5753 / 3402 / 255
Регистрация: 08.02.2010
Сообщений: 7,393
05.06.2011, 12:39     Как перенести параметры из ф-ции printf() в самодельную #37
Цитата Сообщение от Uklunok Посмотреть сообщение
Одна ошибка.
C
1
[VinC.exe] : src\Runtime.c line 87: (error) C1100 undeclared identifier 'vprintf'
Залез в <stdio.h> и прототипа ф-ции vprintf() не нашёл.
Можно поменять на другую? к примеру fprintf() ???

Добавлено через 53 секунды
int fprintf(FILE *, const char *fmt, ...);
Она должна быть в stdarg.h
Uklunok
3 / 3 / 0
Регистрация: 08.05.2010
Сообщений: 135
05.06.2011, 12:41  [ТС]     Как перенести параметры из ф-ции printf() в самодельную #38
Нету там, я же привёл в сообщение содержимое файла.
А что такое токены?
Nameless One
Эксперт С++
 Аватар для Nameless One
5753 / 3402 / 255
Регистрация: 08.02.2010
Сообщений: 7,393
05.06.2011, 12:43     Как перенести параметры из ф-ции printf() в самодельную #39
Если не найдешь vprintf, нужно будет писать разбор форматной строки самому либо гуглить по ключевым словам "printf implementation"

Цитата Сообщение от Uklunok Посмотреть сообщение
Нету там, я же привёл в сообщение содержимое файла.
ну значить под твой контроллер стандартная библиотека кастрированная.
Токен - http://en.wikipedia.org/wiki/Token_(parser)#Token
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
05.06.2011, 12:49     Как перенести параметры из ф-ции printf() в самодельную
Еще ссылки по теме:

Калькулятор на Си. Как реализовать триногометрические ф-ции и функцию логарифм? C++
Чем ::printf предпочтительнее printf? C++
C++ Параметры printf

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
Uklunok
3 / 3 / 0
Регистрация: 08.05.2010
Сообщений: 135
05.06.2011, 12:49  [ТС]     Как перенести параметры из ф-ции printf() в самодельную #40
Цитата Сообщение от Nameless One Посмотреть сообщение
ну значить под твой контроллер стандартная библиотека кастрированная.
Токен - http://en.wikipedia.org/wiki/Token_(parser)#Token
Да на вряд ли такое есть, больше времени проищу.
А на русском можно ссылочку по разбору строки?
И сложно это делается?
Yandex
Объявления
05.06.2011, 12:49     Как перенести параметры из ф-ции printf() в самодельную
Ответ Создать тему
Опции темы

Текущее время: 01:32. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru