Line data Source code
1 : #include "rational.h"
2 :
3 : // A utility function to reverse a string
4 20 : static void reverse(
5 : char str[],
6 : size_t length)
7 : {
8 20 : size_t start = 0;
9 20 : size_t end = length > 0 ? length - 1 : 0; // Guard against empty strings
10 :
11 86 : while(start < end)
12 : {
13 66 : char temp = str[start];
14 66 : str[start] = str[end];
15 66 : str[end] = temp;
16 66 : end--;
17 66 : start++;
18 : }
19 20 : }
20 :
21 : /**
22 : * @brief Converts an integer to a string representation
23 : *
24 : * @param value The integer value to convert
25 : * @param str The destination string buffer
26 : * @param base The base for conversion (2-36)
27 : * @return char* Pointer to the resulting string
28 : *
29 : * @note The buffer should be large enough to hold the result
30 : * @note Supports negative numbers only in base 10
31 : */
32 24 : char *itoa(
33 : int num,
34 : char *str,
35 : unsigned int base)
36 : {
37 24 : size_t i = 0;
38 24 : bool isNegative = false;
39 : unsigned int unum; // Use unsigned int for calculations
40 :
41 : /* Handle 0 explicitly, otherwise empty string is
42 : * printed for 0 */
43 24 : if(num == 0)
44 : {
45 4 : str[i++] = '0';
46 4 : str[i] = '\0';
47 4 : return str;
48 : }
49 :
50 : /* Handle negative numbers */
51 20 : if(num < 0 && base == 10)
52 : {
53 : /* The number is negative and we are converting to base 10.
54 : * In this case we want to print a leading '-' sign and work
55 : * with the absolute value of the number. For other bases we
56 : * will treat the value as unsigned and show its bit pattern.
57 : */
58 4 : isNegative = true;
59 :
60 : /* IMPORTANT:
61 : * We must NOT write: (unsigned int)(-num)
62 : * because the expression (-num) is evaluated in signed int,
63 : * which is undefined behavior when num == INT_MIN
64 : * (e.g. -2147483648 on a 32-bit system), since +2147483648
65 : * cannot be represented in a signed int.
66 : *
67 : * To avoid this, we first cast num to unsigned int, and only
68 : * then apply the unary minus. The unary minus on an unsigned
69 : * type is well-defined: it performs modular arithmetic
70 : * (2^N - value), so it never overflows.
71 : *
72 : * Example for a 32-bit int:
73 : * num = INT_MIN = -2147483648
74 : * (unsigned)num = 0x80000000 (2147483648u)
75 : * -(unsigned)num = 0x80000000 (still 2147483648u)
76 : * This is exactly the magnitude we need for INT_MIN.
77 : */
78 4 : unum = (unsigned int)(-(unsigned int)num);
79 : } else {
80 : /* For non-negative numbers, or for any base other than 10,
81 : * we simply reinterpret the value as unsigned.
82 : *
83 : * - If num >= 0, this just gives the same numeric value.
84 : * - If num < 0 and base != 10, the bit pattern of num is
85 : * reinterpreted as an unsigned integer, which allows us
86 : * to display its two's-complement representation (e.g. for
87 : * hexadecimal or binary dumps).
88 : */
89 16 : unum = (unsigned int)num;
90 : }
91 :
92 : /* Process individual digits */
93 154 : while(unum != 0)
94 : {
95 134 : int rem = (int)(unum % base);
96 134 : str[i++] = (rem > 9) ? (char)(rem - 10 + 'A') : (char)(rem + '0');
97 134 : unum = unum / base;
98 : }
99 :
100 : /* If number is negative, append '-' */
101 20 : if(isNegative)
102 : {
103 4 : str[i++] = '-';
104 : }
105 :
106 20 : str[i] = '\0'; // Append string terminator
107 :
108 : // Reverse the string
109 20 : reverse(str,i);
110 :
111 20 : return str;
112 : }
113 :
114 : #if 0
115 : #include <limits.h>
116 : /// Test
117 :
118 : static void test_conversion(
119 : int value,
120 : unsigned int base,
121 : const char *string)
122 : {
123 : char buffer[66]; /* 64 bits + sign + null terminator */
124 : itoa(value,buffer,base);
125 :
126 : /* Print original value in decimal and result in specified base */
127 : printf("Value: %d (decimal)\n",value);
128 : printf("Base %2d result: %s, %s\n",base,buffer,string);
129 : printf("-------------------\n");
130 : }
131 :
132 : /**
133 : * @brief Test program for itoa function
134 : *
135 : * @note Tests edge cases and different bases with special focus on
136 : * negative numbers and MIN/MAX integer values
137 : */
138 : static void test_itoa(void)
139 : {
140 :
141 : /* Test extreme values */
142 : printf("=== Testing extreme values ===\n");
143 : test_conversion(INT_MAX,10,"2147483647");
144 : test_conversion(INT_MIN,10,"-2147483648");
145 : test_conversion(INT_MIN,16,"Should show in hex");
146 :
147 : /* Test regular cases */
148 : printf("\n=== Testing regular values ===\n");
149 : test_conversion(255,16,"FF");
150 : test_conversion(255,2,"11111111");
151 : test_conversion(-255,10,"-255");
152 :
153 : /* Test zero handling */
154 : printf("\n=== Testing zero ===\n");
155 : test_conversion(0,10,"0");
156 : test_conversion(0,16,"0");
157 : test_conversion(0,2,"0");
158 :
159 : /* Test larger bases */
160 : printf("\n=== Testing different bases ===\n");
161 : test_conversion(12345,36,"Maximum supported base");
162 : test_conversion(12345,16,"Common hex value");
163 : test_conversion(12345,8,"Octal");
164 :
165 : /* Test negative values in different bases */
166 : printf("\n=== Testing negative values ===\n");
167 : test_conversion(-12345,10,"Only base 10 shows negative sign");
168 : test_conversion(-12345,16,"Should show unsigned hex");
169 : test_conversion(-1,2,"All bits set");
170 :
171 : printf("\n=== Few more examples ===\n");
172 : char buffer[33]; /* Buffer for 32-bit integer */
173 :
174 : /* Decimal conversion */
175 : itoa(12345,buffer,10);
176 : puts(buffer);
177 :
178 : /* Hexadecimal conversion */
179 : itoa(255,buffer,16);
180 : puts(buffer);
181 :
182 : /* Binary conversion */
183 : itoa(15,buffer,2);
184 : puts(buffer);
185 :
186 : /* Negative number */
187 : itoa(-789,buffer,10);
188 : puts(buffer);
189 :
190 : /* Zero case */
191 : itoa(0,buffer,10);
192 : puts(buffer);
193 :
194 : char str[100];
195 : printf("Number: %d\nBase: %d\tConverted String: %s\n",1567,10,itoa(1567,str,10));
196 : printf("Base: %d\t\tConverted String: %s\n",2,itoa(1567,str,2));
197 : printf("Base: %d\t\tConverted String: %s\n",8,itoa(1567,str,8));
198 : printf("Base: %d\tConverted String: %s\n",16,itoa(1567,str,16));
199 : }
200 :
201 : /**
202 : * @brief Test program for itoa function
203 : *
204 : * @note Tests edge cases and different bases with special focus on
205 : * negative numbers and MIN/MAX integer values
206 : */
207 : int main(void)
208 : {
209 : test_itoa();
210 :
211 : return 0; // Success
212 : }
213 : #endif
|