繁体   English   中英

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

[英]Print out the third word in a string. 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;
}

您的代码有多个问题:

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

     while ((c = getchar()) != EOF && c != '\\n') continue; 
  • 不需要初始化目标数组,但是您应该通过将fgets()的返回值与NULL比较来检查输入操作是否成功。
  • 当遍历数组以计算空间时,应在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;
}

另一种简单的方法来处理字计数走路,一个指针下你在你是否是一个国家循环保持跟踪串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键,然后输出从第三个单词开始输入的每个句子,或者显示错误"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!

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

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字符

暂无
暂无

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

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