Home > Blockchain >  Cut string by words
Cut string by words

Time:03-02

I need to cut string by words and put them in rows if row width can accept them. If not, they should be put in the next row.

OUTPUT:

--------------------
 The applicant must 
 have some hardware 
 construction 
 experience and be 
 fluent in C and 
 assembly language 
 programming.

Code:

#include <stdio.h>
void cut_words(const char *sentence, int width) {
  int i, j = 0,k, count = 0,rows=0,stop=0,rest;
   for (i = 0; i < width; i  )
    printf("-");
  printf("\n ");
  while (sentence[j] != '\0') {
    count  ;
    printf("%c", sentence[j]);
    j  ;
    if (count> width) {
      printf("\n ");
      count = 0;
    }
  }
}
int main() {
  const char sentence[1000] = "The applicant must have some hardware construction experience and be fluent in C and assembly language programming.";
  int width = 20;
  cut_words(sentence, width);
  return 0;
}
  • Note: auxiliary strings cannot be used.

CodePudding user response:

I'm going to guess you're supposed to do this without using library functions. Line filling and breaking text is a classic exercise. I don't know if you're expected to get a word at a time to fill the lines, such that multiple spaces in the input get collapsed. If not, another approach is to start at a nonspace, look at where the width would fill, then back up if you're at a space or in the middle of a word. Print what you then have, and start again with the next word.

void cut_words(const char *sentence, int width) {
    char *s = (char *)sentence;
    for (int i = 0; i < width; i  )
        printf("-");
    printf("\n");
    // 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);
}

Now, see if you can do that using just indexes instead of pointers. Or, more challenging, try to step along the string and find the beginning and end of each word and print them, keeping track of how much space is left in each row.

CodePudding user response:

I don't much like my previous answer. I think you're supposed to grab a word at a time and print it with one leading space. So I'll describe the pieces and let you put them together. If you can't get it right then show what you have and we'll go from there.

Initialize a pointer as above (but I needn't cast away the const): const char *s = sentence; and set a var to hold the number of characters left to fill on the line: int nleft = width;.

Skip leading spaces: while (*s && *s == ' ') s ;

Now loop until end of string: while (*s). Each time you enter the loop, *s will be the next non-space char to print. Find the boundary after the word and compute the length. If there's not enough room on the line for it (including a space), print a newline, reset nleft. Then print a space and the word, decrement nleft by the number of chars printed (including space). The only catch is if the word is too long to fit on a line, then you'll want to print it piecewise.

After printing, advance s over spaces so it's on a non-space or end of string. After the loop, check if there's anything on the current line and print a newline if so.

At top of loop:

  const char *e = s;
  while (*e && *e != ' ')
    e  ;
  int len = e - s;

If len exceeds width - 1 then set it to width - 1 as that's the longest piece you can print on a line.

The line is empty if nleft == width. There's insufficient space if len 1 > nleft. If there's insufficient space AND the line is non-empty, print a newline and reset nleft. Then print a space and len chars starting at s. Note the use of %*.*s format in my previous answer.

After printing, bump s by len and decrement nleft by number of chars printed. And now loop to advance s to the next nonspace or end of string. Note that if you had printed part of a too-long word (over width-1 chars) then s is already at the next non-space to print.

Also note that the condition "s points to next nonspace to print" at the top of the loop is an "invariant", an important concept in reasoning about loops. If a loop isn't obvious, consider what invariants should be maintained by it and what conditions should hold after it exits.

  • Related