While I'm convinced that you are attempting to reverse a line of text rather than a sentence given,
Enter the output line length: 10
Enter your text (Enter to exit)
and your title "How to print output line length?", if you are looking solely for something that will check for the end of a sentence (e.g. a '.'
), the following can be modified without much effort.
Where you are having problems looks to be "How do I know what the number of characters in the wrapped line is?" Which is required to know how many spaces to prefix each line of output by.
The key to any line wrap scenario is to basically use a sliding window to bracket the characters that fit in each wrap length of characters (accounting for spaces between words). Meaning, you have a wrap length, but that number of characters may end in the middle of a word, so you need to keep track of the last natural break (a space normally) that occurs before that number of characters is reached. (then output the words that fit).
Your next set or characters begins not at your current counter, but at the next non-space character following the words just printed. Your count for the next group of words to output begins there. You are effectively sliding a window of wrap length chars down your string, outputting the words that fit within your sliding window, then sliding the window to capture the next group of words.
Whether you reverse the words within the window is a relatively trivial matter. Either print from the beginning to the end of the window, or the end to the beginning.
The other aspect of your problem is figuring out how many spaces to prefix each reversed group of words by. That is where the number of characters within the window is important.
An easy way to handle both the window and the length is simply to use a pair of pointers. Setting your start pointer (say sp
) to the beginning character in your windows, and your end pointer (say ep
) to the last character in each word as you work your way down the string. When you reach your wrap length number of characters, you know you have ep - sp
number of characters in the words to output. You then know you need wrap_length - (ep - sp)
number of spaces
to prefix your line.
Putting those concepts together, you can both wrap and reverse your input with something similar to the following:
void str_word_wrap_rev (char *buf, int n)
{
char *p = buf, /* pointer to current char */
*sp = buf, /* pointer to start of line to print */
*ep = buf; /* pointer to end of line to print */
size_t l = 0, /* length of segment (no. of chars */
pre = 0; /* prefix - number of spaces */
for (; *p && *p != '\n'; p++) { /* loop over each char (omit '\n')*/
if (*p == ' ') /* if space, set ep */
ep = p;
if (p - sp >= n) { /* if limit from start reached */
l = ep - sp; /* compute number of characters */
pre = n - l; /* get leading spaces required */
while (pre--) /* output spaces */
putchar (' ');
while (l--) /* loop over chars ep -> sp (reverse) */
putchar (sp[l]);
putchar ('\n'); /* tidy up with '\n' */
sp = ++ep; /* set start to next after end */
ep = ++p; /* set end to next after current */
}
} /* handle last line of chars */
l = p - sp; /* number of chars */
pre = n - l; /* number of spaces */
if (*p == '\n') /* if buf ends with '\n', decrement */
p--;
while (pre--) /* output spaces */
putchar (' ');
while (p >= sp) /* output chars */
putchar (*p--);
putchar ('\n');
}
(note: the function also checks for a string ending in '\n'
to allow buf
to be passed directly from one of the line oriented input functions, such as fgets
or POSIX getline
)
A short example similar to your example, could be:
#include <stdio.h>
#define MAXC 1000
void str_word_wrap_rev (char *buf, int n)
{
char *p = buf, /* pointer to current char */
*sp = buf, /* pointer to start of line to print */
*ep = buf; /* pointer to end of line to print */
size_t l = 0, /* length of segment (no. of chars */
pre = 0; /* prefix - number of spaces */
for (; *p && *p != '\n'; p++) { /* loop over each char (omit '\n')*/
if (*p == ' ') /* if space, set ep */
ep = p;
if (p - sp >= n) { /* if limit from start reached */
l = ep - sp; /* compute number of characters */
pre = n - l; /* get leading spaces required */
while (pre--) /* output spaces */
putchar (' ');
while (l--) /* loop over chars ep -> sp (reverse) */
putchar (sp[l]);
putchar ('\n'); /* tidy up with '\n' */
sp = ++ep; /* set start to next after end */
ep = ++p; /* set end to next after current */
}
} /* handle last line of chars */
l = p - sp; /* number of chars */
pre = n - l; /* number of spaces */
if (*p == '\n') /* if buf ends with '\n', decrement */
p--;
while (pre--) /* output spaces */
putchar (' ');
while (p >= sp) /* output chars */
putchar (*p--);
putchar ('\n');
}
int main (void) {
char buf[MAXC] = "";
int n = 0;
/* read/validate n */
printf ("Enter the output line length: ");
if (scanf ("%d%*c", &n) != 1) {
fprintf (stderr, "error: invalid conversion for 'n'\n");
return 1;
}
/* read/validate line using fgets for line-oriented input */
printf ("Enter your text (Enter to exit)\n");
if (!fgets (buf, MAXC, stdin) || *buf == '\n') {
fprintf (stderr, "error: EOF or empty string\n");
return 1;
}
putchar ('\n');
str_word_wrap_rev (buf, n); /* reverse and wrap */
for (int i = 1; i <= n; i++)
putchar ('0' + i % 10);
putchar ('\n');
return 0;
}
Example Use/Output
$ ./bin/str_rev_wrap
Enter the output line length: 10
Enter your text (Enter to exit)
The quick brown fox jumps over the lazy old dog.
kciuq ehT
xof nworb
revo spmuj
yzal eht
.god dlo
1234567890
$ ./bin/str_rev_wrap
Enter the output line length: 25
Enter your text (Enter to exit)
The quick brown fox jumps over the lazy old dog.
spmuj xof nworb kciuq ehT
.god dlo yzal eht revo
1234567890123456789012345
Look things over and let me know if you have further questions.
(note: It may help to simply write your input out on a piece of paper and draw the start, end and current character pointers below the string and move them manually to understand exactly what is taking place.)