Created
June 12, 2018 18:56
-
-
Save vpetrigo/2e3885ee6ea677cc897895d83e4891fd to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// string_carryover.c : Defines the entry point for the console application. | |
#include <stdbool.h> | |
#include <stdio.h> | |
#include <string.h> | |
#define MAX_LINES 2 | |
#define MAX_LINE_LENGTH 14 | |
#define NULL_TERM_LINE_LENGTH (MAX_LINE_LENGTH + 1) | |
#define MIN_HYPHEN_CAP 4 | |
#define DOTS_NUM 3 | |
struct string_split | |
{ | |
char **lines; | |
size_t capacity; | |
size_t size; | |
size_t max_lines; | |
size_t line_length; | |
}; | |
char *lines_ptr[MAX_LINES]; | |
char lines_storage[MAX_LINES][NULL_TERM_LINE_LENGTH]; | |
static struct string_split split = {.capacity = MAX_LINES * MAX_LINE_LENGTH, | |
.size = 0, | |
.max_lines = MAX_LINES, | |
.line_length = MAX_LINE_LENGTH}; | |
int append_word(const char *word, size_t word_size, struct string_split *split); | |
size_t calculate_req_lines(size_t cur_line, size_t word_size, | |
const struct string_split *split); | |
static inline void put_dots(struct string_split *split) | |
{ | |
strncpy(&split->lines[split->max_lines - 1][split->line_length - DOTS_NUM], | |
"...", DOTS_NUM); | |
} | |
int format_string(const char *str, struct string_split *split) | |
{ | |
size_t length = strlen(str); | |
split->size = 0; | |
for (size_t i = 0; i < split->max_lines; ++i) | |
{ | |
memset(split->lines[i], '\0', (split->line_length + 1)); | |
} | |
if (length <= split->line_length) | |
{ | |
strncpy(split->lines[0], str, length); | |
return 0; | |
} | |
const char *ptr = str; | |
const char *space_pos = NULL; | |
while ((space_pos = strchr(ptr, ' ')) != 0) | |
{ | |
size_t word_size = space_pos - ptr; | |
if (append_word(ptr, word_size, split) != 0) | |
{ | |
put_dots(split); | |
break; | |
} | |
length -= space_pos - ptr + 1; | |
ptr = space_pos + 1; | |
} | |
if (length != 0) | |
{ | |
if (append_word(ptr, strlen(ptr), split) != 0) | |
{ | |
put_dots(split); | |
} | |
} | |
return 0; | |
} | |
int append_word(const char *word, size_t word_size, struct string_split *split) | |
{ | |
if (split->size == split->capacity) | |
{ | |
return 1; | |
} | |
size_t cur_line = split->size / split->line_length; | |
size_t cur_put_position = split->size % split->line_length; | |
size_t lines_required = | |
calculate_req_lines(cur_line, cur_put_position + word_size, split); | |
size_t word_offset = 0; | |
int retval = 0; | |
for (size_t i = 0; i < lines_required - 1; ++i) | |
{ | |
size_t to_write = split->line_length - cur_put_position - 1; | |
strncpy(&split->lines[cur_line][cur_put_position], word + word_offset, | |
to_write); | |
split->lines[cur_line][split->line_length - 1] = '-'; | |
word_size -= to_write; | |
word_offset += to_write; | |
split->size += to_write + 1; | |
cur_put_position = 0; | |
++cur_line; | |
} | |
if (cur_line + 1 == split->max_lines && | |
cur_put_position + word_size > split->line_length) | |
{ | |
strncpy(&split->lines[cur_line][cur_put_position], word + word_offset, | |
split->line_length - cur_put_position); | |
split->size = split->capacity; | |
retval = 1; | |
} | |
else | |
{ | |
strncpy(&split->lines[cur_line][cur_put_position], word + word_offset, | |
word_size); | |
split->size += word_size; | |
if (cur_put_position + word_size < split->line_length) | |
{ | |
split->lines[cur_line][cur_put_position + word_size] = ' '; | |
++split->size; | |
} | |
} | |
return retval; | |
} | |
size_t calculate_req_lines(size_t cur_line, size_t word_size, | |
const struct string_split *split) | |
{ | |
size_t num_of_hyphens = | |
((word_size + split->line_length - 1) / split->line_length) - 1; | |
size_t total_num_of_char = word_size + num_of_hyphens; | |
size_t lines_required = | |
(total_num_of_char + split->line_length - 1) / split->line_length; | |
return (cur_line + lines_required <= split->max_lines) | |
? lines_required | |
: split->max_lines - cur_line; | |
} | |
static void init_split(struct string_split *split) | |
{ | |
split->lines = lines_ptr; | |
for (size_t i = 0; i < MAX_LINES; ++i) | |
{ | |
split->lines[i] = &lines_storage[i]; | |
} | |
} | |
static void print_lines(const struct string_split *split) | |
{ | |
for (size_t i = 0; i < split->max_lines; ++i) | |
{ | |
printf("%s\n", split->lines[i]); | |
} | |
} | |
int main(void) | |
{ | |
const char test0[] = "Test"; | |
const char test1[] = "Veeeeeeeeeeeery longggggggg"; | |
const char test2[] = "VEEEEEEEEEEEEEEEEEEERRRRRRRRRRRRRRRRYYYYYYYYYYYY"; | |
const char test3[] = "WORLDS LIKELYS VERY LONG STORY"; | |
const char test4[] = "A A A A A A A A A A A A A A A A A A A A A A A"; | |
const char test5[] = "01234567899876 01234567899876"; | |
const char test6[] = "Very loooooooooong line"; | |
init_split(&split); | |
format_string(test0, &split); | |
printf("%s\n", split.lines[0]); | |
puts("============="); | |
format_string(test1, &split); | |
print_lines(&split); | |
puts("============="); | |
format_string(test2, &split); | |
print_lines(&split); | |
puts("============="); | |
format_string(test3, &split); | |
print_lines(&split); | |
puts("============="); | |
format_string(test4, &split); | |
print_lines(&split); | |
puts("============="); | |
format_string(test5, &split); | |
print_lines(&split); | |
puts("============="); | |
format_string(test6, &split); | |
print_lines(&split); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment