Advertisement
2607

ssprintf.c

Nov 24th, 2021
1,193
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 10.89 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdarg.h>
  3. #include <string.h>
  4. #include <stdlib.h>
  5. #include <math.h>
  6.  
  7. // целое число в строку
  8. char* IntStr(char *buf,int is_int, long int n, char flag, char flag3, int width, int prec);
  9. // вещественное число в строку
  10. char* DoubleStr(char *buf, long double n, char flag, char flag3, int width, int prec);
  11. //длина целого числа
  12. int LenInt(int n);
  13.  
  14. int s21_sprintf(char *output, char *str, ...)
  15. {
  16.   va_list ap;             /* point on next unnamed argument */
  17.   va_start(ap, str); /* set 'ap' on 1-st unnamed argument */
  18.   int out_len = 0; // массив, куда осуществляется вывод, он должен задаваться как аргумент s21_sprintf, но пока так
  19.   for (char *p = str; *p; p++) //циклом пробегаем каждый символ строки (например "%*.*d %d % f %+-*d %% %n %*.*s %-#*.*o %.*i %*c %*x %#X\n")
  20.   {
  21.     if (*p !='%') // если символ не процент, то просто печатаем его
  22.     {
  23.       out_len ++;
  24.       output[strlen(output)] = *p;
  25.       continue;
  26.     }
  27.     char flag1 = -1; //задаём значения подспецификаторов по умолчанию
  28.     char flag3 = -1;
  29.     int width = -1;
  30.     int prec = -1;
  31.     char lenght = -1;
  32.  
  33.     ++p; //переключаемся на следующий символ и если он один из флагов, то считываем его
  34.     while(1) { //цикл бесконечный, так как флагов можно ставить хоть сколько
  35.         if (*p == '-' || *p == '+' || *p == ' ') {
  36.           if (*p == '+' || *p == ' ') {
  37.               if (flag1 == '+')
  38.                 flag1 = '+';
  39.               else
  40.                 flag1 = *p;
  41.           }
  42.           if (*p == '-'){
  43.               flag3 = *p;
  44.           }
  45.           ++p;
  46.         } else {
  47.           break;
  48.         }
  49.     }
  50.     if (*p == '*') {  //следующий символ, и если он ширина, то считываем её. Один раз проверяем наличие шиирны, так как ширину можно указывать только один раз, в отличии от флагов
  51.       width = va_arg(ap, int);
  52.       ++p;
  53.     }
  54.  
  55.     if(*p == '.' && *(p+1) == '*') { //следующий символ, и если он точность, то считываем его.
  56.       prec = va_arg(ap, int);
  57.       p+=2;
  58.     }
  59.  
  60.     if (*p == 'h' || *p == 'l') {
  61.       lenght = *p;
  62.       ++p;
  63.     }
  64.    
  65.     switch(*p)         // теперь смотрим спецификаторы.
  66.     {
  67.       case 'c':
  68.       {
  69.         char ival;
  70.         ival = (char) va_arg(ap, int);
  71.         if (flag3 != '-' && width != -1){
  72.           for (int i = 0; i < width - 1; ++i) {
  73.             output[strlen(output)] = ' ';
  74.             out_len++;
  75.           }
  76.         }
  77.         output[strlen(output)] = ival;
  78.         out_len++;
  79.         if (flag3 == '-' && width != -1){
  80.           for (int i = 0; i < width - 1; ++i) {
  81.             output[strlen(output)] = ' ';
  82.             out_len++;
  83.           }
  84.         }
  85.         break;
  86.       }
  87.       case 'u':
  88.       {
  89.         unsigned long int ival = 0;
  90.         if (lenght == 'l')
  91.             ival = (unsigned long int)va_arg(ap, unsigned long int);
  92.         else
  93.             ival = (unsigned long int)va_arg(ap, unsigned int);
  94.         char buf[21]="";
  95.         IntStr(buf,1, ival, -1, flag3, width, prec);
  96.         out_len+=strlen(buf);
  97.         strcat(output, buf);
  98.         break;
  99.       }
  100.       case 'd':
  101.       {
  102.         long int ival = 0;
  103.         if (lenght == 'l')
  104.             ival = (long int)va_arg(ap, long int);
  105.         else
  106.             ival = (long int)va_arg(ap, int);
  107.         char buf[50]="";
  108.         IntStr(buf,1, ival, flag1, flag3, width, prec);
  109.         out_len+=strlen(buf);
  110.         strcat(output, buf);
  111.         break;
  112.       }
  113.       case 'i':
  114.       {
  115.         long int ival = 0;
  116.         if (lenght == 'l')
  117.             ival = (long int)va_arg(ap, long int);
  118.         else
  119.             ival = (long int)va_arg(ap, int);
  120.         char buf[50]="";
  121.         IntStr(buf,1, ival, flag1, flag3, width, prec);
  122.         out_len+=strlen(buf);
  123.         strcat(output, buf);
  124.         break;
  125.         break;
  126.       }
  127.       case 'f':
  128.       {
  129.         double dval = 0.;
  130.         dval = va_arg(ap, double);
  131.         char buf[50]="";
  132.         DoubleStr(buf, dval, flag1, flag3, width, prec);
  133.         out_len+=strlen(buf);
  134.         strcat(output, buf);
  135.         break;
  136.       }
  137.       case 's':
  138.       {
  139.         char *buf = malloc(sizeof(char));
  140.         int k = 0;
  141.         for(char *sval = va_arg(ap, char *); *sval; sval++) {
  142.             k++;
  143.             if (prec < k && prec > 0)
  144.                 continue;
  145.             buf = realloc(buf, k*sizeof(char));
  146.             *(buf+k-1)=*sval;
  147.             out_len++;
  148.         }
  149.         int l = strlen(buf);
  150.         if (flag3 != '-') {
  151.           for (int i = 0; i < width - l; ++i) {
  152.               strcat(output, " ");
  153.               out_len++;
  154.           }
  155.         }
  156.         strcat(output, buf);
  157.         free(buf);
  158.         if (flag3 == '-') {
  159.           for (int i = 0; i < width - l; ++i) {
  160.               strcat(output, " ");
  161.               out_len++;
  162.           }
  163.         }
  164.         break;
  165.       }
  166.       case '%':
  167.       {
  168.         strcat(output, "%");
  169.         out_len++;
  170.         break;
  171.       }
  172.       default:
  173.       {
  174.         output[strlen(output)] = *p;
  175.         break;
  176.       }
  177.     }
  178.   }
  179.   va_end(ap); /* clean all */
  180.   printf("\n");
  181.   return out_len;
  182. }
  183.  
  184. int main ()
  185. {
  186.   //s21_sprintf("%d %s",5,"HElllo");
  187.   //printf("\n");
  188.   char r[200];
  189.   sprintf(r, "%*.*d %d % f %+-*d %% %*.*s %.*i %*c %-*lu\n",9,6, 2888, -286, 4.0,6, 100,8, 3, "Hello", 7, 45674,8,'Q',7, 5555555555);
  190.   //printf("len = %d\n", sprintf(r, "%*.*d %d % f %+-*d %% %*.*s %.*i %*c %-*lu\n",9,6, 2888, -286, 4.0,6, 100,8, 3, "Hello", 7, 45674,8,'Q',7, 5555555555));
  191.   printf("%s", r);
  192.   char output[100] ="";
  193.   printf("\n");
  194.   s21_sprintf(output, "%d %ldqq", 5, 55555555555);
  195.   printf("%s\n", output);
  196.   //printf("\n");
  197.   char output1[100] ="";
  198.   s21_sprintf(output1, "%*.*d %d % f %+-*d %% %*.*s %.*i %*c %-*lu\n",9,6, 2888, -286, 4.0,6, 100,8, 3, "Hello", 7, 45674,8,'Q',7, 5555555555);
  199.   printf("%s\n", output1);
  200.   //s21_sprintf("%-+*.*f %-f",15, 0, 556.1835, 5.2);
  201.   //s21_sprintf("%+*d", 6, 534);
  202.   //s21_sprintf("%.*d %d % f %+-*d %% %n %*.*s", 6, 2888, -286, 4.0,6, 100,10,3, "Hello");
  203.   //s21_sprintf("%*.*d %d",17,11, -28, -286);
  204.   //s21_sprintf("%0#*x %#X\n",8, 1023, 1023);
  205.   //s21_sprintf("%+d %f", 55, 4.45);
  206.   //s21_sprintf("Hello");
  207.   //s21_sprintf("%+*d",9, 28);
  208.   return 0;
  209. }
  210.  
  211.  
  212. char* IntStr(char *buf,int is_int, long int n, char flag, char flag3, int width, int prec) {
  213.     //char *index = buf;
  214.     int len = LenInt(n);
  215.     int fprec = 0;                                                 //длина числа
  216.     if (prec != -1 && is_int == 0) {
  217.         fprec = prec+1;
  218.     }
  219.     int tr_len = len;
  220.     if (prec != -1 && prec > len && is_int == 1)                                        //если задана точность, то длина числа будет равна точности
  221.       len = prec;
  222.     int full_len = len;
  223.     int i = 0;
  224.     int j = 0;
  225.     if (flag == ' ' && n >= 0 || flag == '+' && n > 0 || n < 0)              //если заданы флаги пробел и + или число отрицательное, то фактическая длина больше на единицу, так как нужно печатать плюс, минус или пробел
  226.         full_len++;
  227.     if (flag3 == -1 && width != -1){                                       //если задана ширина и нет флага 0 или -, то печатаем сначала пробелы, затем число
  228.         for (j; j < width - full_len - fprec; ++j) {
  229.           *(buf+j) = ' ';
  230.         }
  231.     }
  232.     if (flag == ' ' && n >= 0) {                                          //если если флаг пробел, то перед числом ставим пробел
  233.       buf+=j;
  234.       *(buf++) = ' ';
  235.       buf-=j;
  236.     }
  237.     if (flag == '+' && n > 0) {                                           //если если флаг +, то перед положительным числом ставим плюс
  238.       buf+=j;
  239.       *(buf++) = '+';
  240.       buf-=j;
  241.     }
  242.     if (n < 0) {                                                           //если число отрицательно, то перед ним печатаем минус
  243.       buf+=j;
  244.         *(buf++) = '-';
  245.         buf-=j;
  246.         n = -n;
  247.     }
  248.     if (n == 0) {                                                       //если число ноль, то печатаем ноль (ноль приходится отдельно обрабатывать, иначе не работает)
  249.       buf+=j;
  250.         *(buf++) ='0';
  251.         buf-=j;
  252.     }
  253.     while (n > 0) {                                                 //непосредственно вывод самого числа
  254.         *(buf+j+len-i-1) = (n % 10) | '0';
  255.         n /= 10;
  256.         i++;
  257.     }
  258.     if (is_int == 1)
  259.         for (int h=0; h < prec - tr_len; h++){                        //а это, если задана точность, вывод дополнительных нулей
  260.             *(buf+j+len-i-1) = '0';
  261.             i++;
  262.         }
  263.    
  264.     if (flag3 == '-' && width != -1 && is_int == 1) {                            //если флаг - и задана ширина, то после числа пробелы печатаем
  265.         for (j; j < width - full_len - fprec; ++j)
  266.           *(buf+len-1+j+1) = ' ';
  267.     }
  268.     return(buf);
  269. }
  270.  
  271. int LenInt(int n) {
  272.     int len = 0;
  273.     if (n < 0)
  274.         n = n * (-1);
  275.     while(n > 0) {
  276.       len++;
  277.       n /= 10;
  278.     }
  279.     return len;
  280. }
  281.  
  282. char* DoubleStr(char *buf, long double n, char flag, char flag3, int width, int prec) {
  283.     int len = LenInt((int)n);
  284.     if (flag == ' ' && n >= 0 || flag == '+' && n > 0 || n < 0)              //если заданы флаги пробел и + или число отрицательное, то фактическая длина больше на единицу, так как нужно печатать плюс, минус или пробел
  285.         len++;
  286.     if (prec == -1)
  287.       prec = 6;
  288.     IntStr(buf,0, (int)n, flag, flag3, width, prec);
  289.     if (prec != 0)
  290.       strcat(buf, ".");
  291.     else
  292.       strcat(buf, " ");
  293.     if (n < 0) {
  294.       n = n * (-1);
  295.     }
  296.     n = n - (long int)n;
  297.    
  298.     for (int i = 0; i < prec; i++) {
  299.         n *= 10;
  300.         buf[strlen(buf)] = n + '0';
  301.         n = n - (int)n;
  302.     }
  303.     if (flag3 == '-') {
  304.       for (int i = 0; i < width - (len + prec + 1); i ++)
  305.         buf[strlen(buf)] = ' ';
  306.     }
  307.     return buf;
  308. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement