3. Consider the following C codes. Finish the code in formatter.c which receives
ID: 3574745 • Letter: 3
Question
3. Consider the following C codes. Finish the code in formatter.c which receives an arrays of strings, reads formatting options and return the array where each line has the appropiate format using dinamically allocated memory(ex.c already creates a statically -Â allocated array of strings and passes this to the format_lines() function in formatter.c), add functions and change any code if neccesary. The following array of strings in ex.c contains the formatting option ".LW width", which indicates that the following text must be formatted such that each line following the command will be formatted such that there is never more than width characters in each line. Concatenates the lines of a paragraph in order to eliminate unnecessary white space. If this command does not appear in the input text, then the input text is not transformed in the output
Example:
Input:
.LW 30
Properly formatting a file where
there
           is
        a smattering of white space throughout
      really means eliminating that
                      extra
                              white
                                   space
       such that the result
looks neat
         and
               very
            tidy.
Output:
Properly formatting a file
where there is a smattering of
white space throughout really
means eliminating that extra
white space such that the
result looks neat and very
tidy.
ex.c
#include <stdio.h
#include <stdlib.h>
#include <string.h>
#include "formatter.h"
int main(int argc, char *argv[]) {
       char **result;
       char *lines[] = {
               ".LW 30",
               "While there   are enough characters  here to",
               "fill",
               "  at least one line, there is",
               "plenty",
               "of",
               "           white space that needs to be",
               "eliminated",
               "from the original",
               "        text file."
       };
       char **line;
       result = format_lines(lines, 10);
       for (line = result; *line != NULL; line++) {
               printf ("%s ", *line);
       }
       exit(0);
}
formatter.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "formatter.h"
char **format_lines(char **lines, int num_lines) {
       char **result = NULL;
       result = (char **)malloc(sizeof(char *) * 2);
       if (result == NULL) {
               return NULL;
       }
       result[0] = (char *)malloc(sizeof(char) * 80);
       if (result[0] == NULL) {
               return NULL;
       }
       strncpy(result[0], "(machine-like voice) EXTERMINATE THEM!", 79);
       result[1] = (char *)malloc(sizeof(char) * 2);
       if (result[1] == NULL) {
               return NULL;
       }
       result[1][0] = '';
       return result;
}
Explanation / Answer
//main.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "formatter.h"
#include "dynamic_array.h"
int main(int argc, char *argv[]) {
DynamicArray *result = NULL;
int i = 0;
 Â
char *lines[] = {
"?width 30",
"While there are enough characters here to",
"fill",
" at least one line, there is",
"plenty",
"of",
" white space that needs to be",
"eliminated",
"from the original",
" text file."Â Â
};
char **line;
result = format_lines(lines, 10);
if (result == NULL) {
printf("%s: it appears 'format_lines' is not yet complete ",
  argv[0]);
exit(1);
}
for (i = 0; i < result->length; i++){
printf("%s ", result[i]);
}
 Â
exit(0);
}
=====================================================================
/**
//file format_options.c
*/
#include "format_options.h"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
int parse_int(char *s){
char *last;
long l = strtol(s, &last, 10);
if (last[0] != ''){
fprintf(stderr, "Error converting '%s' to integer ", s);
return -1;
}
return (int) l;
}
void ws_adjust(FormatOptions *fopt, char *arg){
int n;
if ((n = parse_int(arg)) >= 0){
fopt->word_spacing = n;
}
}
void lw_adjust(FormatOptions *fopt, char *arg){
int n;
if ((n = parse_int(arg)) > 0){
fopt->line_width = n;
}
fopt->formatting = 1;
}
void lm_adjust(FormatOptions *fopt, char *arg){
int n;
int proposed_margin;
int max_margin = fopt->line_width - 20;
if (strncmp(arg, "+", 1) == 0){
n = parse_int(arg + 1);
proposed_margin = n + fopt->left_margin;
fopt->left_margin = proposed_margin > max_margin ?
max_margin : proposed_margin;
} else if (strncmp(arg, "-", 1) == 0){
n = parse_int(arg + 1);
proposed_margin = fopt->left_margin - n;
fopt->left_margin = proposed_margin < 0 ?
0 : proposed_margin;
} else {
n = parse_int(arg);
fopt->left_margin = n;
}
}
void ft_adjust(FormatOptions *fopt, char *arg){
if (strncmp(arg, "on", 2) == 0){
fopt->formatting = 1;
} else {
fopt->formatting = 0;
}
}
void ls_adjust(FormatOptions *fopt, char *arg){
int n;
if ((n = parse_int(arg)) >= 0){
fopt->line_spacing = n;
}
}
/**
* main export function
*/
void
format_options_update(FormatOptions *fopt, char *directive, char *arg){
if (strncmp(directive, ".WS", 3) == 0){
ws_adjust(fopt, arg);
} else if (strncmp(directive, ".LW", 3) == 0){
lw_adjust(fopt, arg);
} else if (strncmp(directive, ".LM", 3) == 0){
lm_adjust(fopt, arg);
} else if (strncmp(directive, ".FT", 3) == 0){
ft_adjust(fopt, arg);
} else if (strncmp(directive, ".LS", 3) == 0){
ls_adjust(fopt, arg);
}
}
void
format_options_init(FormatOptions *fopt){
fopt->left_margin = 0;
fopt->formatting = 0;
fopt->line_spacing = 0;
fopt->word_spacing = 1;
fopt->line_width = 132;
}
==========================================================================
/**
* ile format_options.h
*/
#ifndef _FORMAT_OPTIONS_H
#define _FORMAT_OPTIONS_H
typedef struct {
int left_margin;
int line_width;
int formatting;
int line_spacing;
int word_spacing;
} FormatOptions;
void
format_options_update(FormatOptions *fopt, char *directive, char *arg);
void
format_options_init(FormatOptions *fopt);
#endif /* _FORMAT_OPTIONS_H */
=======================================================================
//dynamic_array.c
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "dynamic_array.h"
void
resize(DynamicArray *da);
void
dynamic_array_init(DynamicArray *da){
da->length = 0;
da->capacity = DA_DEFAULT_SIZE;
da->items = malloc(sizeof(char *) * DA_DEFAULT_SIZE);
}
void
dynamic_array_add(DynamicArray *da, char *word){
if (da->length >= da->capacity){
resize(da);
}
char **curr_pos = da->items + da->length;
int wordlength = strlen(word);
*(curr_pos) = malloc(sizeof(char) * (wordlength + 1));
strncpy(*(curr_pos), word, wordlength);
strncpy(*(curr_pos) + wordlength, "", 1);
 Â
da->length += 1;
}
void
dynamic_array_destroy(DynamicArray *da){
int i = 0;
for (i = 0; i < da->length; i++){
free(da->items[i]);
}
free(da->items);
}
void
resize(DynamicArray *da){
da->capacity = da->capacity * 2;
da->items = realloc(da->items, (sizeof(char *) * da->capacity));
if (!da->items){
fprintf(stderr, "Realloc Error ");
exit(-1);
}
}
=====================================================================
/**
* dynamic_array.h
*/
#ifndef _DYNAMIC_ARRAY_H
#define _DYNAMIC_ARRAY_H
#define DA_DEFAULT_SIZE 100
typedef struct {
int length;
int capacity;
char **items;
} DynamicArray;
void
dynamic_array_init(DynamicArray *);
void
dynamic_array_add(DynamicArray *, char *);
void
dynamic_array_destroy(DynamicArray *);
#endif /* _DYNAMIC_ARRAY_H */
======================================================================
//formatter.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "formatter.h"
#include "dynamic_array.h"
#include "output_line.h"
#include "format_options.h"
FormatOptions *
fo_copy(FormatOptions *fopt){
FormatOptions *new_fopt = malloc(sizeof(FormatOptions));
new_fopt->formatting = fopt->formatting;
new_fopt->left_margin = fopt->left_margin;
new_fopt->line_width = fopt->line_width;
new_fopt->word_spacing = fopt->word_spacing;
new_fopt->line_spacing = fopt->line_spacing;
return new_fopt;
}
int
is_command(char *word){
char *COMMANDS[5] = {".LW", ".LM", ".FT", ".LS", ".WS"};
int i = 0;
for (i = 0; i < 5; i++){
if (strncmp(COMMANDS[i], word, 3) == 0){
return 1;
}
}
return 0;
}
/**
* my main format funciton
*/
void
format(DynamicArray *input, DynamicArray *output){
int i = 0;
int j = 0;
int linelength = 0;
char *line_cpy = NULL;
int wordlength = 0;
char *word = NULL;
char *argument = NULL;
int err;
/* setup format options */
FormatOptions *fopt = malloc(sizeof(FormatOptions));
format_options_init(fopt);
/* setup output line */
OutputLine *ol = malloc(sizeof(OutputLine));
outputline_init(ol, fo_copy(fopt));
for (i = 0; i < input->length; i++){ /* for each line */
linelength = my_strlen(input->items[i]);
if (linelength == 0){
/* dump what we've got */
outputline_dump(ol, output, 0);
/* renew outputline */
outputline_init(ol, fo_copy(fopt));
/* send through the newline */
dynamic_array_add(output, "");
for (j = 0; j < ol->fopt->line_spacing; j++){
  dynamic_array_add(output, "");
}
continue;
}
/* copy in case we don't need to format */
line_cpy = malloc(sizeof(char) * (linelength + 1));
strncpy(line_cpy, input->items[i], linelength);
strncpy(line_cpy + linelength, "", 1);
/* parse this line */
word = strtok(input->items[i], " ");
wordlength = my_strlen(word);
/* empty line */
/* if (wordlength == 0){ */
/* continue; */
/* } */
/* assume nonempty line */
if (is_command(word)){
argument = strtok(NULL, " ");
format_options_update(fopt, word, argument);
/* if the output_line is empty, we should update formatting on
  the fly
*/
if (ol->char_count == 0){
  free(ol->fopt);
  outputline_init(ol, fo_copy(fopt));
}
continue;
}
/* otherwise, this is an ordinary line */
if (! ol->fopt->formatting){
/* no formatting */
dynamic_array_add(output, line_cpy);
free(line_cpy);
continue;
}
/* continue parsing the line */
do {
sscanf(word, "%s", word);
if ((err = outputline_has_room(ol, word)) > 0){
 Â
  /* fprintf(stderr, "adding %s of length %d ", word, my_strlen(word)); */
  /* int lk = 0; */
  /* for (lk = 0; lk < my_strlen(word); lk++){ */
  /* fprintf(stderr, "char[%d] is %c ", lk, word[lk]); */
  /* } */
  /* fprintf(stderr, " "); */
 Â
  outputline_add_word(ol, word);
} else if (err < 0){
  exit(-1);
} else {
  /* gotta dump line */
  outputline_dump(ol, output, 0);
  free(ol->fopt);
  outputline_init(ol, fo_copy(fopt));
  /* now we can add */
  outputline_add_word(ol, word);
}
word = strtok(NULL, " ");
} while (word);
}
outputline_dump(ol, output, 1);
}
char *
my_getline(FILE *f){
DynamicArray *da = malloc(sizeof(DynamicArray));
dynamic_array_init(da);
char c[] = {' ', ''};
int i = 0;
char *return_line;
 Â
while ((c[0] = fgetc(f)) != EOF){
if (c[0] == ' '){
break;
}
dynamic_array_add(da, c);
}
if (c[0] != EOF){
return_line = malloc(sizeof(char) * (da->length + 1));
 Â
for (i = 0; i < da->length; i++){
strncpy(return_line + i, da->items[i], 1);
}
return_line[da->length] = '';
dynamic_array_destroy(da);
}
 Â
if (c[0] != EOF){
return return_line;
}
return NULL;
}
void
read_file_in(FILE *infile, DynamicArray *da){
/* char *lineptr = NULL; */
/* size_t n = 0; */
/* int num_chars = 0; */
/* while ((num_chars = getline(&lineptr, &n, infile)) != -1){ */
/* /* kill newline */ */
/* lineptr[num_chars - 1] = ''; */
/* dynamic_array_add(da, lineptr); */
/* } */
/* free(lineptr); */
char *this_line = my_getline(infile);
 Â
while (this_line){
dynamic_array_add(da, this_line);
free(this_line);
this_line = my_getline(infile);
}
}
DynamicArray *
format_stdin(){
DynamicArray *input;
DynamicArray *output;
input = malloc(sizeof(DynamicArray));
dynamic_array_init(input);
read_file_in(stdin, input);
output = malloc(sizeof(DynamicArray));
dynamic_array_init(output);
format(input, output);
return output;
}
DynamicArray *
format_file(FILE *infile) {
DynamicArray *input;
DynamicArray *output;
input = malloc(sizeof(DynamicArray));
dynamic_array_init(input);
/* read the input file into the input array*/
read_file_in(infile, input);
output = malloc(sizeof(DynamicArray));
dynamic_array_init(output);
format(input, output);
dynamic_array_destroy(input);
return output;
}
DynamicArray *
format_lines(char **lines, int num_lines) {
int i = 0;
DynamicArray *input;
DynamicArray *output;
input = malloc(sizeof(DynamicArray));
dynamic_array_init(input);
for (i = 0; i < num_lines; i++){
dynamic_array_add(input, lines[i]);
}
output = malloc(sizeof(DynamicArray));
format(input, output);
dynamic_array_destroy(input);
return output;
}
==================================================================
//formatter.h
#ifndef _FORMATTER_H_
#define _FORMATTER_H_
#include <stdio.h>
#include "dynamic_array.h"
DynamicArray *format_file(FILE *);
DynamicArray *format_lines(char **, int);
DynamicArray *format_stdin(void);
#ifdef DBG_FORMAT
void
format(DynamicArray *input, DynamicArray *output);
void
read_stdin(DynamicArray *da);
void
read_file_in(FILE *infile, DynamicArray *da);
#endif  /* DBG_FORMAT */
#endif  /* _FORMATTER_H_ */
================================================================
//output_line.c
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "output_line.h"
#include "dynamic_array.h"
#include "format_options.h"
int
my_strlen(char *s){
int count = 0;
if (s[0] == 'â'){
return 1;
}
for (count = 0; s[count] != ''; count++);
return count;
}
void
outputline_init(OutputLine *ol, FormatOptions *fopt){
int i = 0;
ol->fopt = fopt; Â Â Â Â Â /* should already by init'ed */
ol->words = malloc(sizeof(DynamicArray));
dynamic_array_init(ol->words);
ol->char_count = 0;
ol->space_holder = malloc(sizeof(char) * (fopt->word_spacing + 1));
for (i = 0; i < fopt->word_spacing; i++){
ol->space_holder[i] = ' ';
}
ol->space_holder[fopt->word_spacing] = '';
}
void
outputline_add_word(OutputLine *ol, char *word){
int wordlength = my_strlen(word);
if (wordlength < 1){
return;
}
if (ol->words->length == 0){ Â Â /* we're empty */
ol->char_count += wordlength;
} else {
ol->char_count += wordlength + ol->fopt->word_spacing;
}
dynamic_array_add(ol->words, word);
}
int
outputline_has_room(OutputLine *ol, char *word){
int wordlength = my_strlen(word);
if (wordlength > ol->fopt->line_width - ol->fopt->left_margin){
fprintf(stderr, "Word too long: %s ", word);
fprintf(stderr, "line_width - left_margin = %d - %d and wordlength is %d ",
  ol->fopt->line_width, ol->fopt->left_margin, wordlength);
return -1;
}
if (ol->words->length == 0){ /** current line is empty */
return ol->fopt->line_width - ol->fopt->left_margin - wordlength >= 0;
} else { /* need to account for space */
return ol->fopt->line_width - ol->fopt->word_spacing -
wordlength - ol->fopt->left_margin - ol->char_count >= 0;
}
}
void
outputline_dump(OutputLine *ol, DynamicArray *dest, int is_lastline){
int out_line_length = 0;
char *out_line = NULL;
int i = 0;
int cursor = 0; Â Â Â Â Â /* position we're writing to */
int num_words = 0;
if (ol->words->length == 0){
return;
}
/* get the length of each word */
for (i = 0; i < ol->words->length; i++){
out_line_length += strlen(ol->words->items[i]);
}
/* add whitespace in between to length */
out_line_length += (ol->words->length - 1) * ol->fopt->word_spacing;
/* add margin to length */
out_line_length += ol->fopt->left_margin;
if (! is_lastline){
/* add newlines to length */
out_line_length += ol->fopt->line_spacing;
}
/* create a new line */
out_line = malloc(sizeof(char) * (out_line_length + 1));
/* copy margin */
for (i = 0; i < ol->fopt->left_margin; i++){
strncpy(out_line + i, " ", 1);
}
cursor += ol->fopt->left_margin;
/* copy into the line */
num_words = ol->words->length;
for (i = 0; i < num_words - 1; i++){
strncpy(out_line + cursor, ol->words->items[i], strlen(ol->words->items[i]));
cursor += strlen(ol->words->items[i]);
strncpy(out_line + cursor, ol->space_holder, ol->fopt->word_spacing);
cursor += ol->fopt->word_spacing;
}
/* get the last word, no space after */
strncpy(out_line + cursor, ol->words->items[num_words - 1],
  strlen(ol->words->items[num_words - 1]));
cursor += strlen(ol->words->items[num_words - 1]);
/* add newlines */
if (! is_lastline){
for (i = 0; i < ol->fopt->line_spacing; i++){
strncpy(out_line + cursor, " ", 1);
cursor += 1;
}
}
/* cap this line */
strncpy(out_line + cursor, "", 1);
cursor += 1;
/* add it to the dynamic array */
dynamic_array_add(dest, out_line);
/* now we have to purge the output_line, and free out_line */
dynamic_array_destroy(ol->words);
dynamic_array_init(ol->words);
free(out_line);
}
=====================================================================
//output_line.h
#ifndef _OUTPUT_LINE_H
#define _OUTPUT_LINE_H
/**
* output_line class
*/
#include "format_options.h"
#include "dynamic_array.h"
typedef struct {
FormatOptions *fopt;
DynamicArray *words;
int char_count;
char *space_holder;
} OutputLine;
void
outputline_init(OutputLine *ol, FormatOptions *fopt);
void
outputline_add_word(OutputLine *ol, char *word);
int
outputline_has_room(OutputLine *ol, char *word);
/**
* pops the current line into the dynamic array
*/
void
outputline_dump(OutputLine *ol, DynamicArray *dest, int is_lastline);
#endif /* _OUTPUT_LINE_H */
==============================================================================
Related Questions
drjack9650@gmail.com
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.