c - 查找以数组中的字符开头的单词

标签 c

在字符数组中,我试图挑选出以字符开头或单词中包含该字符的单词。我可以用什么来实现这个目标?谢谢你!

如果我有一个数组,上面写着“农耕乐趣很好”。 我的输出应该是: 农业 乐趣 阿尔夫

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

int main(void) {

char list[50];
int i;




  fgets(list, 50, stdin);     //retrieve the string from the user
  for(i = 0; i < 50; i++){
  if(list[i] == 'z'){
     printf("%c", list[i]);
  }
}

最佳答案

虽然它仍然出现,但您希望根据您的输入和输出查找包含 'F''f' 的单词 - 您发布的代码正在寻找 if (list[i] == 'z') 相当令人困惑......无论你想完成什么,你永远不会解析包含 'F'' 的单词f' 来自输入行检查 'z'

每个人都需要一点帮助,所以让我们从您需要完成的任务开始,假设“农业乐趣 alf 很好。” 并且您想要“农业乐趣 alf” 出来。您需要完成的基本步骤是:

  1. 将用户输入读取到有效存储中;
  2. 将输入拆分为单个单词(称为字符串标记化);和
  3. 检查每个单词中是否有字符为'F''f',如果找到则输出该单词。

读取用户的输入

您应该因为选择 fgets 来获取用户的输入而受到赞扬。这(与 POSIX getline 一起)将是一个不错的选择。无论您选择哪种输入函数,您都需要通过检查返回(至少)来验证输入通过生成手动 EOF(Linux 上的 Ctrl+d 或 Windows 上的 Ctrl+z)来确保用户提供了有效的输入并且没有取消),在您的情况下,您还应该验证用户输入的字符而不是简单地按 Enter。您可以执行类似于以下操作:

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

#define MAXC  1024  /* if you need a constanst, #define one (or more) */

int main (void) {

    char str[MAXC];                     /* storage for string */
    ...
    fputs ("enter string: ", stdout);   /* prompt */
    /* validate user provided input, not ctrl+d(z) or just [Enter] */
    if (!fgets (str, MAXC, stdin) || *str == '\n') {
        fputs ("(user canceled or empty input)\n", stderr);
        return 1;
    }

现在,您已将用户输入(最多 1023 个字符)存储在 str 中,并在末尾附加了 '\n' 字符.

str 标记为单词

虽然有很多方法可以将字符串标记为单词,但一种简单的方法是使用恰当命名的 strtok 函数。请参阅strtok(3) - Linux manual page了解其使用详情。总之,它在第一次调用时将要标记化的字符串作为其输入,并使用一串分隔符将字符串拆分为单词。 (在所有后续调用中,将传递 NULL 来代替原始 str)。

注意: strtok 修改原始 str,因此您无法传递 string-literal 或其他不可变字符串。 (如果需要保留原始文件,请复制 str)

要使用 strtok 进行标记化,您可以这样做:

    const char *delim = " \t\n.?!",     /* delimiters to split str */
               *find = "fF";            /* chars to test for */
    ...
    /* tokenize str into words */
    for (char *p = strtok(str, delim); p; p = strtok (NULL, delim)) {
        /* test for characters here */
    }

上面的 for 循环声明一个字符指针 p 作为循环变量(初始化为 strtok(str, delim) 的返回值,其中将是指向第一个单词的指针。然后循环检查 p (例如 p != NULL)作为循环条件,并使用 p = strtok ( NULL, delim) 在每次迭代中确保 p 指向下一个单词。您可能会认为逻辑更简单一些:

    char *p = strtok(str, delim);
    while (p != NULL) {
        /* test for characters here */
        p = strtok (NULL, delim);
    }

(两者是等效的)

检查单词是否包含要查找的字符

为了检查一个单词是否包含任意数量的字符之一,strpbrk 函数是量身定制的。请参阅strtok(3) - Linux manual pagestrtok 将定位您在分隔符字符串(名为上面声明的 find)中提供的任何一个字符的第一次出现,例如

        if (strpbrk (p, find)) {    /* does word contain fF? */
            ...

就是这样。现在您只需填写逻辑即可输出上面找到的单词。您可以简单地printf("%s", p);。总而言之,你可以这样做:

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

#define MAXC  1024  /* if you need a constanst, #define one (or more) */

int main (void) {

    char str[MAXC];                     /* storage for string */
    const char *delim = " \t\n.?!",     /* delimiters to split str */
               *find = "fF";            /* chars to test for */

    fputs ("enter string: ", stdout);   /* prompt */
    /* validate user provided input, not ctrl+d(z) or just [Enter] */
    if (!fgets (str, MAXC, stdin) || *str == '\n') {
        fputs ("(user canceled or empty input)\n", stderr);
        return 1;
    }

    /* tokenize str into words */
    for (char *p = strtok(str, delim); p; p = strtok (NULL, delim)) {
        if (strpbrk (p, find)) {    /* does word contain fF? */
            printf (" %s", p);      /* output with space */
        }
    }
    putchar ('\n');     /* tidy up with newline */

    return 0;
}

示例使用/输出

$ ./bin/strtokspn
enter string: Farming fun alf is good.
 Farming fun alf

这不是唯一的方法,但可能是解决该问题的更简洁的方法之一。仔细检查一下,如果有疑问请告诉我。

关于c - 查找以数组中的字符开头的单词,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57228404/

相关文章:

c - 输入长度未知

c - 计算 ASCII 文件中换行符的最简单方法是什么?

c - 哪些部分构成可执行文件的大小?

c - C语言中的用户输入过滤,例如避免字母和符号

malloc() 可以用来定义数组的大小吗?

C UDP套接字,在recvfrom检索之前数据包存储在哪里?

c - 如何在 Linux 的 udp 中使用 select api

c - 为什么这个 SDL2 程序变慢了?

python - 在旧的 CE 设备上运行 Python 时遇到问题

c - getchar 缓冲输入、EOF 和终端驱动程序