Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h>
- #include <stdarg.h>
- #include <string.h>
- #include <stdlib.h>
- #include <math.h>
- // целое число в строку
- char* IntStr(char *buf,int is_int, int n, char flag, char flag3, int width, int prec);
- // вещественное число в строку
- char* DoubleStr(char *buf, long double n, char flag, char flag3, int width, int prec);
- //длина целого числа
- int LenInt(int n);
- //длина 8-ричнго или 16-ричнго числа
- int Len8Int(int n, int base);
- //8 ричное и 16-ричное в строку
- char *convert(unsigned int num, int base, int symb, char flag2, char flag3, int width, int prec);
- //не используется
- char* Int8Str(char *buf, int n);
- //и эта функция не используется
- int LenDouble(double n);
- //эта функция тоже не используется
- int subspecifier(char *str, int p);
- void s21_sprintf(char *str, ...)
- {
- va_list ap; /* point on next unnamed argument */
- va_start(ap, str); /* set 'ap' on 1-st unnamed argument */
- char *t = str;
- char output[200] =""; // массив, куда осуществляется вывод, он должен задаваться как аргумент s21_sprintf, но пока так
- for (char *p = str; *p; p++) //циклом пробегаем каждый символ строки (например "%*.*d %d % f %+-*d %% %n %*.*s %-#*.*o %.*i %*c %*x %#X\n")
- {
- //int curr = p - t;
- //printf("%d\n" , curr);
- if (*p !='%') // если символ не процент, то просто печатаем его
- {
- putchar(*p);
- output[strlen(output)] = *p;
- continue;
- }
- char flag1 = -1; //задаём значения подспецификаторов по умолчанию
- char flag3 = -1;
- int width = -1;
- int prec = -1;
- char lenght = -1;
- ++p; //переключаемся на следующий символ и если он один из флагов, то считываем его
- while(1) { //цикл бесконечный, так как флагов можно ставить хоть сколько
- if (*p == '-' || *p == '+' || *p == ' ') {
- if (*p == '+' || *p == ' ') {
- flag1 = *p;
- printf("%c", flag1);
- }
- if (*p == '-'){
- flag3 = *p;
- printf("%c", flag3);
- }
- ++p;
- } else {
- break;
- }
- }
- if (*p == '*') { //следующий символ, и если он ширина, то считываем её. Один раз проверяем наличие шиирны, так как ширину можно указывать только один раз, в отличии от флагов
- width = va_arg(ap, int);
- printf("!%d!", width);
- ++p;
- }
- if(*p == '.' && *(p+1) == '*') { //следующий символ, и если он точность, то считываем его.
- prec = va_arg(ap, int);
- printf("!%d!", prec);
- p+=2;
- }
- if (*p == 'h' || *p == 'l') {
- lenght = *p;
- ++p;
- }
- switch(*p) // теперь смотрим спецификаторы. Нету e, E, g, G, u, p
- {
- case 'c':
- {
- char ival;
- ival = (char) va_arg(ap, int);
- printf ("%c", ival);
- if (width != -1){
- for (int i = 0; i < width - 1; ++i)
- output[strlen(output)] = ' ';
- }
- output[strlen(output)] = ival;
- break;
- }
- case 'd':
- {
- int ival = 0;
- ival = va_arg(ap, int);
- char buf[21]="";
- IntStr(buf,1, ival, flag1, flag3, width, prec);
- printf("%s", buf);
- strcat(output, buf);
- break;
- }
- case 'i':
- {
- int ival = 0;
- ival = va_arg(ap, int);
- char buff[21]="";
- IntStr(buff,1, ival, flag1, flag3, width, prec);
- printf("%s", buff);
- strcat(output, buff);
- break;
- }
- case 'f':
- {
- long double dval = 0.;
- dval = (long double)va_arg(ap, double);
- //printf("dval%f\n", dval);
- char buf[21]="";
- DoubleStr(buf, dval, flag1, flag3, width, prec);
- printf("%s", buf);
- strcat(output, buf);
- break;
- }
- case 's':
- {
- char *buf = malloc(sizeof(char));
- int k = 0;
- for(char *sval = va_arg(ap, char *); *sval; sval++) {
- k++;
- if (prec < k)
- continue;
- printf("%c", *sval);
- buf = realloc(buf, k*sizeof(char));
- *(buf+k-1)=*sval;
- }
- int l = strlen(buf);
- if (flag3 != '-') {
- for (int i = 0; i < width - l; ++i)
- strcat(output, " ");
- }
- printf("%s", buf);
- strcat(output, buf);
- free(buf);
- if (flag3 == '-') {
- for (int i = 0; i < width - l; ++i)
- strcat(output, " ");
- }
- break;
- }
- case '%':
- {
- printf("%%");
- strcat(output, "%");
- break;
- }
- default:
- {
- putchar(*p);
- output[strlen(output)] = *p;
- break;
- }
- }
- }
- va_end(ap); /* clean all */
- printf("\n");
- printf("%s\n", output);
- }
- int main ()
- {
- //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');
- s21_sprintf("%*f %-f",12, 55.1, 5.2);
- //s21_sprintf("%+*d", 6, 534);
- //s21_sprintf("%.*d %d % f %+-*d %% %n %*.*s", 6, 2888, -286, 4.0,6, 100,10,3, "Hello");
- //s21_sprintf("% *.*d %d",17,11, -28, -286);
- //s21_sprintf("%0#*x %#X\n",8, 1023, 1023);
- //s21_sprintf("%+d %f", 55, 4.45);
- //s21_sprintf("Hello");
- //s21_sprintf("%+*d",9, 28);
- return 0;
- }
- char* IntStr(char *buf,int is_int, int n, char flag, char flag3, int width, int prec) {
- //char *index = buf;
- int len = LenInt(n);
- int fprec = 0; //длина числа
- if (prec != -1 && is_int == 0) {
- fprec = prec+1;
- printf("#%d#", len);
- }
- int tr_len = len;
- if (prec != -1 && prec > len && is_int == 1) //если задана точность, то длина числа будет равна точности
- len = prec;
- int full_len = len;
- printf("$%d$", full_len);
- int i = 0;
- int j = 0;
- if (flag == ' ' && n >= 0 || flag == '+' && n > 0 || n < 0) //если заданы флаги пробел и + или число отрицательное, то фактическая длина больше на единицу, так как нужно печатать плюс, минус или пробел
- full_len++;
- if (flag3 == -1 && width != -1){ //если задана ширина и нет флага 0 или -, то печатаем сначала пробелы, затем число
- for (j; j < width - full_len - fprec; ++j) {
- *(buf+j) = ' ';
- }
- }
- if (flag == ' ' && n >= 0) { //если если флаг пробел, то перед числом ставим пробел
- buf+=j;
- *(buf++) = ' ';
- buf-=j;
- }
- if (flag == '+' && n > 0) { //если если флаг +, то перед положительным числом ставим плюс
- buf+=j;
- *(buf++) = '+';
- buf-=j;
- }
- if (n < 0) { //если число отрицательно, то перед ним печатаем минус
- buf+=j;
- *(buf++) = '-';
- buf-=j;
- n = -n;
- }
- if (n == 0) { //если число ноль, то печатаем ноль (ноль приходится отдельно обрабатывать, иначе не работает)
- buf+=j;
- *(buf++) ='0';
- buf-=j;
- }
- while (n > 0) { //непосредственно вывод самого числа
- *(buf+j+len-i-1) = (n % 10) | '0';
- n /= 10;
- i++;
- printf("%d ", i);
- }
- if (is_int == 1)
- for (int h=0; h < prec - tr_len; h++){ //а это, если задана точность, вывод дополнительных нулей
- *(buf+j+len-i-1) = '0';
- i++;
- printf("%d ", i);
- }
- if (flag3 == '-' && width != -1) { //если флаг - и задана ширина, то после числа пробелы печатаем
- for (j; j < width - full_len; ++j)
- *(buf+len-1+j+1) = ' ';
- }
- //*(buf+len) = '\0';
- return(buf);
- }
- int LenInt(int n) {
- int len = 0;
- if (n < 0)
- n = n * (-1);
- while(n > 0) {
- len++;
- n /= 10;
- }
- return len;
- }
- int Len8Int(int n, int base) {
- int len = 0;
- while(n > 0) {
- len++;
- n /= base;
- }
- return len;
- }
- char* DoubleStr(char *buf, long double n, char flag, char flag3, int width, int prec) {
- //printf("q%f\n", n);
- int len = LenInt(n);
- if (prec == -1)
- prec = 6;
- IntStr(buf,0, (int)n, flag, flag3, width, prec);
- strcat(buf, ".");
- if (n < 0) {
- n = n * (-1);
- }
- //printf("w%f\n", n);
- n = n - (long int)n;
- //printf("$%Lf$", n);
- //n = n * pow(10, prec);
- n = n * 1000000;
- //printf("$%Lf$", n);
- char buf1[21]="";
- IntStr(buf1,0, (long long int)n, -1, -1, -1, -1);
- strcat(buf, buf1);
- //printf("%f\n", n);
- /*
- for (int i = 0; i < 6; i++) {
- n *= 10;
- //printf("i = %d n = %f (int)n = %d", i, n, (int)n);
- //char c = n + '0';
- //strcat(buf, &c);
- buf[strlen(buf)] = n + '0';
- n = n - (int)n;
- //printf(" n = %f\n", n);
- }
- */
- return buf;
- }
- int LenDouble(double n) {
- }
- char *convert(unsigned int num, int base, int symb, char flag2, char flag3, int width, int prec)
- {
- //printf("#%d#", width);
- printf("%d", flag3);
- static char Representation[] = "0123456789ABCDEF"; // если спецификатор X
- static char Representation1[] = "0123456789abcdef"; //если спецификатор х
- static char buffer[50];
- char *ptr;
- ptr = &buffer[49];
- *ptr = '\0';
- int len = Len8Int(num , base);
- int tr_len = len; //длина числа
- if (prec != -1 && prec > len)
- len = prec;
- printf("len=%d", len);
- if (flag2 == '#') { //если есть флаг #, то фактическая ддлина числа увеличивается
- if (base == 8)
- len+=1;
- else if (base == 16)
- len+=2;
- }
- if (flag3 == '-' && width != -1) { //если флаг -, то печатаем число, а за ним пробелы
- printf("$%d$", width);
- for (int i = 0; i < width - len; ++i)
- *--ptr = ' ';
- }
- do //непосредственно печать числа
- {
- if (symb == 0)
- *--ptr = Representation[num%base];
- else
- *--ptr = Representation1[num%base];
- num /= base;
- } while(num != 0);
- for (int h=0; h < prec - tr_len; h++){ //а это, если задана точность, вывод дополнительных нулей
- *--ptr = '0';
- }
- if (flag3 == '0' && width != -1) { //если флаг 0, то сначала печатаем нули, а потом число
- printf("$%d$", width);
- for (int i = 0; i < width - len; ++i)
- *--ptr = '0';
- }
- if (flag2 == '#') { //печать дополнительных символов в связи с флагом #
- if (base == 8) {
- *--ptr = '0';
- } else if (base == 16 && symb == 0){
- *--ptr = 'X';
- *--ptr = '0';
- } else if (base == 16 && symb == 1){
- *--ptr = 'x';
- *--ptr = '0';
- }
- }
- if (flag3 == -1 && width != -1) { //если есть ширина без флагов, то сначала пробелы, потом число
- printf("$%d$", width);
- for (int i = 0; i < width - len; ++i)
- *--ptr = ' ';
- }
- return(ptr);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement