简体   繁体   中英

Manipulating string for specific length

I need to analyze string and put it centered inside a frame according to width and specific rules.

  • There must be at least one space at the beginning and at least one space at the end of row.
  • If number of spaces that need to be added is odd, excess space should be added to the right.
  • If the whole word cannot fit in the row, word is printed in the next row.
  • If the word is longer than row width, word should be split in parts which will be printed in a row in which they can fit complete. Default is to split word in two parts. If that's not possible, word is split proportionally according to the width of row.
  • Auxiliary strings are not allowed.

EXAMPLE 1:

const char text[]="This is word with four characters";
int width = 20;

********************
*   This is word   *
*    with four     *
*    characters    * 
********************

EXAMPLE 2:

const char text[]="This word Thyroparathyroidectomized is too long for frame";
int width = 20;

********************
*    This word     * 
*  Thyroparathy-   *
* roidectomized is *
*   too long for   *
*      frame       *
********************

EXAMPLE 3:

const char text[]="This word Thyroparathyroidectomized is too long for frame";
int width = 10;

**********
*  This  * 
*  word  * 
* Thyro- *
* parat- *
* hyroi- *
* decto- *
* mized  *
* is too *
*  long  *
*   for  *  
* frame  *
**********

Code:

#include <stdio.h>
#include <string.h>
void cut_words(const char *text, int width) {
  char *s = (char *)text;
  // skip leading spaces
  while (*s && *s == ' ')
    s++;
  while (strlen(s) > width) {
    // *s must be nonspace and not EOS
    char *e = s + width - 1;
    // *e is last char that can possibly fit
    // *e cannot be EOS nor can e[1]
    // back up to nonspace if at space
    while (*e == ' ')
      e--;
    // *e is inside or end of word
    if (e[1] != ' ') {
      // not end of word; must be inside
      // back up to prev space
      while (e > s && *e != ' ')
        e--;
      // if e == s then no word break
      // must assume word is longer than width
      if (e == s)
        e = s + width - 1;
      else
        // find end of prev word
        while (e > s && *e == ' ')
          e--;
    }
    // *e is end of word
    int k = e - s + 1;
    printf("* %*.*s *\n", k, k, s);
    s += k;
    while (*s && *s == ' ')
      s++;
  }
  if (*s)
    printf("* %s *\n", s);
}
void framed(const char *text, int width) {
  int i;
  for (i = 0; i < width; i++)
    printf("*");
  printf("\n");
  cut_words(text, width - 4);
  for (i = 0; i < width; i++)
    printf("*");
}
int main() {
  const char text[] = "This is word with four characters";
  int width = 20;
  framed(text, width);
  return 0;
}

MY OUTPUTS:

********************
* This is word *
* with four *
* characters *
********************

********************
* This word *
* Thyroparathyroid *
* ectomized is too *
* long for frame *
********************

**********
* This *
* word *
* Thyrop *
* arathy *
* roidec *
* tomize *
* d is *
* too *
* long *
* for *
* frame *
**********

Could you help me center words in rows?

In your code you have:

int k = e - s + 1;
printf("* %*.*s *\n", k, k, s);

and

if (*s)
  printf("* %s *\n", s);

But that doesn't try to pad the words at all. To add padding you need to print a certain number of spaces before and after the word. You can do that the same way you are printing a certain number of characters of the string ( %*.*s )

You need to replace those bits of code with

int k = e - s + 1;
int b = (width-k)/2;
int a = (width-k)/2+(width-k)%2;
printf("* %*.*s%*.*s%*.*s *\n", b, b, "", k, k, s, a, a, "");

and

if (*s) {
  k = strlen(s);
  b = (width - k) / 2;
  a = (width - k) / 2 + (width - k) % 2;
  printf("* %*.*s%*.*s%*.*s *\n", b, b, "", k, k, s, a, a, "");
}

That fixes the centering problem. But you aren't hyphenating the words - you are just cutting them into pieces. So you need to account for the hyphen.

To make the portion smaller when the word is going to be cut so there is room for the hyphen you can change

// if e == s then no word break
// must assume word is longer than width
if (e == s)
  e = s + width - 1;

to

// if e == s then no word break
// must assume word is longer than width
if (e == s)
  e = s + width - 2;

Then you can change

k = e - s + 1;
b = (width - k) / 2;
a = (width - k) / 2 + (width - k) % 2;
printf("* %*.*s%*.*s%*.*s *\n", b, b, "", k, k, s, a, a, "");

to

k = e - s + 1;
b = (width - k) / 2;
a = (width - k) / 2 + (width - k) % 2;
if (lenght_prev_word(s) > width)
  printf("* %*.*s%*.*s-%*.*s *\n", b, b, "", k, k, s, a-1, a-1, "");
else
  printf("* %*.*s%*.*s%*.*s *\n", b, b, "", k, k, s, a, a, "");

And a hyphen will be printed only when the word is longer than the width.

The full program be found at https://onlinegdb.com/4_9eQwA_H

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM