通过从C中获取用户的输入来分隔单词

时间:2017-09-17 07:02:55

标签: c

输入

您将获得一行文字,长度最多为1000 字符。该文本由英文单词组成。相邻的单词 线由一个空格分隔。

第二行由一个整数'N'组成,表示宽度 输出线。

输出

按以下格式打印输入文本:

  1. 任何输出行都不得超过N个字符。
  2. 没有单词可以分为两行。如果一个词没有 完全符合一行,将单词移到下一行。
  3. 样本输入

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

    样本输出

    O SOFT embalmer of the still 
    midnight Shutting with careful 
    fingers
    

    说明

    每个输出行最多34个字符。 “午夜”没有 适合在第一行,因此它被移动到第二行 线。 “手指”不适合第二行,因此它被移动了 到第三行。

    #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");
    }
    

    我的代码提供了一个无限循环而没有给出输出。

    我希望通过的示例测试用例但是我失败了。

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

    任何人都可以帮助我。

6 个答案:

答案 0 :(得分:1)

有几个问题:在阅读第一行之前,您正在读取长度(位于第二行)。那不行 - scanf()在“Imagination”中看到'I'时失败,并且没有设置n,将其保留为未定义的值。

另外,你的while循环只在EOF上终止,而不是在\ n上,所以你也会读到第二行。

最后,你永远不会初始化我,因此无法保证你开始在索引0处编写arr []。

编译器(假设你正在使用gcc)会标记你的最后一个错误,如果你在编译时打开了-Wall -Werror。启用所有错误检查(并将警告视为错误)将为您带来长期的悲痛。

答案 1 :(得分:1)

您必须首先使用字符串输入然后使用int {并使用strtok()函数来断开字符串。

#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;
}

答案 2 :(得分:1)

像这样:

#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("");
}

答案 3 :(得分:1)

要简化答案集,您只需使用滑动窗口来跟踪适合给定换行长度的单词。

例如,使用sp开始指针指向一行中单词的第一个字符,ep表示结束指针指向遇到的最后一个空格,你可以做:

#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;
}

无论你怎么做,只要你考虑到最后一行结束后的角色,你就可以了。

答案 4 :(得分:1)

成功编程有两个关键因素(&#34的其他名称;用更少的努力更快地获得工作程序&#34; &#34;在派对上取笑在作业上工作迟到&#34;

  • 分解(分解成更小的功能)
  • 选择标识符。

命名变量n,i将导致您不必要的认知负荷(您必须记住它们的含义)。我知道使用一个字母和/或隐藏的名字(或者不关心它)在教授C方面是一种长期存在的传统,但它是一种愚蠢而又适得其反的名字。

在问题空间中,你有像

这样的概念
  • 行的最大宽度
  • 到目前为止在线上写的字符数
  • 下一个字的长度

我建议您将变量重命名为word_lengthcurrent_line_widthmax_line_width。您很快就会发现代码有什么问题。

此外,一些关注点分离可能有所帮助。格式化指定行宽的给定文本字符串是一个非常明确的指定任务,那么为什么不编写一个函数并从主函数中调用它呢?

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

关于另一个话题:这个问题有两种常用方法。

  • 一个是&#34;对于字符串中的每个字符都用它做什么&#34; (具有状态变量的自动机)
  • 另一个似乎更容易&#34;对于字符串中的每个单词&#34; ...

编辑:在这里

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");
}

请记住,程序员的任务不是来编写可正常工作的可执行程序。这是一个目标,但是,日常工作是花时间编写/维护将在以后工作的源代码,何时完成,删除所有错误等。并修改以供以后使用等。

因此,请尝试编写清晰的代码,这些代码在您必须阅读时看起来非常明显。在尝试使其工作时,您必须多次阅读它。

答案 5 :(得分:-1)

它不会保留第34位的空间 - 我不确定它是否是必需的。其他答案也不保留它们。

#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("");
    }
}