1

Input

You are given a single line of text, with length at most 1000 characters. The text consists of English words. Adjacent words in the line are separated by a single space.

The second line consists of a single integer 'N' denoting the width of an output line.

Output

Print the input text in the following format:

  1. no line of output must be more than N characters long.
  2. no word can be split across two lines. If a word does not completely fit in a line, move the word to the next line.

Sample Input

O SOFT embalmer of the still midnight Shutting with careful fingers 
34

Sample Output

O SOFT embalmer of the still 
midnight Shutting with careful 
fingers

Explanation

Each output line is at most 34 characters long. "midnight" does not fit on the first line, hence it was moved to the second line. "fingers" does not fit on the second line, hence it was moved to the third line.

#include<stdio.h>

void main()
{
  int n,i,c;
  char arr[1000];
  scanf("%d",&n);
  //input
  while((c=getchar())!=EOF)
  {
    arr[i]=c;
    i++;
  }
  //checking
  while(i!=n)
  {
    printf("%c",arr[i]);
    i++;
  }
  printf("\n");
}

my code is giving an infinite loop and is not giving the output.

sample test case which I want to pass but I am failing.

Input   
Imagination is more powerful than knowledge
14

OUTPUT
Imagination is\n
 more powerful\n
 than \n
knowledge

can anyone please help me.

BLUEPIXY
  • 39,699
  • 7
  • 33
  • 70
Atanu Mondal
  • 61
  • 1
  • 12

6 Answers6

1

Several problems: you are reading the length (which is on the second line) before you read the first line. That's not going to work--the scanf() fails when it sees the 'I' in "Imagination" and does not set n, leaving it at an undefined value.

Also, your while loop terminates on EOF only, not on \n, so you will read the second line as well.

Finally, you are never initializing i, so it is not guaranteed that you are starting writing arr[] at index 0.

The complier (assuming you are using gcc) would have flagged that last error for you, had you turned on -Wall -Werror when you compiled. Turning on all the error checking you can (and causing warnings to be treated as errors) will save you a lot of grief in the long run.

One Guy Hacking
  • 1,176
  • 11
  • 16
1

You must take string input first then int and break the string using strtok() function.

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

int main (void)
{
    int n,i=0,count=0,len;
    char arr[1000];
    char *token;
    fgets(arr, sizeof(arr), stdin);
    scanf("%d",&n);
    //checking
    token = strtok(arr, " ");
    while (token != NULL)
    {
        len=strlen(token);
        count+=len;
        if(count<n)
        {
            printf("%s ", token);
            count++;
        }
        else if(count==n)
        {
            printf("%s", token);
            printf("\n ");
            count=1;
        }
        else
        {
            printf("\n%s ", token);
            count=len+1;
        }
        token = strtok(NULL, " ");
    }
    return 0;
}
Aashish Kumar
  • 2,771
  • 3
  • 28
  • 43
  • No need for `strtok`, you can simply use a *sliding window*, either denoted by indexes or a start and end pointer. `strtok` is simply one option. – David C. Rankin Sep 17 '17 at 10:06
  • @DavidC.Rankin you are right. We can also achieve the same without using `strtok()`, but using `strtok()` we minimize the length of the code. – Aashish Kumar Sep 17 '17 at 10:11
  • I'll see you one and raise you a sliding window on code length -- even including full validations `:)` – David C. Rankin Sep 17 '17 at 10:12
1

like this:

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

