Branch data Line data Source code
1 : : #include "rational.h"
2 : : #include <errno.h>
3 : :
4 : : // A utility function to reverse a string
5 : 33 : static void reverse(
6 : : char str[],
7 : : size_t length)
8 : : {
9 : 33 : size_t start = 0;
10 : 33 : size_t end = 0;
11 : :
12 : : // Guard against empty strings
13 [ + - ]: 33 : if(length > 0)
14 : : {
15 : 33 : end = length - 1;
16 : : }
17 : :
18 [ + + ]: 147 : while(start < end)
19 : : {
20 : 114 : char temp = str[start];
21 : 114 : str[start] = str[end];
22 : 114 : str[end] = temp;
23 : 114 : end--;
24 : 114 : start++;
25 : : }
26 : 33 : }
27 : :
28 : : /**
29 : : * @brief Converts an integer to a string representation
30 : : *
31 : : * @param value The integer value to convert
32 : : * @param str The destination string buffer
33 : : * @param base The base for conversion (2-36)
34 : : * @return char* Pointer to the resulting string
35 : : *
36 : : * @note The buffer should be large enough to hold the result
37 : : * @note Supports negative numbers only in base 10
38 : : * @note For invalid base (not in 2-36), sets errno = EINVAL,
39 : : * writes an empty string, and returns str
40 : : * @note If str is NULL, sets errno = EINVAL and returns NULL
41 : : */
42 : 48 : char *itoa(
43 : : int num,
44 : : char *str,
45 : : unsigned int base)
46 : : {
47 : 48 : size_t i = 0;
48 : 48 : bool isNegative = false;
49 : : unsigned int unum; // Use unsigned int for calculations
50 : :
51 [ + + ]: 48 : if(str == NULL)
52 : : {
53 : 2 : errno = EINVAL;
54 : 2 : return NULL;
55 : : }
56 : :
57 [ + + + + ]: 46 : if(base < 2 || base > 36)
58 : : {
59 : 6 : errno = EINVAL;
60 : 6 : str[0] = '\0';
61 : 6 : return str;
62 : : }
63 : :
64 : : /* Handle 0 explicitly, otherwise empty string is
65 : : * printed for 0 */
66 [ + + ]: 40 : if(num == 0)
67 : : {
68 : 7 : str[i++] = '0';
69 : 7 : str[i] = '\0';
70 : 7 : return str;
71 : : }
72 : :
73 : : /* Handle negative numbers */
74 [ + + + + ]: 33 : if(num < 0 && base == 10)
75 : : {
76 : : /* The number is negative and we are converting to base 10.
77 : : * In this case we want to print a leading '-' sign and work
78 : : * with the absolute value of the number. For other bases we
79 : : * will treat the value as unsigned and show its bit pattern.
80 : : */
81 : 5 : isNegative = true;
82 : :
83 : : /* IMPORTANT:
84 : : * We must NOT write: (unsigned int)(-num)
85 : : * because the expression (-num) is evaluated in signed int,
86 : : * which is undefined behavior when num == INT_MIN
87 : : * (e.g. -2147483648 on a 32-bit system), since +2147483648
88 : : * cannot be represented in a signed int.
89 : : *
90 : : * To avoid this, we first cast num to unsigned int, and only
91 : : * then apply the unary minus. The unary minus on an unsigned
92 : : * type is well-defined: it performs modular arithmetic
93 : : * (2^N - value), so it never overflows.
94 : : *
95 : : * Example for a 32-bit int:
96 : : * num = INT_MIN = -2147483648
97 : : * (unsigned)num = 0x80000000 (2147483648u)
98 : : * -(unsigned)num = 0x80000000 (still 2147483648u)
99 : : * This is exactly the magnitude we need for INT_MIN.
100 : : */
101 : 5 : unum = (unsigned int)(-(unsigned int)num);
102 : : } else {
103 : : /* For non-negative numbers, or for any base other than 10,
104 : : * we simply convert the value to unsigned.
105 : : *
106 : : * - If num >= 0, this just gives the same numeric value.
107 : : * - If num < 0 and base != 10, the result is the unsigned
108 : : * value modulo 2^N, which is useful for hexadecimal or
109 : : * binary dumps of the underlying representation.
110 : : */
111 : 28 : unum = (unsigned int)num;
112 : : }
113 : :
114 : : /* Process individual digits */
115 [ + + ]: 267 : while(unum != 0)
116 : : {
117 : 234 : int rem = (int)(unum % base);
118 [ + + ]: 234 : str[i++] = (rem > 9) ? (char)(rem - 10 + 'A') : (char)(rem + '0');
119 : 234 : unum = unum / base;
120 : : }
121 : :
122 : : /* If number is negative, append '-' */
123 [ + + ]: 33 : if(isNegative)
124 : : {
125 : 5 : str[i++] = '-';
126 : : }
127 : :
128 : 33 : str[i] = '\0'; // Append string terminator
129 : :
130 : : // Reverse the string
131 : 33 : reverse(str,i);
132 : :
133 : 33 : return str;
134 : : }
|