реализация fprintf C++ = СИ++ функция ФКН ВГУ 2012 = реализация printf c++

смотрите этот код =

// my_printf.cpp : Defines the entry point for the console application.
//
/* задача - Реализовать внутренности функции (каждому по 1) в среде разработки Microsoft Visual C++.
Описания функций брать в Microsoft Solution Developers Network(MSDN).

    24. fprintf
*/

#include "stdafx.h"
#include < vector >
#include < iterator >
// далее следуют объявления функций.
int welcome();
int my_printf(FILE *stream, char* frm,...);
void testme(); // 

// далее реализация
int _tmain(int argc, _TCHAR* argv[])
{
	 welcome(); // приветствие 

	 testme(); // запускаем тесты

	return 0;
}

int my_fprintf(FILE *file, char* frm,...) // это и есть "рабочая часть программы"
{
    #define IF_FILE if (file) // для краткости кода - если файл имеется - открываем его или пишем его.
	
	void* next= & frm; /* этот указатель мы будем сдвигать, если окажется, что
						в функцию переданы необязательные парамтеры.*/
	int i=0; // используем для перебора строки
	int prnt=0; // признак того, что текущий символ строки формата напечатан
	int j=0; // счётчик для хождения по строкам дополнительных параметров
	int ind=0; //  признак того, что предыдущий символ был %
	char** str1; /* вспомогательный указатель на строку формата(т.е. указатель на указатель на первый символ строки)  - 
			   нужен только чтобы переместить next первый раз - "переступить" через строку формата*/
	str1=((char**)next); // указатель на обязательную строку формата
	str1++;/*переставляем указатель на первый необязательный пареметр(предположительно переданный)*/
	next=str1;


 if (!file) // если файл для вывода не указан.

 {
	while (frm[i]) 
	{
		   if (ind==1) // если предыдущий символ был знаком формата
		   {
		     // prnt = 1; // поднимаем флаг,чтобы не печатать символ специфицирующий тип параметра 
			   ind = 0; // сбрасываем признак того, что ранее был знак %
			  switch (frm[i])  // ВАРИАНТЫ ПАРАМЕТРОВ
				{
				 case 's': // это или иное значение которому может быть равен параметр
					 {//printf("this's string \n");
						 char** str;// указатель на строку для работы с необязательными параметрами
						 str= (char**) next; // приводим указатель к нужному нам типу
						 char * strt = *str;

						 j=0;
						 while (*(*str+j)!='\0') // разыменовываем указатель
						  {
						   putchar(*(*str+j));// выводим символ
						   j++; // чтобы перейти к следующему символу
						  }
						 j=0; // обнуляем счётчик.
						  str++; //?????? какая разница - str++  next= str++ ?????????????
						 next= str;// "перешагиваем" через обработанный параметр
					 }
					break; // выход из перебора вариантов -иначе будет рассматриваться case 2

				  case 'i': // если это integer
					 {
					  int* value = (int*) next; // если i - значит приводим указаетль к типу int
					  

					  using namespace std; // пространство имён стандртной библиотеки.
					  vector< char > charVector; // используем шаблон вектор для типа char например
					  
					  int val  = *value;

					  // минус для отрицательного числа
					  if (val<0) 
						  {
							  val*=-1;
							  putchar('-');
					  }

					   value++;
					  next= value;// и сразу "перешагиваем" через область памяти размера "указатель на целое"
					  int dig; // очередная цифра
					  int small; // после деления на десять
					  char ch;//получаемый символ
					  while (val!=0) 
					  {
						  small =val/10;
						  dig = val -small*10 ; // получаем ASSCI код символа
						  ch= dig + 48 ;
						  charVector.push_back(ch); // получается , что мы записываем целую часть начиная с младшего символа
						  val = int(val/10);
					  } // по цикла мы получили все символы  - она лежат в charVector в обратной последовательности
					  // теперь выведем эти символы

					 // charVector.push_back('0');

					  typedef vector< char >::iterator char_iterator;
					  reverse_iterator< char_iterator > rev_end (charVector.begin()); // начало= конец обратного перечислителя                                                                 //         <------    
                       reverse_iterator < char_iterator > rev_iterator (charVector.end()); 
					 // j=0; // исользуем в качестве счётчика
	
						while (rev_iterator != rev_end) {
						   ch = (char) *rev_iterator;
							  //ch ='1';
							putchar(ch); /* Обратите внимание, что доступ к элементу
					можно получить посредством разыменования итератора */
						  ++rev_iterator;
                        }


					 }
				   break;
				    case 'd': // если это double
						{
							 double* value  = (double*) next;
							 double val = *value;
							 		  // минус для отрицательного числа
						  	 if (val<0) 
						    {
							  val*=-1;
							  putchar('-');
					         }
							 value++;
					        next= value;
				
							 
							 double  v1 = 123.34;
							 double * va = &v1;
							 double val3 = * va;
							 
							 
							 int val1=(int)val; // целая часть числа
							 double val2=val-val1; // дробная часть числа

							 // сначала обратываем и выводим целую часть числа
							 using namespace std; // пространство имён стандртной библиотеки.
							 vector<char> charVector1; // для цифр целой части числа
					  
							  int dig; // очередная цифра
							  int small; // после деления на десять
							  char ch;//получаемый символ
							  while (val1!=0)  // работаем с целой частью 
							  {
								  small =val1/10;
								  dig = val1 -small*10 ; // получаем ASSCI код символа
								  ch= dig + 48 ;
								  charVector1.push_back(ch); // получается , что мы записываем целую часть начиная с младшего символа
								  val1 = int(val1/10);
							  }

							   typedef vector < char >::iterator char_iterator;
					  reverse_iterator < char_iterator > rev_end (charVector1.begin()); // начало= конец обратного перечислителя                                                                 //         <------    
                       reverse_iterator< char_iterato r> rev_iterator (charVector1.end()); 
					 // j=0; // исользуем в качестве счётчика
	
						while (rev_iterator != rev_end) {
						   ch = (char) *rev_iterator;
							  //ch ='1';
							putchar(ch); /* Обратите внимание, что доступ к элементу
					можно получить посредством разыменования итератора */
						  ++rev_iterator;
                        }
						putchar('.');//  выводим точку которая разделяет целую и дробную часть числа
						
						// далее обратываем и выводим дробную часть числа
						 vector < char > charVector2; // для цифр дробной части числа
						while (val2!=0)
						 {
							dig =(int)( val2*10);
							val2 = val2*10 - dig;
							charVector2.push_back(dig+48);
						}
						vector < char >::iterator iter; // инициализируем перечислитель
						iter = charVector2.begin();
                         while (iter != charVector2.end())
						 {
						   putchar(*iter);
						   ++iter;
                          }
						
						}

						 break;
				default: // действия, если ничего выше не встретили
			         putchar(frm[i]);
				}
		   } else if (frm[i]=='%') ind=1; // если встречаем знак формата
		    else  putchar(frm[i]);
	           	//prnt=0; // опускаем флаг 
		 
	
		   i++; // переходим к следующему символу строки второго параметра
		 
	}
 } else // если дескриптор файла передан ВСЁ ТАКИ - ДАЛЕЕ ПОВТОР, НО С ВЫВОДОМ В ФАЙЛ ВМЕСТО КОНСОЛИ
	 {
		 while (frm[i]) 
	{
		   if (ind==1) // если предыдущий символ был знаком формата
		   {
		     // prnt = 1; // поднимаем флаг,чтобы не печатать символ специфицирующий тип параметра 
			   ind = 0; // сбрасываем признак того, что ранее был знак %
			  switch (frm[i])  // ВАРИАНТЫ ПАРАМЕТРОВ
				{
				 case 's': // это или иное значение которому может быть равен параметр
					 {//printf("this's string \n");
						 char** str;// указатель на строку для работы с необязательными параметрами
						 str= (char**) next; // приводим указатель к нужному нам типу
						 char * strt = *str;

						 j=0;
						 while (*(*str+j)!='\0') // разыменовываем указатель
						  {
						   fputc(*(*str+j),file);//putchar(*(*str+j));// выводим символ
						   j++; // чтобы перейти к следующему символу
						  }
						 j=0; // обнуляем счётчик.
						  str++; //?????? какая разница - str++  next= str++ ?????????????
						 next= str;// "перешагиваем" через обработанный параметр
					 }
					break; // выход из перебора вариантов -иначе будет рассматриваться case 2

				  case 'i': // если это integer
					 {
					  int* value = (int*) next; // если i - значит приводим указаетль к типу int
					  

					  using namespace std; // пространство имён стандртной библиотеки.
					  vector< char > charVector; // используем шаблон вектор для типа char например
					  
					  int val  = *value;

					  // минус для отрицательного числа
					  if (val<0) 
						  {
							  val*=-1;
							   fputc('-',file);
					  }

					   value++;
					  next= value;// и сразу "перешагиваем" через область памяти размера "указатель на целое"
					  int dig; // очередная цифра
					  int small; // после деления на десять
					  char ch;//получаемый символ
					  while (val!=0) 
					  {
						  small =val/10;
						  dig = val -small*10 ; // получаем ASSCI код символа
						  ch= dig + 48 ;
						  charVector.push_back(ch); // получается , что мы записываем целую часть начиная с младшего символа
						  val = int(val/10);
					  } // по цикла мы получили все символы  - она лежат в charVector в обратной последовательности
					  // теперь выведем эти символы

					 // charVector.push_back('0');

					  typedef vector< char >::iterator char_iterator;
					  reverse_iterator< char_iterator > rev_end (charVector.begin()); // начало= конец обратного перечислителя                                                                 //         <------    
                       reverse_iterator<char_iterator> rev_iterator (charVector.end()); 
					 // j=0; // исользуем в качестве счётчика
	
						while (rev_iterator != rev_end) {
						   ch = (char) *rev_iterator;
							  //ch ='1';
							fputc(ch,file); /* Обратите внимание, что доступ к элементу
					можно получить посредством разыменования итератора */
						  ++rev_iterator;
                        }


					 }
				   break;
				    case 'd': // если это double
						{
							 double* value  = (double*) next;
							 double val = *value;
							 		  // минус для отрицательного числа
						  	 if (val<0) 
						    {
							  val*=-1;
							  fputc('-',file);
					         }
							 value++;
					        next= value;
				
							 
							 double  v1 = 123.34;
							 double * va = &v1;
							 double val3 = * va;
							 
							 
							 int val1=(int)val; // целая часть числа
							 double val2=val-val1; // дробная часть числа

							 // сначала обратываем и выводим целую часть числа
							 using namespace std; // пространство имён стандртной библиотеки.
							 vector<char> charVector1; // для цифр целой части числа
					  
							  int dig; // очередная цифра
							  int small; // после деления на десять
							  char ch;//получаемый символ
							  while (val1!=0)  // работаем с целой частью 
							  {
								  small =val1/10;
								  dig = val1 -small*10 ; // получаем ASSCI код символа
								  ch= dig + 48 ;
								  charVector1.push_back(ch); // получается , что мы записываем целую часть начиная с младшего символа
								  val1 = int(val1/10);
							  }

							   typedef vector< char >::iterator char_iterator;
					  reverse_iterator< char_iterator > rev_end (charVector1.begin()); // начало= конец обратного перечислителя                                                                 //         <------    
                       reverse_iterator< char_iterator > rev_iterator (charVector1.end()); 
					 // j=0; // исользуем в качестве счётчика
	
						while (rev_iterator != rev_end) {
						   ch = (char) *rev_iterator;
							  //ch ='1';
							fputc(ch,file); /* Обратите внимание, что доступ к элементу
					можно получить посредством разыменования итератора */
						  ++rev_iterator;
                        }
						fputc('.',file);//  выводим точку которая разделяет целую и дробную часть числа
						
						// далее обратываем и выводим дробную часть числа
						 vector < char > charVector2; // для цифр дробной части числа
						while (val2!=0)
						 {
							dig =(int)( val2*10);
							val2 = val2*10 - dig;
							charVector2.push_back(dig+48);
						}
						vector < char >::iterator iter; // инициализируем перечислитель
						iter = charVector2.begin();
                         while (iter != charVector2.end())
						 {
						   fputc(*iter,file);
						   ++iter;
                          }
						
						}

						 break;
				default: // действия, если ничего выше не встретили
			         fputc(frm[i],file);
				}
		   } else if (frm[i]=='%') ind=1; // если встречаем знак формата
		    else  fputc(frm[i],file);
	           	//prnt=0; // опускаем флаг 
		 
	
		   i++; // переходим к следующему символу строки второго параметра
		 
	}
 }

	 return 1;
}

void testme() // используем для тестирования нашей реалзиации fprintf
{
	// просто вывод в консоль  
	my_fprintf(0,"1) %% string % = %s","THIS IS FIRST TEST \n");
	  my_fprintf(0,"2) this's text = %s -> this's text continuation))\n","THIS IS STR PARAM");
	  my_fprintf(0,"3) this's integer = %i -> this's text continuation))\n",123999);
	  my_fprintf(0,"4) this's double = %d -> this's text continuation after double))\n",123.555);
	  my_fprintf(0,"5)  negative double = %d -> this's text continuation after double))\n",-123.555);
	  my_fprintf(0,"6)negative  int = %i -> this's text continuation negative  int ))\n\n",-555);

	  my_fprintf(0,"7-1)COMPLEX TEST   STR = %s INT = %i  DOUBLE = %d))\n\n","my_str",-7845,-12.55);
	  my_fprintf(0,"7-2)COMPLEX TEST  INT = %i STR = %s  DOUBLE = %d))\n\n",-555,"my_str",-12.55);
	 // printf("%%");

	  // опять же тестируем нашу функцию , но теперь попытаемся записать что-нибудь в файл.
	  
	  FILE* fp = fopen("C:\\samer\\sam.txt","w");

	    my_fprintf(fp,"2) this's text = %s -> this's text continuation))\n","THIS IS STR PARAM");
		my_fprintf(fp,"7-2)COMPLEX TEST  INT = %i STR = %s  DOUBLE = %d))\n\n",-555,"my_str",-12.55);

	   fclose(fp); // закрываем файл

      getchar(); // чтобы консоль ждала нажатия клавиши
}

int welcome() // это просто)
{
	printf(" {{This is the my fprintf realization.}} \n");
	
	//getchar(); 

	return 0;
}