int main(void){
    char arr[1000+2];//+2: newline + NUL
    fgets(arr, sizeof arr, stdin);

    int N;
    if(scanf("%d", &N) != 1 || N <= 0){
        fputs("invalid input\n", stderr);
        return -1;
    }

    char *p = arr;
    size_t output_len = 0;

    while(*p){
        size_t word_len = strcspn(p, " \n");
        if(!word_len){
            break;
        } else if(!!output_len + output_len + word_len <= N){// <= N: exclude newline, if include newline Change <= to < 
            if(!!output_len){
                putchar(' ');
                ++output_len;
            }
            printf("%.*s", (int)word_len, p);
            output_len += word_len;
            p += word_len + 1;//+ 1: skip space or newline
        } else {
            puts("");
            output_len = 0;
        }
    }
    puts("");
}
BLUEPIXY
  • 39,699
  • 7
  • 33
  • 70
  • It can be broken by any double space and it doesn't preserve all spaces though I am not sure that this is a necessity. – vollitwr Sep 17 '17 at 10:14
  • @vollitwr _Adjacent words in the line are separated by a **single space**._ – BLUEPIXY Sep 17 '17 at 10:15
  • Oooh -- I like the catch of `1000+2`, well done. (even though arguably `1000+1` would do it, just chopping off the trailing `'\n'` `:)` – David C. Rankin Sep 17 '17 at 10:16
1

To round out the set of answers, you can simply use a sliding-window to keep track of the words that will fit within the given wrap length.

For example, using a sp for start-pointer to point to the first character of the word in a line, and ep for end-pointer to point to the last space encountered, you can do:

#include <stdio.h>

#define MAXC 1000

int main (void) {

    char buf[MAXC+2] = "",  /* good job BLUEPIXY */
        *p = buf,   /* pointer to current char */
        *sp = buf,  /* pointer to start of line to print */
        *ep = buf;  /* pointer to end of line to print */
    int n = 0;

    /* read/validate line using fgets for line-oriented input */
    if (!fgets (buf, MAXC, stdin) || *buf == '\n') {
        fprintf (stderr, "error: EOF or empty string\n");
        return 1;
    }
    /* read/validate n */
    if (scanf ("%d", &n) != 1) {
        fprintf (stderr, "error: invalid conversion for 'n'\n");
        return 1;
    }

    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 */
            while (sp < ep)         /* loop over chars sp -> ep */
                putchar (*sp++);
            putchar ('\n');         /* tidy up with '\n' */
            sp = ++ep;              /* set start to next after end */
            ep = ++p;               /* set end to next after current */
        }
    }
    while (*sp && *sp != '\n')      /* output last line of chars */
        putchar (*sp++);
    putchar ('\n');

    return 0;
}

No matter how you do it, as long as you account for the characters since the last end-of-line-that-fit, you will be fine.

David C. Rankin
  • 81,885
  • 6
  • 58
  • 85
1

There are 2 key factors for success in programming (other name for "getting working programs sooner with less efforts" and "having fun at parties instead of working late on assignments")

  • decomposition (break into smaller functions)
  • choice of identifiers.

Naming variables n,i will lead you to unnecessary cognitive load (you have to remember what they mean). I know that using one-letter and/or cryptic names (or not caring about it) is sort of a long-established tradition in teaching C, but it is a silly and very counter-productive one.

In the problem space, you have notions like

  • maximum width for the line
  • number of chars written so far on the line
  • length of the next word

I suggest you rename your variables as word_length, current_line_width, max_line_width. You'll quickly see what's wrong with your code.

Also, some separation of concerns may help. Formatting a given text string for a specified line width is a cleary specified task, so why not write a function and call it from the main?

int main() 
{
    char *test_string = "This is a very long string for my first test";
    format_string(test_string, 10);
    return 0;
}

On another topic : there are two usual approaches to this problem.

  • One is "for each char in the string do something with it" (an automaton with state variables)
  • The other seems easier "for each word in the string" ...

EDIT: here it goes

void format_string(char string[], int max_width)
{
  char *position = string;
  int line_length = 0;

  for(;;) {                              // a loop over words

        // get a word

        while(*position == ' ') {
               position++;              // skip spaces
        }
        if (*position == '\0') {
               break;                   // no more words -> break
        }

        // found one !

        char *word_start = position;    
        while((*position != ' ') && (*position) != '\0') {
               position++;
        }
        char *word_end = position;      
        int word_length = word_end - word_start; 

        // skip to next line if needed
        // a word longer than max_width will
        // be printed alone beyond the right margin

        int new_width = line_length + word_length + 1; 
        if ((line_length != 0) 
            && ( new_width > max_width)) {
              printf("\n");
              line_length = 0;
        }

        // add space between words if needed
        if (line_length != 0) {
          printf(" ");
          line_length++;
        }

        // put word
        for (char *p = word_start; p != word_end; p++) {
          printf("%c", *p);
          line_length++;
        }
    }

    printf("\n");
}

Remember the task of the programmer is not to write executable programs that work correctly. That's one objective, but, the daily work is to spend time writing/maintaining source code that will work later, when it will be completed, all bugs removed etc. And modified for later uses, etc.

So please try to write crystal-clear code that seems absolutely obvious when you have to read it. You are the one who will have to read it many times while trying to make it work.

Michel Billaud
  • 1,758
  • 11
  • 14
-1

It doesn't preserve spaces at the 34th position - I am not sure that it is required. Other answers don't preserve them too.

#include<stdio.h>
#include<string.h>
void main() {
    int n, i = 0, c;
    char arr[1000], *p, *q;
    //input
    while((c = getchar()) != '\n')
        arr[i++] = c;
    scanf("%d", &n);
    i = 0;
    q = arr;
    //checking
    p = strchr(q, ' ');
    while (p) {
       while (p - q + i < n) {
           p[0] = 0;
           printf("%s ", q);
           i += p - q + 1;
           q = p + 1;
           p = strchr(q, ' ');
           if (p == 0) break;
       }
       i = 0;
       puts("");
    }
}
vollitwr
  • 429
  • 2
  • 8