Advertisement
2607

ssprintf

Nov 1st, 2021 (edited)
449
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 12.80 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, 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. //длина 8-ричнго или 16-ричнго числа
  14. int Len8Int(int n, int base);
  15. //8 ричное и 16-ричное в строку
  16. char *convert(unsigned int num, int base, int symb, char flag2, char flag3, int width, int prec);
  17. //не используется
  18. char* Int8Str(char *buf, int n);
  19. //и эта функция не используется
  20. int LenDouble(double n);
  21. //эта функция тоже не используется
  22. int subspecifier(char *str, int p);
  23.  
  24. void s21_sprintf(char *str, ...)
  25. {
  26.   va_list ap;             /* point on next unnamed argument */
  27.   va_start(ap, str); /* set 'ap' on 1-st unnamed argument */
  28.   char *t = str;
  29.   char output[200] =""; // массив, куда осуществляется вывод, он должен задаваться как аргумент s21_sprintf, но пока так
  30.   for (char *p = str; *p; p++) //циклом пробегаем каждый символ строки (например "%*.*d %d % f %+-*d %% %n %*.*s %-#*.*o %.*i %*c %*x %#X\n")
  31.   {
  32.     //int curr = p - t;
  33.     //printf("%d\n" , curr);
  34.     if (*p !='%') // если символ не процент, то просто печатаем его
  35.     {
  36.       putchar(*p);
  37.       output[strlen(output)] = *p;
  38.       continue;
  39.     }
  40.     char flag1 = -1; //задаём значения подспецификаторов по умолчанию
  41.     char flag3 = -1;
  42.     int width = -1;
  43.     int prec = -1;
  44.     char lenght = -1;
  45.  
  46.     ++p; //переключаемся на следующий символ и если он один из флагов, то считываем его
  47.     while(1) { //цикл бесконечный, так как флагов можно ставить хоть сколько
  48.         if (*p == '-' || *p == '+' || *p == ' ') {
  49.           if (*p == '+' || *p == ' ') {
  50.               flag1 = *p;
  51.               printf("%c", flag1);
  52.           }
  53.           if (*p == '-'){
  54.               flag3 = *p;
  55.               printf("%c", flag3);
  56.           }
  57.           ++p;
  58.         } else {
  59.           break;
  60.         }
  61.     }
  62.     if (*p == '*') {  //следующий символ, и если он ширина, то считываем её. Один раз проверяем наличие шиирны, так как ширину можно указывать только один раз, в отличии от флагов
  63.       width = va_arg(ap, int);
  64.       printf("!%d!", width);
  65.       ++p;
  66.     }
  67.  
  68.     if(*p == '.' && *(p+1) == '*') { //следующий символ, и если он точность, то считываем его.
  69.       prec = va_arg(ap, int);
  70.       printf("!%d!", prec);
  71.       p+=2;
  72.     }
  73.  
  74.     if (*p == 'h' || *p == 'l') {
  75.       lenght = *p;
  76.       ++p;
  77.     }
  78.    
  79.     switch(*p)         // теперь смотрим спецификаторы. Нету e, E, g, G, u, p
  80.     {
  81.       case 'c':
  82.       {
  83.         char ival;
  84.         ival = (char) va_arg(ap, int);
  85.         printf ("%c", ival);
  86.         if (width != -1){
  87.           for (int i = 0; i < width - 1; ++i)
  88.             output[strlen(output)] = ' ';
  89.         }
  90.         output[strlen(output)] = ival;
  91.         break;
  92.       }
  93.       case 'd':
  94.       {
  95.         int ival = 0;
  96.         ival = va_arg(ap, int);
  97.         char buf[21]="";
  98.         IntStr(buf,1, ival, flag1, flag3, width, prec);
  99.         printf("%s", buf);
  100.         strcat(output, buf);
  101.         break;
  102.       }
  103.       case 'i':
  104.       {
  105.           int ival = 0;
  106.           ival = va_arg(ap, int);
  107.           char buff[21]="";
  108.           IntStr(buff,1, ival, flag1, flag3, width, prec);
  109.           printf("%s", buff);
  110.           strcat(output, buff);
  111.           break;
  112.       }
  113.       case 'f':
  114.       {
  115.         long double dval = 0.;
  116.         dval = (long double)va_arg(ap, double);
  117.         //printf("dval%f\n", dval);
  118.         char buf[21]="";
  119.         DoubleStr(buf, dval, flag1, flag3, width, prec);
  120.         printf("%s", buf);
  121.         strcat(output, buf);
  122.         break;
  123.       }
  124.       case 's':
  125.       {
  126.         char *buf = malloc(sizeof(char));
  127.         int k = 0;
  128.         for(char *sval = va_arg(ap, char *); *sval; sval++) {
  129.             k++;
  130.             if (prec < k)
  131.                 continue;
  132.             printf("%c", *sval);
  133.             buf = realloc(buf, k*sizeof(char));
  134.             *(buf+k-1)=*sval;
  135.         }
  136.         int l = strlen(buf);
  137.         if (flag3 != '-') {
  138.           for (int i = 0; i < width - l; ++i)
  139.               strcat(output, " ");
  140.         }
  141.         printf("%s", buf);
  142.         strcat(output, buf);
  143.         free(buf);
  144.         if (flag3 == '-') {
  145.           for (int i = 0; i < width - l; ++i)
  146.               strcat(output, " ");
  147.         }
  148.         break;
  149.       }
  150.       case '%':
  151.       {
  152.         printf("%%");
  153.         strcat(output, "%");
  154.         break;
  155.       }
  156.       default:
  157.       {
  158.         putchar(*p);
  159.         output[strlen(output)] = *p;
  160.         break;
  161.       }
  162.     }
  163.   }
  164.   va_end(ap); /* clean all */
  165.   printf("\n");
  166.   printf("%s\n", output);
  167. }
  168.  
  169. int main ()
  170. {
  171.  
  172.   //s21_sprintf("%*.*d %d % f %+-*d %% %*.*s %.*i %*c\n",9,6, 2888, -286, 4.0,6, 100,8, 3, "Hello", 7, 45674,8,'Q');
  173.   s21_sprintf("%*f %-f",12, 55.1, 5.2);
  174.   //s21_sprintf("%+*d", 6, 534);
  175.   //s21_sprintf("%.*d %d % f %+-*d %% %n %*.*s", 6, 2888, -286, 4.0,6, 100,10,3, "Hello");
  176.   //s21_sprintf("% *.*d %d",17,11, -28, -286);
  177.   //s21_sprintf("%0#*x %#X\n",8, 1023, 1023);
  178.   //s21_sprintf("%+d %f", 55, 4.45);
  179.   //s21_sprintf("Hello");
  180.   //s21_sprintf("%+*d",9, 28);
  181.   return 0;
  182. }
  183.  
  184.  
  185. char* IntStr(char *buf,int is_int, int n, char flag, char flag3, int width, int prec) {
  186.     //char *index = buf;
  187.     int len = LenInt(n);
  188.     int fprec = 0;                                                 //длина числа
  189.     if (prec != -1 && is_int == 0) {
  190.         fprec = prec+1;
  191.       printf("#%d#", len);
  192.     }
  193.     int tr_len = len;
  194.     if (prec != -1 && prec > len && is_int == 1)                                        //если задана точность, то длина числа будет равна точности
  195.       len = prec;
  196.     int full_len = len;
  197.     printf("$%d$", full_len);
  198.     int i = 0;
  199.     int j = 0;
  200.     if (flag == ' ' && n >= 0 || flag == '+' && n > 0 || n < 0)              //если заданы флаги пробел и + или число отрицательное, то фактическая длина больше на единицу, так как нужно печатать плюс, минус или пробел
  201.         full_len++;
  202.     if (flag3 == -1 && width != -1){                                       //если задана ширина и нет флага 0 или -, то печатаем сначала пробелы, затем число
  203.         for (j; j < width - full_len - fprec; ++j) {
  204.           *(buf+j) = ' ';
  205.         }
  206.     }
  207.     if (flag == ' ' && n >= 0) {                                          //если если флаг пробел, то перед числом ставим пробел
  208.       buf+=j;
  209.       *(buf++) = ' ';
  210.       buf-=j;
  211.     }
  212.     if (flag == '+' && n > 0) {                                           //если если флаг +, то перед положительным числом ставим плюс
  213.       buf+=j;
  214.       *(buf++) = '+';
  215.       buf-=j;
  216.     }
  217.     if (n < 0) {                                                           //если число отрицательно, то перед ним печатаем минус
  218.       buf+=j;
  219.         *(buf++) = '-';
  220.         buf-=j;
  221.         n = -n;
  222.     }
  223.     if (n == 0) {                                                       //если число ноль, то печатаем ноль (ноль приходится отдельно обрабатывать, иначе не работает)
  224.       buf+=j;
  225.         *(buf++) ='0';
  226.         buf-=j;
  227.     }
  228.     while (n > 0) {                                                 //непосредственно вывод самого числа
  229.         *(buf+j+len-i-1) = (n % 10) | '0';
  230.         n /= 10;
  231.         i++;
  232.         printf("%d ", i);
  233.     }
  234.     if (is_int == 1)
  235.         for (int h=0; h < prec - tr_len; h++){                        //а это, если задана точность, вывод дополнительных нулей
  236.             *(buf+j+len-i-1) = '0';
  237.             i++;
  238.             printf("%d ", i);
  239.         }
  240.    
  241.     if (flag3 == '-' && width != -1) {                            //если флаг - и задана ширина, то после числа пробелы печатаем
  242.         for (j; j < width - full_len; ++j)
  243.           *(buf+len-1+j+1) = ' ';
  244.     }
  245.     //*(buf+len) = '\0';
  246.     return(buf);
  247. }
  248.  
  249. int LenInt(int n) {
  250.     int len = 0;
  251.     if (n < 0)
  252.         n = n * (-1);
  253.     while(n > 0) {
  254.       len++;
  255.       n /= 10;
  256.     }
  257.     return len;
  258. }
  259.  
  260. int Len8Int(int n, int base) {
  261.     int len = 0;
  262.     while(n > 0) {
  263.       len++;
  264.       n /= base;
  265.     }
  266.     return len;
  267. }
  268.  
  269. char* DoubleStr(char *buf, long double n, char flag, char flag3, int width, int prec) {
  270.     //printf("q%f\n", n);
  271.     int len = LenInt(n);
  272.     if (prec == -1)
  273.       prec = 6;
  274.     IntStr(buf,0, (int)n, flag, flag3, width, prec);
  275.     strcat(buf, ".");
  276.     if (n < 0) {
  277.       n = n * (-1);
  278.     }
  279.     //printf("w%f\n", n);
  280.     n = n - (long int)n;
  281.     //printf("$%Lf$", n);
  282.     //n = n * pow(10, prec);
  283.     n = n * 1000000;
  284.     //printf("$%Lf$", n);
  285.     char buf1[21]="";
  286.     IntStr(buf1,0, (long long int)n, -1, -1, -1, -1);
  287.     strcat(buf, buf1);
  288.     //printf("%f\n", n);
  289.     /*
  290.     for (int i = 0; i < 6; i++) {
  291.         n *= 10;
  292.         //printf("i = %d n = %f (int)n = %d", i, n, (int)n);
  293.         //char c = n + '0';
  294.         //strcat(buf, &c);
  295.         buf[strlen(buf)] = n + '0';
  296.         n = n - (int)n;
  297.         //printf(" n = %f\n", n);
  298.     }
  299.     */
  300.     return buf;
  301. }
  302.  
  303. int LenDouble(double n) {
  304. }
  305.  
  306. char *convert(unsigned int num, int base, int symb, char flag2, char flag3, int width, int prec)
  307. {
  308.     //printf("#%d#", width);
  309.     printf("%d", flag3);
  310.     static char Representation[] = "0123456789ABCDEF";                  // если спецификатор X
  311.     static char Representation1[] = "0123456789abcdef";                //если спецификатор х
  312.     static char buffer[50];
  313.     char *ptr;
  314.  
  315.     ptr = &buffer[49];
  316.     *ptr = '\0';
  317.     int len = Len8Int(num , base);
  318.     int tr_len = len; //длина числа
  319.     if (prec != -1 && prec > len)
  320.         len = prec;
  321.     printf("len=%d", len);
  322.     if (flag2 == '#') {           //если есть флаг #, то фактическая ддлина числа увеличивается
  323.       if (base == 8)
  324.         len+=1;
  325.       else if (base == 16)
  326.         len+=2;
  327.     }
  328.     if (flag3 == '-' && width != -1) {                 //если флаг -, то печатаем число, а за ним пробелы
  329.       printf("$%d$", width);
  330.       for (int i = 0; i < width - len; ++i)
  331.         *--ptr = ' ';
  332.     }
  333.     do                                              //непосредственно печать числа
  334.     {
  335.       if (symb == 0)
  336.         *--ptr = Representation[num%base];
  337.       else
  338.         *--ptr = Representation1[num%base];
  339.         num /= base;
  340.     } while(num != 0);
  341.     for (int h=0; h < prec - tr_len; h++){                        //а это, если задана точность, вывод дополнительных нулей
  342.         *--ptr = '0';
  343.     }
  344.     if (flag3 == '0' && width != -1) {                  //если флаг 0, то сначала печатаем нули, а потом число
  345.       printf("$%d$", width);
  346.       for (int i = 0; i < width - len; ++i)
  347.         *--ptr = '0';
  348.     }
  349.     if (flag2 == '#') {                                  //печать дополнительных символов в связи с флагом #
  350.         if (base == 8) {
  351.           *--ptr = '0';
  352.         } else if (base == 16 && symb == 0){
  353.           *--ptr = 'X';
  354.           *--ptr = '0';
  355.         } else if (base == 16 && symb == 1){
  356.           *--ptr = 'x';
  357.           *--ptr = '0';
  358.         }
  359.         }
  360.     if (flag3 == -1 && width != -1) {                 //если есть ширина без флагов, то сначала пробелы, потом число
  361.       printf("$%d$", width);
  362.       for (int i = 0; i < width - len; ++i)
  363.         *--ptr = ' ';
  364.     }
  365.  return(ptr);
  366. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement