Skip to content

Instantly share code, notes, and snippets.

@vpetrigo
Created June 12, 2018 18:56
Show Gist options
  • Save vpetrigo/2e3885ee6ea677cc897895d83e4891fd to your computer and use it in GitHub Desktop.
Save vpetrigo/2e3885ee6ea677cc897895d83e4891fd to your computer and use it in GitHub Desktop.
// 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