打印出字符串中的第三个单词。 C

时间:2018-10-12 20:30:25

标签: c

因此,我正在尝试编写一个程序,该程序需要一个句子并将其从第三个单词中打印出来。前one two three four应打印出three four

现在此代码有效,但我不知道为什么else语句下的逻辑使它看起来不应该如此。

如果有人能解释为什么会这样,将不胜感激。

代码如下:

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

#define SIZE 100

int main(void) {
    char arr[SIZE];
    char *point;
    char again = 'n';

    do {
        int count = 0;
        for (int i = 0; i < SIZE; i++) {
            arr[i] = '\0';
        }
        printf("Enter a sentence:");
        gets(arr);
        for (int i = 0; i < SIZE; i++) {
            if (arr[i] == ' ') {
                count++;
            }
        }
        if (count < 2) {
            printf("The sentence is to short!\n");
        } else {
            count = 1;  //shouldn't this be count = 0?
            for (int i = 0; i < SIZE; i++) {
                if (arr[i] == ' ') {
                    count++;
                }
                if (count == 2) {
                    point = &arr[i + 2]; //shouldn't this be [i+1]? 
                }
            }
            printf("%s\n", point);
        }
        printf("Do you want to try again? (y/n)");
        scanf("%c", &again);
        while (getchar() != '\n');
    } while (again == 'y' || again == 'Y');

    return 0;
}

3 个答案:

答案 0 :(得分:1)

您的代码有多个问题:

  • 请勿使用gets()。此功能已从C标准中删除,因为无法给它提供最大数量的字符以写入目标缓冲区,因此输入流中足够长的行将导致未定义的行为。这是一个经典的安全漏洞。请改用fgets()
  • 如果文件末尾没有换行,循环while (getchar() != '\n');将导致无限循环,如果您重定向输入一个空文件,则会发生无限循环。您还应该检查EOF

    while ((c = getchar()) != EOF && c != '\n')
        continue;
    
  • 不需要初始化目标数组,但是您应该通过比较fgets()NULL的返回值来检查输入操作是否成功。
  • 遍历数组以计算空间时,应在null终止符处停止。输入操作后,空终止符之后的数组的内容是不确定的,如果在调用之前对其进行了初始化,则甚至
  • 跳过单词的代码很麻烦,并且不容易验证。确实point = &arr[i+2];应该是point = &arr[i+1]
  • 单词可能用多个空格隔开,并且初始空格应忽略。

以下是使用字符串函数strspnstrcspn跳过空格和非空格的更正版本:

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

#define SIZE  100
#define WS  " \t\n\r\v\f"  /* white space characters */

int main(void) {
    char arr[SIZE];
    char *p;

    for (;;) {
        printf("Enter a sentence:");
        if (fgets(arr, sizeof arr, stdin) == NULL)
            break;
        p = arr;
        p += strspn(p, WS);     /* skip initial spaces */
        p += strcspn(p, WS);    /* skip first word */
        p += strspn(p, WS);     /* skip spaces */
        p += strcspn(p, WS);    /* skip second word */
        p += strspn(p, WS);     /* skip spaces */

        if (*p == '\0') {
            printf("The sentence is too short!\n");
        } else {
            printf("%s", p);
        }
        printf("Do you want to try again? (y/n)");
        if (fgets(arr, sizeof arr, stdin) == NULL)
            break;
        if (*arr != 'y' && *arr != 'Y')
            break;
    }
    return 0;
}

答案 1 :(得分:1)

处理字数统计的另一种简单方法是在状态循环中沿字符串走指针 ,以跟踪您是否in一个单词(如果增加单词数的话),否则您不是in一个单词,而只是保持沿着前进(即遍历每个字符)直到找到下一个单词(或字符串的结尾)。

在填充缓冲区并设置指向其的指针后,逻辑很简单

#define MAXC  1024  /* buffer size (don't skimp) */
#define NWORD    3  /* output beginning with NWORD word */
...    
        char buf[MAXC] = "",    /* buffer to hold line */
            *p = buf;           /* pointer to walk down buffer */
        int n = 0,              /* word counter */
            in = 0;             /* flag - in a word */

只需循环使用isspace()检查每个字符,然后处理将in标志设置为1(字)或0(字前或字之间的空格)递增每次您in输入一个新单词时,计数器就会计数,计数达到3时退出循环,例如

        for (; *p; p++) {               /* loop over each char */
            if (!in && !isspace(*p)) {  /* if not in word and not space */
                in = 1, n++;            /* set in flag, increment words */
                if (n == NWORD)         /* if 3rd word, break */
                    break;
            }
            else if (isspace(*p))       /* if space */
                in = 0;                 /* unset in flag */ 
        }

在一个简短的示例中将其全部放入,您可以执行与以下操作类似的操作:接受输入,直到在空行上单独按下 Enter 键,然后输出从第三行开始输入的每个句子-word,如果输入的单词少于三个单词,则显示错误"too few words.",例如

#include <stdio.h>
#include <ctype.h>

#define MAXC  1024  /* buffer size (don't skimp) */
#define NWORD    3  /* output beginning with NWORD word */

int main (void) {

    for (;;) {                  /* loop continually until empy-line */
        char buf[MAXC] = "",    /* buffer to hold line */
            *p = buf;           /* pointer to walk down buffer */
        int n = 0,              /* word counter */
            in = 0;             /* flag - in a word */

        fputs ("\nenter sentence: ", stdout);               /* prompt */
        if (!fgets (buf, MAXC, stdin) || *buf == '\n') {    /* read line */
            puts ("all done!");
            break;
        }

        for (; *p; p++) {               /* loop over each char */
            if (!in && !isspace(*p)) {  /* if not in word and not space */
                in = 1, n++;            /* set in flag, increment words */
                if (n == NWORD)         /* if 3rd word, break */
                    break;
            }
            else if (isspace(*p))       /* if space */
                in = 0;                 /* unset in flag */ 
        }

        if (n == NWORD) /* if 3 or more words */
            fputs (p, stdout);
        else            /* other wise handle error */
            fputs ("too few words.\n", stderr);
    }

    return 0;
}

使用/输出示例

$ ./bin/thirdword

enter sentence: one two three four five
three four five

enter sentence: one two
too few words.

enter sentence:   one   two   three
three

enter sentence:
all done!

仔细检查一下,如果还有其他问题,请告诉我。

答案 2 :(得分:0)

  

count = 1; //这不应该算为0吗?和point = &arr[i + 2]; //不应该是[i + 1]吗?

以下内容回答了两个问题。

count    count     count       count
  0        1         2           3
     one       two       three       four
     i+0       i+1       i+2         i+3

point = &arr[i + 2];printf("%s\n", point);一起表示从地址arr[i + 2]直到看到\0字符为止打印所有字符