Advertisement
2607

neww_string

Dec 10th, 2021
1,152
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 32.72 KB | None | 0 0
  1. #include "s21_string.h"
  2.  
  3. #include <stdarg.h>
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6.  
  7. #include "errlist.h"
  8.  
  9. /**
  10.  * @brief Searches for the first occurrence of the character (c) (an unsigned char)
  11.  * in the first (n) bytes of the string pointed to, by the argument (str).
  12.  *
  13.  * @param str string which need to be searched to find a first occurance of "c"
  14.  * @param c character which need to be found in "str"
  15.  * @param n amount of bytes of "str" where "c" need to be found
  16.  * @return void *
  17.  */
  18. void *s21_memchr(const void *str, int c, s21_size_t n) {
  19.     void *returnable = S21_NULL;
  20.     char *str_temp = (char *)str;
  21.     if (str != S21_NULL && c > 0 && n > 0) {
  22.         s21_size_t i = 0;
  23.         if (s21_strlen(str) < n) n = s21_strlen(str);
  24.         while (i < n && str_temp[i] != c) {
  25.             i++;
  26.         }
  27.         if (str_temp[i] == c) {
  28.             returnable = &str_temp[i];
  29.         }
  30.     }
  31.     return returnable;
  32. }
  33.  
  34. /**
  35.  * @brief Compares the first n bytes of str1 and str2.
  36.  *
  37.  * @param str1 string which need to be compared with "str2"
  38.  * @param str2 string which need to be compared with "str1"
  39.  * @param n amount of bytes of strings which need to be compared
  40.  * @return int 0 if equial; 1 if str1 > str2; -1 if str1 < str2;
  41.  * if one of "str" is S21_NULL it's considered smaller, but equial if they are both are S21_NULL.
  42.  */
  43. int s21_memcmp(const void *str1, const void *str2, s21_size_t n) {
  44.     int returnable = 0;
  45.     char *str1_temp = (char *)str1;
  46.     char *str2_temp = (char *)str2;
  47.     if (str1_temp != S21_NULL && str2_temp != S21_NULL) {
  48.         s21_size_t i = 0;
  49.         while (i < n && str1_temp[i] == str2_temp[i]) {
  50.             i++;
  51.         }
  52.         if (i != n && str1_temp[i] > str2_temp[i]) {
  53.             returnable = 1;
  54.         } else if (i != n && str1_temp[i] < str2_temp[i]) {
  55.             returnable = -1;
  56.         } else {
  57.             returnable = 0;
  58.         }
  59.     } else if (str1_temp == S21_NULL && str2_temp != S21_NULL) {
  60.         returnable = 1;
  61.     } else if (str1_temp != S21_NULL && str2_temp == S21_NULL) {
  62.         returnable = -1;
  63.     }
  64.     return returnable;
  65. }
  66.  
  67. /**
  68.  * @brief Copies n characters from src to dest.
  69.  *
  70.  * @param dest string which need to copy "src" to
  71.  * @param src string which need to be copied to "dest"
  72.  * @param n amount of bytes of "src" to be copied to "dest"
  73.  * @return void *new string
  74.  */
  75. void *s21_memcpy(void *dest, const void *src, s21_size_t n) {
  76.     void *returnable = S21_NULL;
  77.     char *dest_temp = (char *)dest;
  78.     char *src_temp = (char *)src;
  79.     s21_size_t len1 = s21_strlen(dest_temp);
  80.     s21_size_t len2 = s21_strlen(src_temp);
  81.     if (dest_temp == S21_NULL || src_temp == S21_NULL || len1 < len2) {
  82.         returnable = S21_NULL;
  83.     } else {
  84.         if (len1 < n) n = len1;
  85.         for (s21_size_t i = 0; i < n; i++) {
  86.             dest_temp[i] = src_temp[i];
  87.         }
  88.         returnable = &dest_temp[0];
  89.     }
  90.     return returnable;
  91. }
  92.  
  93. /**
  94.  * @brief Another function to copy n characters from "src" to "dest".
  95.  *
  96.  * @param dest string which need to copy "src" to
  97.  * @param src string which need to be copied to "dest"
  98.  * @param n amount of bytes of "src" to be copied to "dest"
  99.  * @return void *new string
  100.  */
  101. void *s21_memmove(void *dest, const void *src, s21_size_t n) {
  102.     void *returnable = S21_NULL;
  103.     char *dest_temp = (char *)dest;
  104.     char *src_temp = (char *)src;
  105.     char *buffer = (char *)malloc(n * sizeof(char));
  106.     if (dest_temp == S21_NULL || src_temp == S21_NULL || s21_strlen(dest_temp) < n || buffer == S21_NULL) {
  107.         returnable = S21_NULL;
  108.     } else {
  109.         for (s21_size_t i = 0; i < n; i++) {
  110.             buffer[i] = src_temp[i];
  111.         }
  112.         for (s21_size_t i = 0; i < n; i++) {
  113.             dest_temp[i] = buffer[i];
  114.         }
  115.         returnable = &dest_temp[0];
  116.     }
  117.     free(buffer);
  118.     return returnable;
  119. }
  120.  
  121. /**
  122.  * @brief Copies the character c (an unsigned char) to the first n
  123.  * characters of the string pointed to, by the argument str.
  124.  *
  125.  * @param str string which need to be filled with "c"
  126.  * @param c charcter to fill "str" with
  127.  * @param n amount of bytes to fill with "c" inside "src"
  128.  * @return char * sting filled with "c" inside "str" for "n" bytes
  129.  */
  130. void *s21_memset(void *str, int c, s21_size_t n) {
  131.     char *returnable = S21_NULL;
  132.     char *str_temp = (char *)str;
  133.     if (str != S21_NULL && c > 0) {
  134.         s21_size_t strIndex = s21_strlen(str) - 1;
  135.         if (n > strIndex) n = strIndex;
  136.         returnable = str_temp;
  137.         while (n > 0) {
  138.             *str_temp = (unsigned char)c;
  139.             str_temp++;
  140.             n--;
  141.         }
  142.     }
  143.     return returnable;
  144. }
  145.  
  146. /**
  147.  * @brief Appends the string pointed to, by src to the end
  148.  * of the string pointed to by dest.
  149.  *
  150.  * @param dest string where will be copied "src" to
  151.  * @param src string which will be copied to "dest"
  152.  * @return char * sting with "src" copied to "dest"
  153.  */
  154. char *s21_strcat(char *dest, const char *src) {
  155.     char *returnable = S21_NULL;
  156.     if (dest != S21_NULL && src != S21_NULL) {
  157.         char *start = dest;
  158.         while (*start != '\0') {
  159.             start++;
  160.         }
  161.         while (*src != '\0') {
  162.             *start++ = *src++;
  163.         }
  164.         *start = '\0';
  165.         returnable = dest;
  166.     }
  167.     return returnable;
  168. }
  169.  
  170. /**
  171.  * @brief Appends the string pointed to, by src to the end of the
  172.  * string pointed to, by dest up to n characters long.
  173.  *
  174.  * @param dest string where will be copied "src" to
  175.  * @param src string which will be copied to "dest"
  176.  * @param n amount of bytes to be copied
  177.  * @return char * sting with "n" bytes of "src" copied to "dest"
  178.  */
  179. char *s21_strncat(char *dest, const char *src, s21_size_t n) {
  180.     char *returnable = S21_NULL;
  181.     s21_size_t zero = 0;  // because "comparison of unsigned expression >= 0 is always true"
  182.     if (dest != S21_NULL && src != S21_NULL && n >= zero) {
  183.         s21_size_t len = s21_strlen(src);
  184.         if (n > len) n = len;
  185.         char *tmpdst = dest;
  186.         while (*tmpdst != '\0') {
  187.             tmpdst++;
  188.         }
  189.         while (n-- && *src != '\0') {
  190.             *tmpdst++ = *src++;
  191.         }
  192.         *tmpdst = '\0';
  193.         returnable = dest;
  194.     }
  195.     return returnable;
  196. }
  197.  
  198. /**
  199.  * @brief Searches for the first occurrence of the character c
  200.  * (an unsigned char) in the string pointed to, by the argument str.
  201.  *
  202.  * @param str string which need to be searched to find "c"
  203.  * @param c characher which first occurance have to be found in "str"
  204.  * @return char * string which starts from "c" in "str"
  205.  */
  206. char *s21_strchr(const char *str, int c) {
  207.     char *returnable = S21_NULL;
  208.     char *str_temp = (char *)str;
  209.     if (str != S21_NULL && c >= 0) {
  210.         s21_size_t i = 0, strLen = s21_strlen(str);
  211.         while (i < strLen && str_temp[i] != c) {
  212.             i++;
  213.         }
  214.         if (str_temp[i] == c) {
  215.             returnable = &str_temp[i];
  216.         }
  217.     }
  218.     return returnable;
  219. }
  220.  
  221. /**
  222.  * @brief Compares the string pointed to, by str1 to the string pointed to by str2.
  223.  *
  224.  * @param str1 string which need to be compared with "str2"
  225.  * @param str2 string which need to be compared with "str1"
  226.  * @return int 0 if equial; 1 if str1 > str2; -1 if str1 < str2;
  227.  * if one of "str" is S21_NULL it's considered smaller, but equial if they are both are S21_NULL.
  228.  */
  229. int s21_strcmp(const char *str1, const char *str2) {
  230.     int returnable = 0;
  231.     if (str1 != S21_NULL && str2 != S21_NULL) {
  232.         s21_size_t len1 = s21_strlen(str1);
  233.         s21_size_t len2 = s21_strlen(str2);
  234.         if (len2 > len1) {
  235.             returnable = -str2[len1];
  236.         } else if (len2 < len1) {
  237.             len1 = len2;
  238.             returnable = str1[len2];
  239.         }
  240.         s21_size_t i = 0;
  241.         while (i < len1 && str1[i] == str2[i]) {
  242.             i++;
  243.         }
  244.         if (i < len1 && str1[i] > str2[i]) {
  245.             returnable = 1;
  246.         } else if (i < len1 && str1[i] < str2[i]) {
  247.             returnable = -1;
  248.         }
  249.     } else if (str1 == S21_NULL && str2 != S21_NULL) {
  250.         returnable = 1;
  251.     } else if (str1 != S21_NULL && str2 == S21_NULL) {
  252.         returnable = -1;
  253.     }
  254.     return returnable;
  255. }
  256.  
  257. /**
  258.  * @brief Compares at most the first n bytes of str1 and str2.
  259.  *
  260.  * @param str1 string which need to be compared with "str2"
  261.  * @param str2 string which need to be compared with "str1"
  262.  * @return int 0 if equial; 1 if str1 > str2; -1 if str1 < str2;
  263.  * if one of "str" is S21_NULL it's considered smaller, but equial if they are both are S21_NULL.
  264.  */
  265. int s21_strncmp(const char *str1, const char *str2, s21_size_t n) {
  266.     int returnable = 0;
  267.     if (str1 != S21_NULL && str2 != S21_NULL) {
  268.         s21_size_t len1 = s21_strlen(str1);
  269.         s21_size_t len2 = s21_strlen(str2);
  270.         if (len2 > len1 && len2 <= n) {
  271.             returnable = -str2[len1];
  272.         } else if (len2 < len1 && len1 <= n) {
  273.             len1 = len2;
  274.             returnable = str1[len2];
  275.         }
  276.         s21_size_t i = 0;
  277.         if (n > len1) n = len1;
  278.         while (i < n && str1[i] == str2[i]) {
  279.             i++;
  280.         }
  281.         if (i < len1 && str1[i] > str2[i]) {
  282.             returnable = 1;
  283.         } else if (i < len1 && str1[i] < str2[i]) {
  284.             returnable = -1;
  285.         }
  286.     } else if (str1 == S21_NULL && str2 != S21_NULL) {
  287.         returnable = 1;
  288.     } else if (str1 != S21_NULL && str2 == S21_NULL) {
  289.         returnable = -1;
  290.     }
  291.     return returnable;
  292. }
  293.  
  294. /**
  295.  * @brief Copies the string pointed to, by src to dest.
  296.  *
  297.  * @param dest string which need to copy "src" to
  298.  * @param src string which need to be copied to "dest"
  299.  * @return char * string "src" copied till "\\0" appear
  300.  */
  301. char *s21_strcpy(char *dest, const char *src) {
  302.     char *returnable = S21_NULL;
  303.     s21_size_t i = 0;
  304.     if (src != S21_NULL && dest != S21_NULL) {
  305.         while (src[i] != '\0') {
  306.             dest[i] = src[i];
  307.             i++;
  308.         }
  309.         dest[i] = '\0';
  310.         returnable = dest;
  311.     }
  312.     return returnable;
  313. }
  314.  
  315. /**
  316.  * @brief Copies up to n characters from the string pointed to, by src to dest.
  317.  *
  318.  * @param dest string which need to copy "src" to
  319.  * @param src string which need to be copied to "dest"
  320.  * @param n amount of char to be copied from "src" to "dest"
  321.  * @return char * string "src" copied till n-th character appear
  322.  */
  323. char *s21_strncpy(char *dest, const char *src, s21_size_t n) {
  324.     char *returnable = S21_NULL;
  325.     s21_size_t i = 0;
  326.     if (src != S21_NULL && dest != S21_NULL) {
  327.         s21_size_t srcLen = s21_strlen(src);
  328.         if (n > srcLen) n = srcLen;
  329.         while (i != n) {
  330.             dest[i] = src[i];
  331.             i++;
  332.         }
  333.         dest[i] = '\0';
  334.         returnable = dest;
  335.     }
  336.     return returnable;
  337. }
  338.  
  339. /**
  340.  * @brief Calculates the length of the initial segment of str1
  341.  * which consists entirely of characters not in str2.
  342.  *
  343.  * @param str1 string which need to be searched at the start for symbols of "str2"
  344.  * @param str2 string of symbols which have not to be found at the start of "str1"
  345.  * @return s21_size_t amount of symbols of "str1" weren't found matching with "str2"
  346.  */
  347. s21_size_t s21_strcspn(const char *str1, const char *str2) {
  348.     //printf("Start\n\n");
  349.     s21_size_t len = 0, str1Index = 0, str2Index = 0;
  350.     s21_size_t len_2 = s21_strlen(str2);
  351.     if (len_2 == 0 && str2 != S21_NULL)
  352.         len =  s21_strlen(str1);
  353.     if (str1 != S21_NULL && str2 != S21_NULL && len_2 !=0) {
  354.         for (; str1[str1Index] != str2[str2Index]; str2Index++) {
  355.             //printf("%c\n", str1[str1Index]);
  356.             if (str2[str2Index] == '\0') {
  357.                 len += 1;
  358.                 str1Index += 1;
  359.                 str2Index = 0;
  360.             }
  361.         }
  362.         if (str1[len-1]==str2[0]) {
  363.             len-=1;
  364.         }
  365.     }
  366.     return len;
  367. }
  368.  
  369. /**
  370.  * @brief Searches an internal array for the error number "errnum"
  371.  * and returns a pointer to an error message string.
  372.  *
  373.  * @param errnum code of error
  374.  * @return char * string with error message
  375.  */
  376. char *s21_strerror(int errnum) {
  377.     static char *array[] = errlist;
  378.     static char *err;
  379.     err = array[errnum];
  380.     static char buffer[1024];
  381. #if defined(__APPLE__)
  382.     snprintf(buffer, sizeof(buffer), "Unknown error: %d", (int)errnum);
  383. #elif defined(__linux__)
  384.     snprintf(buffer, sizeof(buffer), "Unknown error %d", (int)errnum);
  385. #endif
  386.     if (err == S21_NULL || errnum > MAX_ERROR || errnum < 0) {
  387.         err = buffer;
  388.     }
  389.     return err;
  390. }
  391.  
  392. /**
  393.  * @brief Computes the length of the string str up to but not including the terminating S21_NULL character.
  394.  *
  395.  * @param str string which need to count character in
  396.  * @return s21_size_t string length without "\\0"; return length 0 if str is S21_NULL.
  397.  */
  398. s21_size_t s21_strlen(const char *str) {
  399.     s21_size_t i = 0;
  400.     if (str != S21_NULL) {
  401.         for (i = 0; str[i] != '\0'; i++) {
  402.         }
  403.     }
  404.     return i;
  405. }
  406.  
  407. /**
  408.  * @brief Finds the first character in the string str1
  409.  * that matches any character specified in str2.
  410.  *
  411.  * @param str1 string which need to be searched to find one out of symbols of "str2"
  412.  * @param str2 string contains symbols had to be compared with characters in "str1"
  413.  * @return char * string started with found character
  414.  */
  415. char *s21_strpbrk(const char *str1, const char *str2) {
  416.     char *returnable = S21_NULL;
  417.     if (str1 != S21_NULL && str2 != S21_NULL) {
  418.         s21_size_t str1Index = 0, str2Index = 0;
  419.         for (; str1[str1Index] && str1[str1Index] != str2[str2Index]; str2Index++) {
  420.             if (str2[str2Index] == '\0') {
  421.                 str1Index++;
  422.                 str2Index = -1;
  423.             }
  424.         }
  425.         if (str1[str1Index] != '\0') {
  426.             returnable = (char *)&str1[str1Index];
  427.         }
  428.     }
  429.     return returnable;
  430. }
  431.  
  432. /**
  433.  * @brief Searches for the last occurrence of the character c
  434.  * (an unsigned char) in the string pointed to by the argument str.
  435.  *
  436.  * @param str string which need to be searched to find "c"
  437.  * @param c characher which last occurance have to be found in "str"
  438.  * @return char * string which starts from "c" in "str"
  439.  */
  440. char *s21_strrchr(const char *str, int c) {
  441.     char *returnable = S21_NULL;
  442.     char *str_temp = (char *)str;
  443.     if (c=='\0')
  444.         returnable = &str_temp[s21_strlen(str)];
  445.     if (str != S21_NULL && c > 0) {
  446.         s21_size_t strIndex = s21_strlen(str) - 1;
  447.         while (strIndex > 0 && str_temp[strIndex] != c) {
  448.             strIndex--;
  449.         }
  450.         if (str_temp[strIndex] == c) {
  451.             returnable = &str_temp[strIndex];
  452.         }
  453.     }
  454.     return returnable;
  455. }
  456.  
  457. /**
  458.  * @brief Calculates the length of the initial segment of str1
  459.  * which consists entirely of characters in str2.
  460.  *
  461.  * @param str1 string which need to be searched at the start for symbols of "str2"
  462.  * @param str2 string of symbols which have to be found at the start of "str1"
  463.  * @return s21_size_t amount of symbols of "str1" were found matching with "str2"
  464.  */
  465. s21_size_t s21_strspn(const char *str1, const char *str2) {
  466.     s21_size_t len = 0, str1Index = 0, str2Index = 0;
  467.     if ((str1 != S21_NULL) || (str2 != S21_NULL)) {
  468.         while (str2[str2Index] != '\0') {
  469.             if (str1[str1Index] == str2[str2Index]) {
  470.                 str1Index++;
  471.                 str2Index = -1;  // because it's incremented the next
  472.                 len++;
  473.             }
  474.             str2Index++;
  475.         }
  476.     }
  477.     return len;
  478. }
  479.  
  480. /**
  481.  * @brief Finds the first occurrence of the entire string needle
  482.  * (not including the terminating S21_NULL character) which appears in the string haystack.
  483.  *
  484.  * @param haystack string which need to be searched to found "needle" in
  485.  * @param needle string which need to be found inside "haystack"
  486.  * @return char * string starting where "needle" starts inside "haystack" from
  487.  */
  488. char *s21_strstr(const char *haystack, const char *needle) {
  489.     char *returnable = S21_NULL;
  490.     if (s21_strlen(needle)==0)
  491.         returnable = (char *)&haystack[0];
  492.     if (haystack != S21_NULL && needle != S21_NULL && s21_strlen(needle)>0) {
  493.         s21_size_t hayLen = s21_strlen(haystack);
  494.         s21_size_t indx = 0;
  495.         for (s21_size_t i = 0; i < hayLen && returnable == S21_NULL; i++) {
  496.             if (haystack[i] == needle[0]) {
  497.                 while (needle[indx] && haystack[i + indx] && haystack[i + indx] == needle[indx]) {
  498.                     indx++;
  499.                 }
  500.                 indx--;
  501.                 if (haystack[i + indx] == needle[indx] && needle[indx + 1] == '\0') {
  502.                     returnable = (char *)&haystack[i];
  503.                 }
  504.                 indx = 0;
  505.             }
  506.         }
  507.     }
  508.     return returnable;
  509. }
  510.  
  511. /**
  512.  * @brief Breaks string str into a series of tokens separated by delim.
  513.  *
  514.  * @param str string which need to be broken into tokens
  515.  * @param delim string which contains symbols as a separators
  516.  * @return char * string with symbols of "str" till one out of "delim" symbols appear.
  517.  * Use S21_NULL as a "str" after first application to get next tokens of "str"
  518.  */
  519. char *s21_strtok(char *str, const char *delim) {
  520.     static char *last = S21_NULL;
  521.     char *returnable = S21_NULL;
  522.     if (str == S21_NULL && delim != S21_NULL) {
  523.         str = last;
  524.     }
  525.     if (str != S21_NULL && delim != S21_NULL) {
  526.         s21_size_t str1Index = 0, str2Index = 0;
  527.         for (; str[str1Index] && str[str1Index] != delim[str2Index]; str2Index++) {
  528.             if (delim[str2Index] == '\0') {
  529.                 str1Index++;
  530.                 str2Index = -1;
  531.             }
  532.         }
  533.         if (str[str1Index] == '\0' || str[str1Index + 1] == '\0') {
  534.             str[str1Index] = '\0';
  535.             last = S21_NULL;
  536.         } else {
  537.             str[str1Index] = '\0';
  538.             last = (char *)&str[str1Index + 1];
  539.         }
  540.         returnable = str;
  541.     }
  542.     return returnable;
  543. }
  544.  
  545. /**
  546.  * @brief Returns a copy of string (str) converted to uppercase.
  547.  * In case of any error, return S21_NULL.
  548.  *
  549.  * @param str string which need to be converted to uppercase
  550.  * @return void *new string ATTENTION!!! MALLOC IS USED TO CREATE NEW STRING!!!
  551.  * */
  552. void *s21_to_upper(const char *str) {
  553.     void *returnable = S21_NULL;
  554.     if (str != S21_NULL) {
  555.         s21_size_t i = 0, j = 0;
  556.         for (i = 0; str[i] != '\0'; i++) {
  557.         }
  558.         char *copyStr = (char *)malloc(i * sizeof(char) + 1);
  559.  
  560.         while (j < i) {
  561.             if (str[j] > 96 && str[j] < 123) {
  562.                 copyStr[j] = str[j] - 32;
  563.                 j++;
  564.             } else {
  565.                 copyStr[j] = str[j];
  566.                 j++;
  567.             }
  568.         }
  569.         copyStr[i + 1] = '\0';
  570.         returnable = copyStr;
  571.     }
  572.     return returnable;
  573. }
  574.  
  575. /**
  576.  * @brief Returns a copy of string (str) converted to lowercase.
  577.  * In case of any error, return S21_NULL.
  578.  *
  579.  * @param str string which need to be converted to lowercase
  580.  * @return void *new string ATTENTION!!! MALLOC IS USED TO CREATE NEW STRING!!!
  581.  */
  582. void *s21_to_lower(const char *str) {
  583.     void *returnable = S21_NULL;
  584.     if (str != S21_NULL) {
  585.         s21_size_t i = 0, j = 0;
  586.         for (i = 0; str[i] != '\0'; i++) {
  587.         }
  588.         char *copyStr = (char *)malloc(i * sizeof(char) + 1);
  589.  
  590.         while (j < i) {
  591.             if (str[j] > 64 && str[j] < 91) {
  592.                 copyStr[j] = str[j] + 32;
  593.                 j++;
  594.             } else {
  595.                 copyStr[j] = str[j];
  596.                 j++;
  597.             }
  598.         }
  599.         copyStr[i + 1] = '\0';
  600.         returnable = copyStr;
  601.     }
  602.     return returnable;
  603. }
  604.  
  605. /**
  606.  * @brief Returns a new string in which a specified string (str) is inserted at a
  607.  * specified index position (start_index) in the given string (src).
  608.  * In case of any error, return S21_NULL.
  609.  *
  610.  * @param src string which need to paste "str" in
  611.  * @param str string which need to be pasted into "src"
  612.  * @param start_index number of place from where "str" need to be put into "src"
  613.  * @return void *new string ATTENTION!!! MALLOC IS USED TO CREATE NEW STRING!!!
  614.  */
  615. void *s21_insert(const char *src, const char *str, s21_size_t start_index) {
  616.     void *returnable = S21_NULL;
  617.     s21_size_t srcLen = 0;
  618.     s21_size_t strLen = 0;
  619.     char strValid = src != S21_NULL && str != S21_NULL;
  620.     if (strValid == 1) {
  621.         for (srcLen = 0; src[srcLen] != '\0'; srcLen++) {
  622.         }
  623.         for (strLen = 0; str[strLen] != '\0'; strLen++) {
  624.         }
  625.     }
  626.     s21_size_t zero = 0;
  627.     char indexValid = start_index >= zero && start_index <= srcLen;
  628.     if (strValid == 1 && indexValid == 1) {
  629.         char *buffer = (char *)malloc((srcLen + strLen) * sizeof(char) + 1);
  630.         if (buffer != S21_NULL) {
  631.             for (s21_size_t i = 0; i < start_index; i++) {
  632.                 buffer[i] = src[i];
  633.             }
  634.             for (s21_size_t j = 0; j < strLen; j++) {
  635.                 buffer[j + start_index] = str[j];
  636.             }
  637.             for (s21_size_t k = 0; k < srcLen - start_index; k++) {
  638.                 buffer[k + start_index + strLen] = src[k + start_index];
  639.             }
  640.             buffer[srcLen + strLen + 1] = '\0';
  641.             returnable = buffer;
  642.         }
  643.     }
  644.     return returnable;
  645. }
  646.  
  647. /**
  648.  * @brief Returns a new string in which all leading and trailing occurrences of a set of
  649.  * specified characters (trim_chars) from the given string (src) are removed. In case of
  650.  * any error, return S21_NULL.
  651.  *
  652.  * @param src string which need to remove symbols defined in "trim_chars" in
  653.  * @param trim_chars string which contains symbols to remove from "src"
  654.  * @return void *new string ATTENTION!!! MALLOC IS USED TO CREATE NEW STRING!!!
  655.  */
  656. void *s21_trim(const char *src, const char *trim_chars) {
  657.     void *returnable = S21_NULL;
  658.     s21_size_t startIndex = 0, endIndex = 0, i = 0;
  659.     if (src != S21_NULL && trim_chars != S21_NULL) {
  660.         for (endIndex = 0; src[endIndex] != '\0'; endIndex++) {
  661.         }
  662.         endIndex -= 1;
  663.  
  664.         while (trim_chars[i] != '\0') {
  665.             if (src[startIndex] == trim_chars[i]) {
  666.                 startIndex += 1;
  667.                 i = -1;
  668.             }
  669.             i++;
  670.         }
  671.  
  672.         i = 0;
  673.         while (trim_chars[i] != '\0') {
  674.             if (src[endIndex] == trim_chars[i]) {
  675.                 endIndex -= 1;
  676.                 i = -1;
  677.             }
  678.             i++;
  679.         }
  680.  
  681.         if (endIndex - startIndex > 0) {
  682.             char *copyStr = (char *)malloc((endIndex - startIndex) * sizeof(char) + 1);
  683.             if (copyStr != S21_NULL) {
  684.                 for (i = startIndex; i <= endIndex; i++) {
  685.                     copyStr[i - startIndex] = src[i];
  686.                 }
  687.                 copyStr[endIndex] = '\0';
  688.                 returnable = copyStr;
  689.             }
  690.         }
  691.     }
  692.     return returnable;
  693. }
  694.  
  695. int s21_sprintf(char *output, char *str, ...) {
  696.     va_list ap;        /* point on next unnamed argument */
  697.     va_start(ap, str); /* set 'ap' on 1-st unnamed argument */
  698.     int out_len =
  699.         0;  // массив, куда осуществляется вывод, он должен задаваться как аргумент s21_sprintf, но пока так
  700.     for (char *p = str; *p; p++) {
  701.         if (*p != '%') {
  702.             out_len++;
  703.             output[s21_strlen(output)] = *p;
  704.             continue;
  705.         }
  706.         char flag1 = -1;  // задаём значения подспецификаторов по умолчанию
  707.         char flag3 = -1;
  708.         int width = -1;
  709.         int prec = -1;
  710.         char lenght = -1;
  711.  
  712.         ++p;  // переключаемся на следующий символ и если он один из флагов, то считываем его
  713.         while (1) {  // цикл бесконечный, так как флагов можно ставить хоть сколько
  714.             if (*p == '-' || *p == '+' || *p == ' ') {
  715.                 if (*p == '+' || *p == ' ') {
  716.                     if (flag1 == '+')
  717.                         flag1 = '+';
  718.                     else
  719.                         flag1 = *p;
  720.                 }
  721.                 if (*p == '-') {
  722.                     flag3 = *p;
  723.                 }
  724.                 ++p;
  725.             } else {
  726.                 break;
  727.             }
  728.         }
  729.         if (*p == '*') {  // следующий символ, и если он ширина, то считываем её. Один раз проверяем наличие
  730.                           // шиирны, так как ширину можно указывать только один раз, в отличии от флагов
  731.             width = va_arg(ap, int);
  732.             ++p;
  733.         }
  734.  
  735.         if (*p == '.' && *(p + 1) == '*') {  // следующий символ, и если он точность, то считываем его.
  736.             prec = va_arg(ap, int);
  737.             p += 2;
  738.         }
  739.  
  740.         if (*p == 'h' || *p == 'l') {
  741.             lenght = *p;
  742.             ++p;
  743.         }
  744.  
  745.         switch (*p) {
  746.             case 'c': {
  747.                 char ival;
  748.                 ival = (char)va_arg(ap, int);
  749.                 if (flag3 != '-' && width != -1) {
  750.                     for (int i = 0; i < width - 1; ++i) {
  751.                         output[s21_strlen(output)] = ' ';
  752.                         out_len++;
  753.                     }
  754.                 }
  755.                 output[s21_strlen(output)] = ival;
  756.                 out_len++;
  757.                 if (flag3 == '-' && width != -1) {
  758.                     for (int i = 0; i < width - 1; ++i) {
  759.                         output[s21_strlen(output)] = ' ';
  760.                         out_len++;
  761.                     }
  762.                 }
  763.                 break;
  764.             }
  765.             case 'u': {
  766.                 unsigned long int ival = 0;
  767.                 if (lenght == 'l')
  768.                     ival = (unsigned long int)va_arg(ap, unsigned long int);
  769.                 else
  770.                     ival = (unsigned long int)va_arg(ap, unsigned int);
  771.                 char buf[21] = "";
  772.                 IntStr(buf, 1, ival, -1, flag3, width, prec);
  773.                 out_len += s21_strlen(buf);
  774.                 s21_strcat(output, buf);
  775.                 break;
  776.             }
  777.             case 'd': {
  778.                 long int ival = 0;
  779.                 if (lenght == 'l')
  780.                     ival = (long int)va_arg(ap, long int);
  781.                 else
  782.                     ival = (long int)va_arg(ap, int);
  783.                 char buf[50] = "";
  784.                 IntStr(buf, 1, ival, flag1, flag3, width, prec);
  785.                 out_len += s21_strlen(buf);
  786.                 s21_strcat(output, buf);
  787.                 break;
  788.             }
  789.             case 'i': {
  790.                 long int ival = 0;
  791.                 if (lenght == 'l')
  792.                     ival = (long int)va_arg(ap, long int);
  793.                 else
  794.                     ival = (long int)va_arg(ap, int);
  795.                 char buf[50] = "";
  796.                 IntStr(buf, 1, ival, flag1, flag3, width, prec);
  797.                 out_len += s21_strlen(buf);
  798.                 s21_strcat(output, buf);
  799.                 break;
  800.                 break;
  801.             }
  802.             case 'f': {
  803.                 double dval = 0.;
  804.                 dval = va_arg(ap, double);
  805.                 char buf[50] = "";
  806.                 DoubleStr(buf, dval, flag1, flag3, width, prec);
  807.                 out_len += s21_strlen(buf);
  808.                 s21_strcat(output, buf);
  809.                 break;
  810.             }
  811.             case 's': {
  812.                 char *buf = malloc(sizeof(char));
  813.                 int k = 0;
  814.                 for (char *sval = va_arg(ap, char *); *sval; sval++) {
  815.                     k++;
  816.                     if (prec < k && prec > 0) continue;
  817.                     void *bufff = realloc(buf, k * sizeof(char));
  818.                     if (S21_NULL == bufff) {
  819.                         free(buf);
  820.                     } else {
  821.                         buf = bufff;
  822.                     }
  823.                     *(buf + k - 1) = *sval;
  824.                     out_len++;
  825.                 }
  826.                 int l = s21_strlen(buf);
  827.                 if (flag3 != '-') {
  828.                     for (int i = 0; i < width - l; ++i) {
  829.                         s21_strcat(output, " ");
  830.                         out_len++;
  831.                     }
  832.                 }
  833.                 s21_strcat(output, buf);
  834.                 // free(buf);
  835.                 if (flag3 == '-') {
  836.                     for (int i = 0; i < width - l; ++i) {
  837.                         s21_strcat(output, " ");
  838.                         out_len++;
  839.                     }
  840.                 }
  841.                 break;
  842.             }
  843.             case '%': {
  844.                 s21_strcat(output, "%");
  845.                 out_len++;
  846.                 break;
  847.             }
  848.             default: {
  849.                 output[s21_strlen(output)] = *p;
  850.                 break;
  851.             }
  852.         }
  853.     }
  854.     va_end(ap); /* clean all */
  855.     return out_len;
  856. }
  857.  
  858. char *IntStr(char *buf, int is_int, long int n, char flag, char flag3, int width, int prec) {
  859.     // char *index = buf;
  860.     int len = LenInt(n);
  861.     int fprec = 0;  // длина числа
  862.     if (prec != -1 && is_int == 0) {
  863.         fprec = prec + 1;
  864.     }
  865.     int tr_len = len;
  866.     if (prec != -1 && prec > len && is_int == 1)  // если задана точность, то длина числа будет равна точности
  867.         len = prec;
  868.     int full_len = len;
  869.     int i = 0;
  870.     int j = 0;
  871.     if ((flag == ' ' && n >= 0) || (flag == '+' && n > 0) || n < 0)
  872.         // если заданы флаги пробел и + или число отрицательное, то фактическая длина больше на
  873.         // единицу, так как нужно печатать плюс, минус или пробел
  874.         full_len++;
  875.     if (flag3 == -1 &&
  876.         width != -1) {  // если задана ширина и нет флага 0 или -, то печатаем сначала пробелы, затем число
  877.         for (; j < width - full_len - fprec; ++j) {
  878.             *(buf + j) = ' ';
  879.         }
  880.     }
  881.     if (flag == ' ' && n >= 0) {  // если если флаг пробел, то перед числом ставим пробел
  882.         buf += j;
  883.         *(buf++) = ' ';
  884.         buf -= j;
  885.     }
  886.     if (flag == '+' && n > 0) {  // если если флаг +, то перед положительным числом ставим плюс
  887.         buf += j;
  888.         *(buf++) = '+';
  889.         buf -= j;
  890.     }
  891.     if (n < 0) {  // если число отрицательно, то перед ним печатаем минус
  892.         buf += j;
  893.         *(buf++) = '-';
  894.         buf -= j;
  895.         n = -n;
  896.     }
  897.     // если число ноль, то печатаем ноль (ноль приходится отдельно обрабатывать, иначе не работает)
  898.     if (n == 0) {
  899.         buf += j;
  900.         *(buf++) = '0';
  901.         buf -= j;
  902.     }
  903.     while (n > 0) {  // непосредственно вывод самого числа
  904.         *(buf + j + len - i - 1) = (n % 10) | '0';
  905.         n /= 10;
  906.         i++;
  907.     }
  908.     if (is_int == 1) {
  909.         for (int h = 0; h < prec - tr_len; h++) {  // а это, если задана точность, вывод дополнительных нулей
  910.             *(buf + j + len - i - 1) = '0';
  911.             i++;
  912.         }
  913.     }
  914.     // если флаг - и задана ширина, то после числа пробелы печатаем
  915.     if (flag3 == '-' && width != -1 && is_int == 1) {
  916.         for (; j < width - full_len - fprec; ++j) *(buf + len - 1 + j + 1) = ' ';
  917.     }
  918.     return (buf);
  919. }
  920.  
  921. int LenInt(int n) {
  922.     int len = 0;
  923.     if (n < 0) n = n * (-1);
  924.     while (n > 0) {
  925.         len++;
  926.         n /= 10;
  927.     }
  928.     return len;
  929. }
  930.  
  931. char *DoubleStr(char *buf, long double n, char flag, char flag3, int width, int prec) {
  932.     int len = LenInt((int)n);
  933.     if ((flag == ' ' && n >= 0) || (flag == '+' && n > 0) ||
  934.         n < 0)  // если заданы флаги пробел и + или число отрицательное, то фактическая длина больше на
  935.                 // единицу, так как нужно печатать плюс, минус или пробел
  936.         len++;
  937.     if (prec == -1) prec = 6;
  938.     IntStr(buf, 0, (int)n, flag, flag3, width, prec);
  939.     if (prec != 0)
  940.         s21_strcat(buf, ".");
  941.     else
  942.         s21_strcat(buf, " ");
  943.     if (n < 0) {
  944.         n = n * (-1);
  945.     }
  946.     n = n - (long int)n;
  947.  
  948.     for (int i = 0; i < prec; i++) {
  949.         n *= 10;
  950.         buf[s21_strlen(buf)] = n + '0';
  951.         n = n - (int)n;
  952.     }
  953.     if (flag3 == '-') {
  954.         for (int i = 0; i < width - (len + prec + 1); i++) buf[s21_strlen(buf)] = ' ';
  955.     }
  956.     return buf;
  957. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement