/
ne-ilyxa
/
C2_s21_stringplus
Обзор
Документация
Войти
/
ne-ilyxa
/
C2_s21_stringplus
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
develop
src/s21_sprintf.c
1 040 строк
30 KB
git1worker
Updated sprintf
24 янв 2024, 21:26
24 янв 2024, 21:26
364bc7a
Код
Авторство
О чём код?
#include <math.h> #include <stdarg.h> #include "s21_citoa.h" #include "s21_string.h" typedef int bool; #define true 1 #define false 0 typedef struct specifiers { bool isExist; bool c, d, e, E, f, g, G, o, s, u, x, X, p, percent; } Specf; typedef struct flags { bool isExist; bool minus, plus, space, sharp, zero; } Flags; typedef struct width { bool isExist; int num; bool star; } Width; typedef struct precision { bool isExist; int num; bool star; } Precision; typedef struct length { bool isExist; bool h, l, L; } Length; typedef struct all { Specf specf; Flags flags; Width width; Precision prec; Length len; } All; All *initAll() { All *all = (All *)malloc(sizeof(All)); s21_memset(all, 0, sizeof(All)); return all; } int stoi(const char *str) { while (*str == ' ') ++str; int value = 0; int sign = 1; if (*str == '-') sign = (int)-1, ++str; for (int i = 0; str[i] >= '0' && str[i] <= '9'; ++i) value = value * 10 + (int)(str[i] - '0'); return value * sign; } void longToString(long number, char str[]) { int i = 0; bool isLessZero = false; if (number < 0) { isLessZero = true; str[i++] = '-'; number = -number; } if (number != 0) { while (number != 0) { int digit = number % 10; str[i++] = digit + '0'; number /= 10; } str[i] = '\0'; int start = isLessZero, end = i - 1; while (start < end) { char temp = str[start]; str[start] = str[end]; str[end] = temp; start++; end--; } } else str[0] = '0', str[1] = '\0'; } void lftoa(long double n, char *res, unsigned afterpoint) { if (n < 0) *res = '-', ++res, n = -n; long double ipart; long double fpart = modfl(n, &ipart); if (fpart < 0) fpart = -fpart; long double fpartCp = fpart; for (unsigned i = 0; i < afterpoint; ++i) fpartCp = fpartCp * 10 - (long)(fpartCp * 10); int tmp_var = 5; // long double tmp_fpart = fpartCp * 10 - (long)(fpartCp * 10); // if ((int)(fpartCp * 10) == 5 && tmp_fpart >= -0.0000000000000001 && // tmp_fpart <= 0.0000000000000001) // tmp_var = 6; if ((int)(fpartCp * 10) >= tmp_var) { long double num = 1; for (unsigned i = 0; i < afterpoint; ++i) num /= 10; n += num; ipart = (long)n; fpart = n - (long double)ipart; } longToString(ipart, res); s21_size_t i = s21_strlen(res); if (afterpoint != 0) { res[i++] = '.'; // add dot if (fpart < 0) fpart = -fpart; while (afterpoint) { int tmp = (int)(fpart * 10); res[i++] = '0' + tmp; --afterpoint; fpart = fpart * 10 - (long)(fpart * 10); } } } void parseFlags(const char **format, All *all) { char c; while (c = **format, (c == '-' || c == '+' || c == ' ' || c == '#' || c == '0')) { all->flags.isExist = true; if (c == '-') all->flags.minus = true; else if (c == '+') all->flags.plus = true; else if (c == ' ') all->flags.space = true; else if (c == '#') all->flags.sharp = true; else if (c == '0') all->flags.zero = true; ++(*format); } } void parseWidth(const char **format, All *all) { all->width.isExist = true; if (**format == '*') { all->width.star = true; ++(*format); } else if (**format >= '0' && **format <= '9') { int i = 0; all->width.num = stoi(*format); for (; *((*format) + i) >= '0' && *((*format) + i) <= '9'; ++i) ; *format = (*format) + i; } else all->width.isExist = false; } void parsePrecision(const char **format, All *all) { if (**format == '.') { all->prec.isExist = true; ++(*format); if (**format == '*') { all->prec.star = true; ++(*format); } else if (**format >= '0' && **format <= '9') { int i = 0; all->prec.num = stoi(*format); for (; *((*format) + i) >= '0' && *((*format) + i) <= '9'; ++i) ; *format = (*format) + i; } } } void parseLen(const char **format, All *all) { /* It is support only one char, not ll */ all->len.isExist = true; if (**format == 'h') all->len.h = true; else if (**format == 'l') all->len.l = true; else if (**format == 'L') all->len.L = true; else all->len.isExist = false, --(*format); ++(*format); } void parseSpecifier(const char *format, All *all) { all->specf.isExist = true; if (*format == 'd') all->specf.d = true; else if (*format == 'c') all->specf.c = true; else if (*format == 'f') all->specf.f = true; else if (*format == 'u') all->specf.u = true; else if (*format == 's') all->specf.s = true; else if (*format == 'g') all->specf.g = true; else if (*format == 'G') all->specf.G = true; else if (*format == 'e') all->specf.e = true; else if (*format == 'E') all->specf.E = true; else if (*format == 'x') all->specf.x = true; else if (*format == 'X') all->specf.X = true; else if (*format == 'o') all->specf.o = true; else if (*format == 'p') all->specf.p = true; else if (*format == '%') all->specf.percent = true; else all->specf.isExist = false; } #define insertOneAtBegin(buff, _charForInsert) \ { \ char currChar = buff[0]; \ buff[0] = _charForInsert; \ char nextChar; \ int i_ = 1; \ do { \ nextChar = buff[i_]; \ buff[i_] = currChar; \ currChar = nextChar; \ ++i_; \ } while (buff[i_] != '\0'); \ buff[i_] = nextChar; \ buff[i_ + 1] = '\0'; \ } void widthAligner(char *p_tmpBuffer, All *all, char charForInsert) { int currWidth; if (charForInsert == '0' && (p_tmpBuffer[0] == '-' || p_tmpBuffer[0] == '+')) { ++p_tmpBuffer; --all->width.num; } while (currWidth = s21_strlen(p_tmpBuffer), currWidth < all->width.num) { /* Offset to the right while currWidth < num */ insertOneAtBegin(p_tmpBuffer, charForInsert); } } void precAligner(char *p_tmpBuffer, All *all) { int currNumDigits; if ((p_tmpBuffer[0] == '-' || all->flags.plus)) { if (!all->flags.plus || p_tmpBuffer[0] == '-') ++p_tmpBuffer; //--all->width.num; } while (currNumDigits = s21_strlen(p_tmpBuffer), currNumDigits < all->prec.num) { /* Offset to the right while currNumDigits < num */ insertOneAtBegin(p_tmpBuffer, '0'); } } int max(int a, int b) { return a > b ? a : b; } #define endActions() \ { \ s21_strcpy(buffer + posInBuffer, p_tmpBuffer); \ *(buffer + posInBuffer + s21_strlen(p_tmpBuffer)) = '\0'; \ free(p_tmpBuffer); \ } #define built_inHelperForPlusSpace() \ { \ if (all->flags.plus) { \ if (value >= 0) { \ *(buffer + posInBuffer) = '+'; \ ++posInBuffer; \ if (all->width.num) --all->width.num; \ } \ } else if (all->flags.space) { \ if (value >= 0) { \ *(buffer + posInBuffer) = ' '; \ ++posInBuffer; \ if (all->width.num) --all->width.num; \ } \ } \ } int handle_d(va_list *factor, All *all, s21_size_t posInBuffer, char *buffer) { long value = 0; int rv = 1; if (all->width.star) all->width.num = va_arg(*factor, int); if (all->prec.star) all->prec.num = va_arg(*factor, int); char *p_tmpBuffer = (char *)malloc(max(all->width.num, all->prec.num) + 30); /* Buffer should be init with zeros */ s21_memset(p_tmpBuffer, 0, max(all->width.num, all->prec.num) + 30); if (all->len.isExist) { if (all->len.h) { value = (short)va_arg(*factor, int); } else if (all->len.l) value = va_arg(*factor, long); else rv = 0; } else value = va_arg(*factor, int); built_inHelperForPlusSpace(); longToString(value, p_tmpBuffer); if (all->prec.isExist) precAligner(p_tmpBuffer, all); if (all->width.isExist) { if (all->width.num != 0 && all->flags.minus) { /* Align by left edge */ int currWidth; while (currWidth = s21_strlen(p_tmpBuffer), currWidth < all->width.num) { p_tmpBuffer[currWidth] = ' '; p_tmpBuffer[currWidth + 1] = '\0'; } } else if (all->width.num != 0 && all->flags.zero) { widthAligner(p_tmpBuffer, all, '0'); } else if (all->width.num != 0) { /* Align by right edge with inserting ' ' */ widthAligner(p_tmpBuffer, all, ' '); } } endActions(); return rv; } int handle_c(va_list *factor, All *all, s21_size_t posInBuffer, char *buffer) { int rv = 1; int value; if (all->width.star) all->width.num = va_arg(*factor, int); char *p_tmpBuffer = (char *)malloc(all->width.num + 2); /* Buffer should be init with zeros */ s21_memset(p_tmpBuffer, 0, all->width.num + 2); /* Without handling wchar_t */ value = (char)va_arg(*factor, int); p_tmpBuffer[0] = value; p_tmpBuffer[1] = '\0'; if (all->width.isExist) { if (all->width.num != 0 && all->flags.minus) { /* Align by left edge */ int currWidth; while (currWidth = s21_strlen(p_tmpBuffer), currWidth < all->width.num) { p_tmpBuffer[currWidth] = ' '; p_tmpBuffer[currWidth + 1] = '\0'; } } else if (all->width.num != 0) { /* Align by right edge with inserting ' ' */ int currWidth; while (currWidth = s21_strlen(p_tmpBuffer), currWidth < all->width.num) { /* Offset to the right while currWidth < num */ insertOneAtBegin(p_tmpBuffer, ' '); } } } endActions(); return rv; } int handle_f(va_list *factor, All *all, s21_size_t posInBuffer, char *buffer) { long double value = 0; int rv = 1; unsigned len; if (all->width.star) all->width.num = va_arg(*factor, int); if (all->prec.star) all->prec.num = va_arg(*factor, int); char *p_tmpBuffer = (char *)malloc(max(all->width.num, all->prec.num) + 50); /* Buffer should be init with zeros */ s21_memset(p_tmpBuffer, 0, max(all->width.num, all->prec.num) + 50); if (all->len.L) { value = va_arg(*factor, long double); } else value = va_arg(*factor, double); if (all->flags.space && !all->flags.plus) { if (value >= 0) { *(buffer + posInBuffer) = ' '; ++posInBuffer; if (all->width.num) --all->width.num; } } if (all->prec.isExist) { len = all->prec.num; } else len = 6; /* Computing len of an integer part */ // int wholeLen = len; // for (; f_cp * sign >= 10 && rv; ++wholeLen) f_cp /= 10; // gcvt(value, wholeLen, p_tmpBuffer); lftoa(value, p_tmpBuffer, len); if (all->prec.isExist && value >= 0 - 0.000000000000001 && value <= 0 + 0.000000000000001) { if (p_tmpBuffer[2] >= '6') p_tmpBuffer[0] = '1'; else p_tmpBuffer[0] = '0'; p_tmpBuffer[1] = '\0'; } if (!(all->prec.isExist && all->prec.num == 0) || all->flags.sharp) { /* If buffer does not contain '.' */ char *ptrDot = s21_strstr(p_tmpBuffer, "."); if (!ptrDot && rv) { int j = 0; for (; *(p_tmpBuffer + j) != '\0'; ++j) ; ptrDot = p_tmpBuffer + j; *(p_tmpBuffer + j++) = '.'; *(p_tmpBuffer + j++) = '\0'; } /* Zero padding */ for (int j = 0; s21_strlen(ptrDot) < len + 1 && rv; ++j) { if (*(p_tmpBuffer + j) == '\0') { *(p_tmpBuffer + j) = '0'; *(p_tmpBuffer + j + 1) = '\0'; } } } if (all->width.isExist && all->width.num != 0) { if (all->flags.plus && value >= 0) { insertOneAtBegin(p_tmpBuffer, '+'); } if (all->width.num && all->flags.minus) { /* Align by left edge */ int currWidth; while (currWidth = s21_strlen(p_tmpBuffer), currWidth < all->width.num) { p_tmpBuffer[currWidth] = ' '; p_tmpBuffer[currWidth + 1] = '\0'; } } else if (all->width.num && all->flags.zero) { // if (all->flags.plus && value >= 0) { // insertOneAtBegin(p_tmpBuffer, '+') // } widthAligner(p_tmpBuffer, all, '0'); } else if (all->width.num) { /* Align by right edge with inserting ' ' */ widthAligner(p_tmpBuffer, all, ' '); } } else if (all->flags.plus && value >= 0) { insertOneAtBegin(p_tmpBuffer, '+'); } endActions(); return rv; } int handle_u(va_list *factor, All *all, s21_size_t posInBuffer, char *buffer) { unsigned long value = 0; int rv = 1; if (all->width.star) all->width.num = va_arg(*factor, int); if (all->prec.star) all->prec.num = va_arg(*factor, int); char *p_tmpBuffer = (char *)malloc(max(all->width.num, all->prec.num) + 30); /* Buffer should be init with zeros */ s21_memset(p_tmpBuffer, 0, max(all->width.num, all->prec.num) + 30); if (all->len.isExist) { if (all->len.h) { value = (unsigned short)va_arg(*factor, unsigned); } else if (all->len.l) value = va_arg(*factor, unsigned long); else rv = 0; } else value = va_arg(*factor, unsigned); longToString(value, p_tmpBuffer); if (all->prec.isExist) precAligner(p_tmpBuffer, all); if (all->width.isExist && rv) { if (all->width.num != 0 && all->flags.minus) { /* Align by left edge */ int currWidth; while (currWidth = s21_strlen(p_tmpBuffer), currWidth < all->width.num) { p_tmpBuffer[currWidth] = ' '; p_tmpBuffer[currWidth + 1] = '\0'; } } else if (all->width.num != 0 && all->flags.zero) { widthAligner(p_tmpBuffer, all, '0'); } else if (all->width.num != 0) { /* Align by right edge with inserting ' ' */ widthAligner(p_tmpBuffer, all, ' '); } } endActions(); return rv; } int handle_s(va_list *factor, All *all, s21_size_t posInBuffer, char *buffer) { int rv = 1; int j = 0; if (all->width.star) all->width.num = va_arg(*factor, int); if (all->prec.star) all->prec.num = va_arg(*factor, int); char *strToInsert = va_arg(*factor, char *); char *p_tmpBuffer = (char *)malloc( max(max(all->width.num, all->prec.num), s21_strlen(strToInsert)) + 1); /* Buffer should be init with zeros */ /* Without handling wchar_t */ s21_memset( p_tmpBuffer, 0, max(max(all->width.num, all->prec.num), s21_strlen(strToInsert)) + 1); for (; strToInsert[j] != '\0' && (!all->prec.isExist || j < all->prec.num); ++j) p_tmpBuffer[j] = strToInsert[j]; p_tmpBuffer[j] = '\0'; if (all->width.isExist && rv) { /* TODO: s21_strlen strcpy should be replaced */ if (all->width.num != 0 && all->flags.minus) { /* Align by left edge */ int currWidth; while (currWidth = s21_strlen(p_tmpBuffer), currWidth < all->width.num) { p_tmpBuffer[currWidth] = ' '; p_tmpBuffer[currWidth + 1] = '\0'; } } else if (all->width.num != 0) { /* Align by right edge with inserting ' ' */ widthAligner(p_tmpBuffer, all, ' '); } } endActions(); return rv; } int handle_percent(va_list *factor, All *all, s21_size_t posInBuffer, char *buffer) { int rv = 1; int value; if (all->width.star) all->width.num = va_arg(*factor, int); char *p_tmpBuffer = (char *)malloc(all->width.num + 2); /* Buffer should be init with zeros */ s21_memset(p_tmpBuffer, 0, all->width.num + 2); value = '%'; p_tmpBuffer[0] = value; p_tmpBuffer[1] = '\0'; endActions(); return rv; } int handle_o(va_list *factor, All *all, s21_size_t posInBuffer, char *buffer) { /* This function needs refactoring */ int rv = 1; unsigned long value = 0; if (all->width.star) all->width.num = va_arg(*factor, int); if (all->prec.star) all->prec.num = va_arg(*factor, int); char *p_tmpBuffer = (char *)malloc(max(all->width.num, all->prec.num) + 30); /* Buffer should be init with zeros */ s21_memset(p_tmpBuffer, 0, max(all->width.num, all->prec.num) + 30); if (all->len.isExist) { if (all->len.h) { value = (unsigned short)va_arg(*factor, unsigned); } else if (all->len.l) value = va_arg(*factor, unsigned long); else rv = 0; } else value = va_arg(*factor, unsigned); citoa(value, p_tmpBuffer, 8); if (all->flags.sharp && value) { insertOneAtBegin(p_tmpBuffer, '0'); } if (all->prec.isExist) { if (value == 0 && all->prec.num == 0) p_tmpBuffer[0] = '\0'; else precAligner(p_tmpBuffer, all); } if (all->width.isExist) { if (all->width.num != 0 && all->flags.minus) { /* Align by left edge */ int currWidth; while (currWidth = s21_strlen(p_tmpBuffer), currWidth < all->width.num) { p_tmpBuffer[currWidth] = ' '; p_tmpBuffer[currWidth + 1] = '\0'; } } else if (all->width.num != 0 && all->flags.zero) { widthAligner(p_tmpBuffer, all, '0'); } else if (all->width.num != 0) { /* Align by right edge with inserting ' ' */ widthAligner(p_tmpBuffer, all, ' '); } } endActions(); return rv; } int handle_p(va_list *factor, All *all, s21_size_t posInBuffer, char *buffer) { /* This function needs refactoring */ int rv = 1; unsigned long value = 0; if (all->width.star) all->width.num = va_arg(*factor, int); if (all->prec.star) all->prec.num = va_arg(*factor, int); char *p_tmpBuffer = (char *)malloc(max(all->width.num, all->prec.num) + 30); /* Buffer should be init with zeros */ s21_memset(p_tmpBuffer, 0, max(all->width.num, all->prec.num) + 30); value = va_arg(*factor, unsigned long); citoa(value, p_tmpBuffer, 16); insertOneAtBegin(p_tmpBuffer, 'x'); insertOneAtBegin(p_tmpBuffer, '0'); if (all->width.isExist) { if (all->width.num != 0 && all->flags.minus) { /* Align by left edge */ int currWidth; while (currWidth = s21_strlen(p_tmpBuffer), currWidth < all->width.num) { p_tmpBuffer[currWidth] = ' '; p_tmpBuffer[currWidth + 1] = '\0'; } } else if (all->width.num != 0) { /* Align by right edge with inserting ' ' */ widthAligner(p_tmpBuffer, all, ' '); } } endActions(); return rv; } int handle_x(va_list *factor, All *all, s21_size_t posInBuffer, char *buffer) { /* This function needs refactoring */ int rv = 1; unsigned long value = 0; if (all->width.star) all->width.num = va_arg(*factor, int); if (all->prec.star) all->prec.num = va_arg(*factor, int); char *p_tmpBuffer = (char *)malloc(max(all->width.num, all->prec.num) + 30); /* Buffer should be init with zeros */ s21_memset(p_tmpBuffer, 0, max(all->width.num, all->prec.num) + 30); if (all->len.isExist) { if (all->len.h) { value = (unsigned short)va_arg(*factor, unsigned); } else if (all->len.l) value = va_arg(*factor, unsigned long); else rv = 0; } else value = va_arg(*factor, unsigned); citoa(value, p_tmpBuffer, 16); bool isZeroXAdded = false; if (all->prec.isExist) precAligner(p_tmpBuffer, all); if (all->width.isExist) { if (all->width.num != 0 && all->flags.minus) { /* Align by left edge */ int currWidth; while (currWidth = s21_strlen(p_tmpBuffer), currWidth < all->width.num) { p_tmpBuffer[currWidth] = ' '; p_tmpBuffer[currWidth + 1] = '\0'; } } else if (all->width.num != 0 && all->flags.zero) { if (all->flags.sharp) all->width.num -= 2; widthAligner(p_tmpBuffer, all, '0'); } else if (all->width.num != 0) { /* Align by right edge with inserting ' ' */ if (all->flags.sharp && value) { isZeroXAdded = true; insertOneAtBegin(p_tmpBuffer, 'x'); insertOneAtBegin(p_tmpBuffer, '0'); } widthAligner(p_tmpBuffer, all, ' '); } } if (all->flags.sharp && value && !isZeroXAdded) { insertOneAtBegin(p_tmpBuffer, 'x'); insertOneAtBegin(p_tmpBuffer, '0'); } endActions(); return rv; } void to_upper(char *buffer, s21_size_t posInBuffer) { for (; *(buffer + posInBuffer); ++posInBuffer) { char c = *(buffer + posInBuffer); if (c >= 'a' && c <= 'z') *(buffer + posInBuffer) = c - 'a' + 'A'; } } int handle_X(va_list *factor, All *all, s21_size_t posInBuffer, char *buffer) { int rv = handle_x(factor, all, posInBuffer, buffer); to_upper(buffer, posInBuffer); return rv; } int to_eNotation(char *buffer, unsigned buffSize) { int e = 0; char *buffer2 = (char *)malloc(buffSize); char *srcBuf = buffer; char *srcBuf2 = buffer2; s21_memset(buffer2, 0, buffSize); if (*buffer == '-') { *buffer2 = *buffer; ++buffer, ++buffer2; } if (*buffer == '0') { buffer += 2; if (*buffer) { --e; for (; *buffer == '0'; ++buffer, --e) ; *buffer2 = *buffer; ++buffer, ++buffer2; *buffer2 = '.', ++buffer2; for (; *buffer != '\0'; ++buffer, ++buffer2) *buffer2 = *buffer; } else { *buffer = '0'; s21_memcpy(srcBuf2, srcBuf, buffSize); } } else { *buffer2 = *buffer; ++buffer, ++buffer2; *buffer2 = '.', ++buffer2; for (int i = 0; buffer[i] != '.' && buffer[i] != '\0'; ++i, ++e) ; for (; *buffer; ++buffer) { if (*buffer != '.' && *buffer != '\0') { *buffer2 = *buffer; ++buffer2; } } } s21_memcpy(srcBuf, srcBuf2, buffSize); free(srcBuf2); return e; } void roundDoubleStr(char *buffer, int num) { if (*buffer == '-') ++buffer; int i = 0; for (; i < num && buffer[i] != '\0'; ++i) { if (buffer[i] == '.') { ++num; continue; } } if (buffer[i] != '\0') { if (buffer[i] == '.') ++i; /* Rounding in the larger side */ if (buffer[i] >= '5') { buffer[i] = '\0'; while (1) { --i; if (buffer[i] == '.') --i; buffer[i] = buffer[i] + 1; if (buffer[i] <= '9') break; } } else buffer[i] = '\0'; } if (buffer[s21_strlen(buffer) - 1] == '.') buffer[s21_strlen(buffer) - 1] = '\0'; } int handle_g(va_list *factor, All *all, s21_size_t posInBuffer, char *buffer) { long double value = 0; int rv = 1; int len = 0; if (all->width.star) all->width.num = va_arg(*factor, int); if (all->prec.star) all->prec.num = va_arg(*factor, int); unsigned buffSize = max(all->width.num, all->prec.num) + 50; char *p_tmpBuffer = (char *)malloc(buffSize); /* Buffer should be init with zeros */ s21_memset(p_tmpBuffer, 0, max(all->width.num, all->prec.num) + 50); if (all->len.isExist) { if (all->len.L) value = va_arg(*factor, long double); else rv = 0; } else value = (float)va_arg(*factor, double); float sign = value < 0 ? -1 : 1; built_inHelperForPlusSpace(); if (!all->prec.isExist) all->prec.num = 6; for (long i = value; i != 0; i /= 10, ++len) ; if (all->prec.num < len) { lftoa(value, p_tmpBuffer, 0); int e = to_eNotation(p_tmpBuffer, buffSize); roundDoubleStr(p_tmpBuffer, all->prec.num); int br_ = true; if (!all->flags.sharp) { int i_ = s21_strlen(p_tmpBuffer) - 1; for (; i_ > -1 && br_; --i_) { if (p_tmpBuffer[i_] == '0') p_tmpBuffer[i_] = '\0'; else br_ = 0; } if (!br_ && p_tmpBuffer[++i_] == '.') p_tmpBuffer[i_] = '\0'; } int i = s21_strlen(p_tmpBuffer); p_tmpBuffer[i++] = 'e'; if (e >= 0) p_tmpBuffer[i++] = '+'; longToString(e, p_tmpBuffer + i); if (e > -10 && e < 10) { if (e < 0) ++i; insertOneAtBegin((p_tmpBuffer + i), '0'); } } else { if (all->flags.sharp && sign * value <= 0.0000000001 && sign * value >= -0.00000000001) all->prec.num -= 1; int tmp_v = all->prec.num - len; if (tmp_v == 0) ++tmp_v; lftoa(value, p_tmpBuffer, tmp_v); if (!all->flags.sharp) { int i = s21_strlen(p_tmpBuffer) - 1; while (p_tmpBuffer[i] == '0') p_tmpBuffer[i--] = '\0'; if (p_tmpBuffer[i] == '.') p_tmpBuffer[i--] = '\0'; } } if (all->width.isExist) { if (all->width.num != 0 && all->flags.minus) { /* Align by left edge */ int currWidth; while (currWidth = s21_strlen(p_tmpBuffer), currWidth < all->width.num) { p_tmpBuffer[currWidth] = ' '; p_tmpBuffer[currWidth + 1] = '\0'; } } else if (all->width.num != 0 && all->flags.zero) { widthAligner(p_tmpBuffer, all, '0'); } else if (all->width.num != 0) { /* Align by right edge with inserting ' ' */ widthAligner(p_tmpBuffer, all, ' '); } } endActions(); return rv; } int handle_G(va_list *factor, All *all, s21_size_t posInBuffer, char *buffer) { int rv = handle_g(factor, all, posInBuffer, buffer); to_upper(buffer, posInBuffer); return rv; } #define roundHelper() \ { \ if (*curr_num == '9') { \ *curr_num = '0'; \ --curr_num; \ } else { \ was_rounded = 1; \ br_ = 0; \ *curr_num = *curr_num + 1; \ } \ } int handle_e(va_list *factor, All *all, s21_size_t posInBuffer, char *buffer) { long double value = 0; int rv = 1; unsigned len = 7; int e = 0; if (all->width.star) all->width.num = va_arg(*factor, int); if (all->prec.star) all->prec.num = va_arg(*factor, int); unsigned buffSize = max(all->width.num, all->prec.num) + 50; char *p_tmpBuffer = (char *)malloc(buffSize); /* Buffer should be init with zeros */ s21_memset(p_tmpBuffer, 0, max(all->width.num, all->prec.num) + 50); if (all->len.isExist) { if (all->len.L) value = va_arg(*factor, long double); else rv = 0; } else value = (float)va_arg(*factor, double); built_inHelperForPlusSpace(); if (all->prec.isExist) { len = all->prec.num; } else len = 6; lftoa(value, p_tmpBuffer, len); if (!(all->prec.isExist && all->prec.num == 0) || all->flags.sharp) { /* If buffer does not contain '.' */ char *ptrDot = s21_strstr(p_tmpBuffer, "."); if (!(value >= 0 - 0.000000000000001 && value <= 0 + 0.000000000000001)) e = to_eNotation(p_tmpBuffer, buffSize); ptrDot = s21_strstr(p_tmpBuffer, "."); /* Accuracy limit */ if (ptrDot[len + 1] >= '5') { char *curr_num = ptrDot + len; int was_rounded = 0; int br_ = true; while (*curr_num != '.' && br_) { roundHelper(); } if (!was_rounded && *curr_num == '.') --curr_num; if (curr_num == p_tmpBuffer && !was_rounded && *p_tmpBuffer == '9') { *p_tmpBuffer = '0'; *(p_tmpBuffer + 1) = '0'; insertOneAtBegin(p_tmpBuffer, '.'); insertOneAtBegin(p_tmpBuffer, '1'); ++e; } } ptrDot[len + 1] = '\0'; /* Zero padding */ for (int j = 0; s21_strlen(ptrDot) < len + 1 && rv; ++j) { if (*(p_tmpBuffer + j) == '\0') { *(p_tmpBuffer + j) = '0'; *(p_tmpBuffer + j + 1) = '\0'; } } } int i = s21_strlen(p_tmpBuffer); p_tmpBuffer[i++] = 'e'; if (e >= 0) p_tmpBuffer[i++] = '+'; longToString(e, p_tmpBuffer + i); if (e > -10 && e < 10) { if (e < 0) ++i; insertOneAtBegin((p_tmpBuffer + i), '0'); } if (all->width.isExist) { if (all->width.num != 0 && all->flags.minus) { /* Align by left edge */ int currWidth; while (currWidth = s21_strlen(p_tmpBuffer), currWidth < all->width.num) { p_tmpBuffer[currWidth] = ' '; p_tmpBuffer[currWidth + 1] = '\0'; } } else if (all->width.num != 0 && all->flags.zero) { widthAligner(p_tmpBuffer, all, '0'); } else if (all->width.num != 0) { /* Align by right edge with inserting ' ' */ widthAligner(p_tmpBuffer, all, ' '); } } endActions(); return rv; } int handle_E(va_list *factor, All *all, s21_size_t posInBuffer, char *buffer) { int rv = handle_e(factor, all, posInBuffer, buffer); to_upper(buffer, posInBuffer); return rv; } int handling(va_list *factor, All *all, s21_size_t posInBuffer, char *buffer) { /* Need to insert after handling buffer at the end - '\0' */ int rv = 1; if (all->specf.d) /* Specifier d */ rv = handle_d(factor, all, posInBuffer, buffer); else if (all->specf.c) /* Specifier c */ rv = handle_c(factor, all, posInBuffer, buffer); else if (all->specf.f) /* Specifier f */ rv = handle_f(factor, all, posInBuffer, buffer); else if (all->specf.u) /* Specifier u */ rv = handle_u(factor, all, posInBuffer, buffer); else if (all->specf.s) /* Specifier s */ rv = handle_s(factor, all, posInBuffer, buffer); else if (all->specf.o) /* Specifier o */ rv = handle_o(factor, all, posInBuffer, buffer); else if (all->specf.p) /* Specifier p */ rv = handle_p(factor, all, posInBuffer, buffer); else if (all->specf.x) /* Specifier x */ rv = handle_x(factor, all, posInBuffer, buffer); else if (all->specf.X) /* Specifier X */ rv = handle_X(factor, all, posInBuffer, buffer); else if (all->specf.G) /* Specifier G */ rv = handle_G(factor, all, posInBuffer, buffer); else if (all->specf.g) /* Specifier g */ rv = handle_g(factor, all, posInBuffer, buffer); else if (all->specf.E) /* Specifier E */ rv = handle_E(factor, all, posInBuffer, buffer); else if (all->specf.e) /* Specifier e */ rv = handle_e(factor, all, posInBuffer, buffer); else if (all->specf.percent) /* Specifier % */ rv = handle_percent(factor, all, posInBuffer, buffer); return rv; } int s21_sprintf(char *buffer, const char *format, ...) { va_list factor; va_start(factor, format); int rv = 1; s21_size_t posInBuffer = 0; int br = 1; for (; br && *format && rv; ++posInBuffer, ++format) { if (*format == '%') { ++format; /* Allocating memory for all: spec, flags, width etc...*/ All *all = initAll(); parseFlags(&format, all); parseWidth(&format, all); parsePrecision(&format, all); parseLen(&format, all); parseSpecifier(format, all); if (all->specf.isExist) { /* Main handling */ rv = handling(&factor, all, posInBuffer, buffer); /* Moving posInBuffer to zero */ while (*(buffer + posInBuffer) != '\0') ++posInBuffer; --posInBuffer; } else { buffer[posInBuffer++] = '%'; buffer[posInBuffer] = *format; } free(all); } else buffer[posInBuffer] = *format; } buffer[posInBuffer] = '\0'; va_end(factor); if (rv) rv = s21_strlen(buffer); return rv; }