0

I am trying to wrap a long line using line length and print one line(of line length) at a time instead of printing the whole line as a chunk. I thought adding '\n' character at every line length would do the job and wrote the following code.

void wrap(char *tok, int len)
{
  int i, h;
  char *ss = tok;
  for (h = linelen; h < (len + 1); (h + linelen))
    {
      ss[h] = '\n';
      printf("%d\n", h);
      h += linelen;
    }
  char *token = strtok(ss, "\n");
  while (token)
    {
        printf("%s\n", token);
        token = strtok(NULL, "\n");
    }
}

But this code doesn't seem to be working. What other ways can I approach to achieve line wrapping?

Bunny Bunny
  • 745
  • 2
  • 6
  • 9
  • What is `linelen`? Anyways, wrapping text is harder than it seems. You can look a how [fmt](http://code.metager.de/source/xref/DragonFly-BSD/usr.bin/fmt/fmt.c) does it. – jxh Apr 06 '13 at 16:05
  • Number of columns a window can accommodate. – Bunny Bunny Apr 06 '13 at 16:09
  • Perhaps `h + linelen` -> `h += linelen` , `ss[h] = '\n'` broken original character. – BLUEPIXY Apr 06 '13 at 16:09
  • @BunnyBunny: How is `linelen` different from `len`? – jxh Apr 06 '13 at 16:12
  • Your mechanism forcibly breaks the line in the middle of a word. It is usually better to try and find a break between words — white space — just before the break point. You may be forced into a mid-word break if the word is longer than the line length. – Jonathan Leffler Apr 06 '13 at 16:32

3 Answers3

2

Stolen from this post: Is it possible to print out only a certain section of a C-string, without making a separate substring?

#include <stdio.h>
#include <string.h>

int main(void) {

    char *str = "helo world";
    int total_len = strlen(str);
    int single_len = 3;
    for (int i = 0; i < total_len; i += single_len) {
        /* print at most first three characters (safe) */
        printf("%.*s\n", single_len, str + i);
    }

    return 0;
}
Community
  • 1
  • 1
gongzhitaao
  • 6,566
  • 3
  • 36
  • 44
1

You don't need to change the original string, you just need to print out extra newlines when necessary:

void wrap(char *str, int len, int linelen) {
    int i;
    for (i = 0; i < len; ++i) {
        printf("%c", str[i]);
        if (i > 0 && i % linelen == 0) {
            printf("\n");
        }
    }
}

If your original string might have newlines in it, you can keep track of the current line's length so that the next line is wrapped correctly:

void wrap(char *str, int len, int linelen) {
    int i, currlen;
    for (i = 0, currlen = 0; i < len; ++i, ++currlen) {
        printf("%c", str[i]);
        if (str[i] == '\n') {
            currlen = 0;
        }
        if (currlen > 0 && currlen % linelen == 0) {
            printf("\n");
        }
    }
}
Xymostech
  • 9,710
  • 3
  • 34
  • 44
1

Your program seems to want to break up tok into multiple linelen bytes, but you don't seem to care about what character you are replacing to achieve that. This makes your wrap routine drop information that was in the original input. You then call strtok to print one token at a time, but the damage is already done.

Instead, I believe you should restructure your code so that strtok is used to find a token, and you compute whether printing the current token will put you over your linelen or not. If it will, you print a newline, print the token, and compute your current running line length as just the length of the token you just printed. Each token you print on the same line will increment the running line length.

void wrap(char *tok, int linelen)
{
  int len = 0;
  char *ss = tok;
  char *token = strtok(ss, " \t\n");
  while (token) {
    int tokenlen = strlen(token);
    if (len && (len + tokenlen + 1 > linelen)) {
      puts("");
      len = 0;
    }
    if (tokenlen) {
      printf("%s%s", len ? " " : "", token);
      len += 1 + tokenlen;
    }
    token = strtok(0, " \t\n");
  }
  if (len) puts("");
}

Your original implementation does not take into account how to treat tab characters. If you add all linear whitespace characters to the strtok delimiters, then all tabs will be treated like a token separator, and will be dropped when the input is wrapped. Correctly dealing with tabs will complicate your running line length calculation, since a tab character will cause the line length to jump to the next tab stop.

jxh
  • 69,070
  • 8
  • 110
  • 193