Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 10.07.2012, 13:20   #11
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
По умолчанию

Krok27, откуда ноль должен взяться?
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.
Пепел Феникса вне форума Ответить с цитированием
Старый 10.07.2012, 13:38   #12
Krok27
Форумчанин
 
Аватар для Krok27
 
Регистрация: 08.07.2010
Сообщений: 505
По умолчанию

В параметрах.

Код:
int sum ( int first , . . . )
{
va_list vl ;
int result = first ;
va_start (vl , first ) ;
while (first ! = 0 )
{
first = va_arg (vl , int ) ;
result += f irst ;
}
va_end (vl ) ;
return result ;
}
. . .
int x = sum ( 1 , 2 , 3 , 4 , 5 , 0 )
Как то так.
Знающий не говорит, говорящий не знает (С) Лао Цзы
Krok27 вне форума Ответить с цитированием
Старый 10.07.2012, 13:47   #13
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
По умолчанию

это пойдет только при однотипных параметрах и только при ограничении что 0 не может быть, то есть не случай ТС.
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.
Пепел Феникса вне форума Ответить с цитированием
Старый 10.07.2012, 14:04   #14
Krok27
Форумчанин
 
Аватар для Krok27
 
Регистрация: 08.07.2010
Сообщений: 505
По умолчанию

Ога. Но имеет быть место.
Знающий не говорит, говорящий не знает (С) Лао Цзы
Krok27 вне форума Ответить с цитированием
Старый 18.07.2012, 12:54   #15
stranger84
Пользователь
 
Регистрация: 09.07.2012
Сообщений: 11
По умолчанию

как я уже и говорил, прога идёт под контроллер где имеет значение размер кода, поэтому использование стандартных "тяжеловесных" функций типа printf нецелесообразно
в любом случае, вот что накропал.
говорю сразу, прога дико бажная, но мало ли..вдруг кому-нить пригодится


PHP код:
/*
(c) Анос Андрей
aka stranger84
*/

#include <stdarg.h>
#include <iostream>


void main()
{
    
char buff[100];
    
double b 5321.545;

    
aprintf(buff"+%d""\n+%0f+"'\0'654b);

    for(
int i=0buff[i]!='\0';i++)
        
std::cout << buff[i];
    
std::cout << std::endl;
}


/*
Значения параметров:
d, i    — десятичное знаковое число, размер по умолчанию, sizeof( int ). 
u        — десятичное беззнаковое число, размер по умолчанию sizeof( int );
f и F    — числа с плавающей запятой. Аргумент по умолчанию имеет размер double.
        Если полсе символа % и перед F стоит число, то такое кол-во цифр будет 
        отображатся ПОСЛЕ запятой. по умолчанию значение установлено на 2
        значащихся символа
        printf("%4f\n", 12345.1234567);    Вывод : 12345.1235
c        — вывод символа с кодом, соответствующим переданному аргументу; 
        переданное число приводится к типу unsigned char
s        — вывод строки с нулевым завершающим байтом

char aprintf(char *return_str,        ...        ,        ...)
                    ^                ^        ^        ^
                буфер        list of params    '\0'    list of vars
*/

char aprintf(char *return_str, ...)
{
    
char buf[50];
    
char *pbuf = &buf[0];

    
va_list pvalist;        
    
va_start(pvalistreturn_str);

    
// получаю list of parameters и запись во временный буфер 
    
char *formatList va_arg(pvalistchar*);
    while (
formatList != NULL){
        
pbuf strcopy(pbufformatList);
        
formatList va_arg(pvalistchar*);
    }
    
pbuf = &buf[0];

    
// здесь разбор строки из list of parameters
    // на предмет нахождения управляющего символа (%)
    
for(; *pbuf != '\0'pbuf++)
    {
        
// если обычный символ, то просто копировать в 
        // результирующую строку и продолжать цикл 
        
if(*pbuf != '%')
        {
            *
return_str = *pbuf;
            
return_str++;
            continue;
        }


        
// --------------------------------------------------
        // а вот сюда мы попадаем если текущий символ = '%'. 
        // Производится парсинг в зависимости от введённых параметров 

        
pbuf++;
        
        
// d, i — десятичное знаковое число
        
if( (*pbuf == 'd') || (*pbuf == 'D') ||
            (*
pbuf == 'i') || (*pbuf == 'I') )
        {
            
intToStr(va_arg(pvalistint), return_str);
            
return_str eatZeros(return_str);
            continue;
        }

        
// Параметр %f выводит число с плаваящей запятой 
        
if( (*pbuf == 'f') || (*pbuf == 'F') || 
            (*
pbuf >= '0') && (*pbuf <= '9') )
        {
            
// кол-во цифр будет отображатся ПОСЛЕ запятой. 
            // по умолчанию значение установлено на 2 символа
            
int numbers_after_point 2;
            if( (*
pbuf >= '0') && (*pbuf <= '9') )
            {
                
numbers_after_point = *pbuf '0';
                
pbuf++;
            }

            
// получаем число из стека
            
double drobn va_arg(pvalistdouble);
            
// округляем его до нужного нам знака
            
drobn round(drobnnumbers_after_point);
            
// получаю целую часть
            
int celoe = (int)drobn;         
            
// получаю дробную часть 
            
drobn drobn celoe;    
            
intToStr(celoereturn_str);
            
return_str eatZeros(return_str);
            *
return_str '.'
            *(++
return_str) = '\0';
            if (
drobn 0)
                
drobn = -drobn;
             
            
//постоянно умножая на число 10 я вытаскиваю из дробной части 
            //по одной цифре и тут же засовываю в результир строку.
            //функция IntToStr не использовалась т.к. невозможно избежать 
            //удаления значащих предварительных нулей перед числом в дробной части. 
            
for(int i 0<= numbers_after_pointi++)
            {
                
drobn drobn 10;
                *
return_str = (int)drobn '0';
                *(++
return_str) = '\0';
                
drobn drobn - (int)drobn;
            }
            continue;
        }

        
// Параметр %c выводит символ 
        
if( (*pbuf == 'c') || (*pbuf == 'C')  )
        {
            
// записываю символ в результирующую строку 
            
*return_str va_arg(pvalistunsigned char);
            
return_str++;
            continue;
        }

        
// Параметр %s выводит строку 
        
if( (*pbuf == 's') || (*pbuf == 'S')  )
        {
            
char *pTempStr va_arg(pvalistchar*);
            for(; *
pTempStr != '\0'pTempStr++, return_str++)
                *
return_str = *pTempStr;
            continue;
        }
    }
    
// парсинг завершён. "завершение" строки
    
*return_str '\0';
    
// закрытие указателя на структуру va_list
    
va_end(pvalist);
    
// если успешное завершение, то - 0
    
return 0;


Последний раз редактировалось stranger84; 18.07.2012 в 16:34.
stranger84 вне форума Ответить с цитированием
Старый 18.07.2012, 12:55   #16
stranger84
Пользователь
 
Регистрация: 09.07.2012
Сообщений: 11
По умолчанию

PHP код:
/*
(c) Анос Андрей
aka stranger84
*/

double round(double rounded_valuechar numbers_after_point)
{
    
// переменная которая будет хранить 10^numbers_after_point
    
int tenInStepen 1;

    
// возведение 10^numbers_after_point
    
for(int i 0numbers_after_pointi++)
        
tenInStepen tenInStepen 10;
    
rounded_value rounded_value tenInStepen;
    
// число по которому буду судить в какую сторону округлять
    // почему-то если написать 
    // char numb = (int) (rounded_value - (int)rounded_value) * 10; 
    // работать не будет о_О
    
char numb = (rounded_value - (int)rounded_value) * 10
    
rounded_value = (int)rounded_value;
    if( (
numb >= 5) && (numb <= 9) )
        
rounded_value++;
    
rounded_value rounded_value tenInStepen;
    return 
rounded_value;
}


//Функция копирующая строку src в строку dst
//Возвращает указатель на последний ('\0') символ dst
inline char *strcopy (char *dst, const char *src)
{
    for( ; *
src != '\0'src++, dst++)
        *
dst = *src;
    *
dst '\0';
    return 
dst;
}


// Процедура удаляющая из строки предваряющие нули после функции intToStr
// Пример: 
// str[] = "00000054321"; результир строка :
// str[] = "54321"
// Возвращаемое значение - указатель на конец (\0) отформатированной строки
char *eatZeros(char *str)
{
    
char *tmp str;
    
// если первый символ минус, то "перепрыгиваю" его
    
if (*tmp == '-'){
        
tmp++; str++;
    }
    
    for(; *
tmp == '0'tmp++);
    for(; *
tmp != '\0'tmp++, str++)
        *
str = *tmp;
    *
str '\0';
    return 
str;
}

/* процедура перевода переменной типа integer в массив char-ов 
Пример:
int iVar = 874905855;
char str[] = {'8','7','4','9','0','5','8','5','5'};
Для этого делим i сначала на самое большое число для выделения сотен тысяч, 
потом десятков тысяч, потом просто тясяч и прибавляем к ним ASCII код "0"

Возвращает указатель на последний элемент в строке (\0). Это будет нужно при 
преобразованиях float-ов чтобы дописывать в конец
*/
char *intToStr(int iVarchar *str)
{
    
// если разлагаемое число = 0, то нет смысла впустую гонять цикл когда 
    // можно сразу дать результат
    
if(iVar == 0)
    {
        *
str '0'; *(++str) = '\0';
        return 
str;
    }

    
// если число отрицательное, то результирующая строка 
    // дополняется символом "минус" перед массивом чисел 
    
if (iVar 0) {
        *
str '-'str++; iVar = -iVar;
    }

    
// переменные обозначающие числитель (NUMerator) 
    // и знаменатель (DENUMerator)
    
int num iVardenum;        
    for(
int i 10000000000i/10str++)
    {
        
denum num i;
        
num num i;
        *
str num '0';
        
num denum;
    }
    *
str '\0';

Основными бажными местами является :
1) результат функции double round(double, char), а в частности строка "rounded_value = rounded_value / tenInStepen;"
2) кусок кода
Код:
			for(uint8_t i = 0; i <= numbers_after_point; i++)
			{
				drobn = drobn * 10;
				*return_str = (int8_t)drobn + '0';
				*(++return_str) = '\0';
				drobn = drobn - (int32_t)drobn;
			}
