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, long 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);
- int s21_sprintf(char *output, char *str, ...)
- {
- va_list ap; /* point on next unnamed argument */
- va_start(ap, str); /* set 'ap' on 1-st unnamed argument */
- int out_len = 0; // массив, куда осуществляется вывод, он должен задаваться как аргумент s21_sprintf, но пока так
- for (char *p = str; *p; p++) //циклом пробегаем каждый символ строки (например "%*.*d %d % f %+-*d %% %n %*.*s %-#*.*o %.*i %*c %*x %#X\n")
- {
- if (*p !='%') // если символ не процент, то просто печатаем его
- {
- out_len ++;
- 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 == ' ') {
- if (flag1 == '+')
- flag1 = '+';
- else
- flag1 = *p;
- }
- if (*p == '-'){
- flag3 = *p;
- }
- ++p;
- } else {
- break;
- }
- }
- if (*p == '*') { //следующий символ, и если он ширина, то считываем её. Один раз проверяем наличие шиирны, так как ширину можно указывать только один раз, в отличии от флагов
- width = va_arg(ap, int);
- ++p;
- }
- if(*p == '.' && *(p+1) == '*') { //следующий символ, и если он точность, то считываем его.
- prec = va_arg(ap, int);
- p+=2;
- }
- if (*p == 'h' || *p == 'l') {
- lenght = *p;
- ++p;
- }
- switch(*p) // теперь смотрим спецификаторы.
- {
- case 'c':
- {
- char ival;
- ival = (char) va_arg(ap, int);
- if (flag3 != '-' && width != -1){
- for (int i = 0; i < width - 1; ++i) {
- output[strlen(output)] = ' ';
- out_len++;
- }
- }
- output[strlen(output)] = ival;
- out_len++;
- if (flag3 == '-' && width != -1){
- for (int i = 0; i < width - 1; ++i) {
- output[strlen(output)] = ' ';
- out_len++;
- }
- }
- break;
- }
- case 'u':
- {
- unsigned long int ival = 0;
- if (lenght == 'l')
- ival = (unsigned long int)va_arg(ap, unsigned long int);
- else
- ival = (unsigned long int)va_arg(ap, unsigned int);
- char buf[21]="";
- IntStr(buf,1, ival, -1, flag3, width, prec);
- out_len+=strlen(buf);
- strcat(output, buf);
- break;
- }
- case 'd':
- {
- long int ival = 0;
- if (lenght == 'l')
- ival = (long int)va_arg(ap, long int);
- else
- ival = (long int)va_arg(ap, int);
- char buf[50]="";
- IntStr(buf,1, ival, flag1, flag3, width, prec);
- out_len+=strlen(buf);
- strcat(output, buf);
- break;
- }
- case 'i':
- {
- long int ival = 0;
- if (lenght == 'l')
- ival = (long int)va_arg(ap, long int);
- else
- ival = (long int)va_arg(ap, int);
- char buf[50]="";
- IntStr(buf,1, ival, flag1, flag3, width, prec);
- out_len+=strlen(buf);
- strcat(output, buf);
- break;
- break;
- }
- case 'f':
- {
- double dval = 0.;
- dval = va_arg(ap, double);
- char buf[50]="";
- DoubleStr(buf, dval, flag1, flag3, width, prec);
- out_len+=strlen(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 && prec > 0)
- continue;
- buf = realloc(buf, k*sizeof(char));
- *(buf+k-1)=*sval;
- out_len++;
- }
- int l = strlen(buf);
- if (flag3 != '-') {
- for (int i = 0; i < width - l; ++i) {
- strcat(output, " ");
- out_len++;
- }
- }
- strcat(output, buf);
- free(buf);
- if (flag3 == '-') {
- for (int i = 0; i < width - l; ++i) {
- strcat(output, " ");
- out_len++;
- }
- }
- break;
- }
- case '%':
- {
- strcat(output, "%");
- out_len++;
- break;
- }
- default:
- {
- output[strlen(output)] = *p;
- break;
- }
- }
- }
- va_end(ap); /* clean all */
- printf("\n");
- return out_len;
- }
- int main ()
- {
- //s21_sprintf("%d %s",5,"HElllo");
- //printf("\n");
- char r[200];
- 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);
- //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));
- printf("%s", r);
- char output[100] ="";
- printf("\n");
- s21_sprintf(output, "%d %ldqq", 5, 55555555555);
- printf("%s\n", output);
- //printf("\n");
- char output1[100] ="";
- 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);
- printf("%s\n", output1);
- //s21_sprintf("%-+*.*f %-f",15, 0, 556.1835, 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, long 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;
- }
- int tr_len = len;
- if (prec != -1 && prec > len && is_int == 1) //если задана точность, то длина числа будет равна точности
- len = prec;
- int full_len = 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++;
- }
- if (is_int == 1)
- for (int h=0; h < prec - tr_len; h++){ //а это, если задана точность, вывод дополнительных нулей
- *(buf+j+len-i-1) = '0';
- i++;
- }
- if (flag3 == '-' && width != -1 && is_int == 1) { //если флаг - и задана ширина, то после числа пробелы печатаем
- for (j; j < width - full_len - fprec; ++j)
- *(buf+len-1+j+1) = ' ';
- }
- return(buf);
- }
- int LenInt(int n) {
- int len = 0;
- if (n < 0)
- n = n * (-1);
- while(n > 0) {
- len++;
- n /= 10;
- }
- return len;
- }
- char* DoubleStr(char *buf, long double n, char flag, char flag3, int width, int prec) {
- int len = LenInt((int)n);
- if (flag == ' ' && n >= 0 || flag == '+' && n > 0 || n < 0) //если заданы флаги пробел и + или число отрицательное, то фактическая длина больше на единицу, так как нужно печатать плюс, минус или пробел
- len++;
- if (prec == -1)
- prec = 6;
- IntStr(buf,0, (int)n, flag, flag3, width, prec);
- if (prec != 0)
- strcat(buf, ".");
- else
- strcat(buf, " ");
- if (n < 0) {
- n = n * (-1);
- }
- n = n - (long int)n;
- for (int i = 0; i < prec; i++) {
- n *= 10;
- buf[strlen(buf)] = n + '0';
- n = n - (int)n;
- }
- if (flag3 == '-') {
- for (int i = 0; i < width - (len + prec + 1); i ++)
- buf[strlen(buf)] = ' ';
- }
- return buf;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement