— Ludwig Wittgenstein
The aim of the routine below (‘reduce_string’) is to limit a given ‘string’ to at most ‘max_len’ characters. If the length of ‘string’ exceeds ‘max_len’, characters are removed from around the middle and filled with an ‘ellipsis’ string. Here are some examples that demonstrate what ‘reduce_string’ is supposed to do:
1 2 3 4 5 6 7 8 9 10 11 |
char text1[] = "The quick brown fox"; reduce_string(text1, 8, "..") // -> "The..fox" char text2[] = "The quick brown fox"; reduce_string(text2, 4, "") // -> "Thox" char text3[] = "I am the spirit that denies!" reduce_string(text3, 7, "---") // -> "I ---s!" |
But as always in this series, a bug slipped in. Can you find it?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
char* reduce_string(char* string, int max_len, const char* ellipsis) { assert(string != NULL); assert(ellipsis != NULL); int string_len = strlen(string); int excess_chars = string_len - max_len; if (excess_chars > 0) { int ellipsis_len = strlen(ellipsis); // Number of chars to be removed from the original string. int to_be_dropped = excess_chars + ellipsis_len; int to_be_dropped_half = to_be_dropped / 2; int middle = string_len / 2; // Drop chars from the middle to the left; // what remains is called the 'left part'. int p = middle - to_be_dropped_half; // If ellipsis longer than string, skip left part; // ie. the resulting string starts with ellipsis. if (p < 0) { p = 0; } // Append ellipsis after left part. for (int i = 0; i < ellipsis_len; ++i) { // Ensure that maximum length is respected. if (p >= max_len) { break; } string[p++] = ellipsis[i]; } // Append right part. int r = middle + to_be_dropped - to_be_dropped_half; while (p < max_len) { string[p++] = string[r++]; } } return string; } |