в этих местах из-за погрешности в операциях с плав точкой вылазиют ну такие результаты что на голову не нализиет
например:
Код:
rounded_value = 2343; tenInStepen = 10;
rounded_value = rounded_value / tenInStepen;
rounded_value   <---- после деления == 234.29..
если подскажите как побороть эту напасть буду благодарен



также в планах модифицировать макрос va_arg чтобы он мог ещё и возвращать предыдущей указатель на что-то там из стека.
таким образом я могу избавится от временного буфера (а это экономия в 50 байт) + могу напрямую манипулировать данными через стек.

Думал сделать так:

Код:
//стандартная реализация в stdarg.h
va_arg(ap, type)	
	#define va_arg(ap, type) (*(type _FAR *)(((*(char _FAR *_FAR *)&
		(ap))+=((sizeof(type)+1) & 0xFFFE))-(((sizeof(type)+1) & 0xFFFE))))


// моя вариация
// если что-то неправильно ОЧЕНЬ приветствую ваши замечания т.к. если чесно, очень стрёмно попортить что-то в стеке
va_prev(ap, type)	
	#define va_prev(ap, type) (*(type _FAR *)(((*(char _FAR *_FAR *)&
		(ap))-=((sizeof(type)+1) & 0xFFFE))-(((sizeof(type)+1) & 0xFFFE))))

Последний раз редактировалось stranger84; 18.07.2012 в 16:35.
stranger84 вне форума Ответить с цитированием
Старый 18.07.2012, 14:15   #17
waleri
Старожил
 
Регистрация: 13.07.2012
Сообщений: 6,331
По умолчанию

Цитата:
Сообщение от stranger84 Посмотреть сообщение
как я уже и говорил, прога идёт под контроллер где имеет значение размер кода, поэтому использование стандартных "тяжеловесных" функций типа printf нецелесообразно
Вы накропали не менее тяжеловесную функцию. Даже если вы будете печатать только int все равно будет компилироваться *все* - поддрежка float и т.д. - вот отсюдя и идет тяжеловесность таких функций.

Судя по тому, что вы изпользуете std::cout значит у вас С++ - вы будете смеятся, но на С++ можно сделать не более тяжеловесный код, который зато будет typesafe и в некоторых случаях (когда нужны не все типы данных) менее тяжеловесным.
waleri вне форума Ответить с цитированием
Старый 18.07.2012, 15:38   #18
stranger84
Пользователь
 
Регистрация: 09.07.2012
Сообщений: 11
По умолчанию

to waleri не совсем так. первоначально я писал функцию под Visual Studio и там же её отлаживал (соотв нужен был терминал и void main). а потом готовую и "отлаженную" функцию впихнул в IAR.
stranger84 вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Передача аргументов в функции по ссылке skanku Общие вопросы C/C++ 2 11.01.2012 21:24
Передача в функцию неограниченного количества аргументов pronaks Общие вопросы C/C++ 4 13.12.2011 22:54
передача разных типов данных из Exel в Access zinch Microsoft Office Excel 1 10.11.2011 19:54
Передача аргументов в функцию. C++ Kholmansky Помощь студентам 2 15.09.2011 01:02
Как передать в функцию параметр разных типов borispnz Общие вопросы Delphi 5 06.02.2010 08:37