繁体   English   中英

通过在C语言中获取用户输入来分离单词

[英]Separating words by taking input from user in C

输入项

系统会为您提供一行文字,长度最多为1000个字符。 文本由英语单词组成。 行中的相邻单词由单个空格分隔。

第二行由单个整数“ N”组成,表示输出线的宽度。

输出量

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

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

样本输入

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

谁能帮帮我吗。

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

另外,while循环仅在EOF处终止,而不在\\ n处终止,因此您也将阅读第二行。

最后,您永远不会初始化i,因此不能保证您开始在索引0处写arr []。

如果在编译时打开了-Wall -Werror,则编译器(假设您正在使用gcc)会为您标记出最后一个错误。 从长远来看,打开所有可能的错误检查(并使警告被视为错误)将为您节省很多麻烦。

您必须先输入字符串,然后输入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;
}

像这样:

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

要完善答案集,您可以简单地使用滑动窗口来跟踪适合给定换行长度的单词。

例如,将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;
}

不管您怎么做,只要您考虑了自上次适合该行以来的字符,就可以了。

编程成功有两个关键因素(别名为“用更少的精力就能更快地获得工作程序”“在聚会上玩得开心而不是花 功夫 去做”

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

给变量n,i命名会导致不必要的认知负担(您必须记住它们的含义)。 我知道在教学C语言时使用一个字母和/或一个隐秘的名称(或不关心它)是一种悠久的传统,但这是一种愚蠢且适得其反的做法。

在问题空间中,您有类似

  • 线的最大宽度
  • 到目前为止,在线上已写入的字符数
  • 下一个字的长度

我建议您将变量重命名为word_lengthcurrent_line_widthmax_line_width 您将很快看到代码的问题。

同样,将某些关注分离可能会有所帮助。 为指定的行宽设置给定的文本字符串格式是一项明确的任务,那么为什么不编写一个函数并从main调用它呢?

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

关于另一个主题:有两种通常的方法可以解决此问题。

  • 一种是“为字符串中的每个字符做一些事情”(带有状态变量的自动机)
  • 另一个似乎更容易“对于字符串中的每个单词” ...

编辑:在这里

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

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

因此,请尝试编写清晰的代码,当您必须阅读时,这些代码看起来绝对是显而易见的。 您是在尝试使其正常运行时必须多次阅读的人。

它不会在第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("");
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM