查找并打印带有空格或制表符分隔符的字符串的最后一个单词

时间:2019-02-17 01:21:52

标签: c arrays string pointers gcc

我正在尝试获取字符串的最后一个单词作为C语言中的argv参数。如何找到最后一个单词并分隔包含空格/制表符的字符串?

单词的定义是“由空格/制表符或字符串的开头/结尾定界的字符串部分。” 我最初创建了一个函数来识别它是空白还是制表符;但是,我所拥有的解决方案并不适合所有情况。大部分都能正常工作,但是当我的argv具有类似"asdkBakjsdhf1785 "的字符串时,预期的输出应该是"asdkBakjsdhf1785",而不是"asdkBakjsdhf1785 "。所有这些功能都必须从头开始,只能使用write库中的<unistd.h>函数。

int my_isspace(char c)
{
    if (c == ' ' || c == '\t')
        return (1);
    return (0);
}

void    my_putstr(char *str)
{
    while (*str)
        write(1, str++, 1);
}

void    last_word(char *str)
{
    char *last;
    int i;

    i = 0;
    last = &str[i];
    while (str[i])
    {
        if (my_isspace(str[i]))
        {
            if (str[i + 1] >= '!' && str[i + 1] <= '~')
                last = &str[i + 1];
        }
        i++;
    }
    if (last)
        my_putstr(last);
}

int     main(int argc, char *argv[])
{
    if (argc == 2)
       last_word(argv[1]);
    my_putstr("\n");
    return (0);
}

目前,它的作用是解析字符串并检查是否具有空格/制表符。如果有,它将忽略它并移至下一个字符,直到命中!~之间的一个字符(包括那些字符)为止。一旦找到中间的任何字符,它将把解析存储到另一个空的字符串指针中,以保留“最后一个字”。通过我的使用方式,我可以在哪里改善一点点来最后划定我的空格/制表符?

1 个答案:

答案 0 :(得分:1)

您有几个问题。首先,这将有助于使您的my_isspace()大致等同于isspace(),以便正确地将行尾也视为空白,例如

int my_isspace (const char c)
{
    if (c == ' ' || c == '\t' || c == '\n' || c == '\r')
        return 1;

    return 0;
}

接下来,您可以通过采用状态循环方法并保留一个简单的标志来帮助您进行分类,从而简化last_word()(以及许多其他类似的分类函数)。例如,在这里可以帮助您了解您是否正在阅读单词。这样可以使其处于简单的输入/输出状态,您可以使用int in = 0;的简单标志来跟踪单词以外的单词,使用in = 1;的简单标志来跟踪单词。

在使用中,对于可变字符串,last_word()可以编写如下(main()的参数是可变的):

void last_word (char *str)
{
    char *p = NULL,     /* your last */
        *ep = NULL;     /* end pointer to end of last */
    int in = 0;         /* flag - in/out of a word */

    while (*str) {                  /* loop over each char */
        if (my_isspace (*str)) {    /* if a space */
            if (in)                 /* if in a word */
                ep = str;           /* set endptr to current char */
            in = 0;                 /* set out of word */
        }
        else {                      /* not a space */
            if (!in)                /* if not in a word */
                p = str;            /* set start pointer */
            in = 1;                 /* set in word */
        }
        str++;          /* increment pointer */
    }

    if (p) {            /* if we have start of word */
        if (ep)         /* if we have endptr set */
            *ep = 0;    /* nul-terminate at endptr */
        my_putstr (p);  /* output last */
    }
}

注意:,如果要处理不可更改的字符串输入,则可以使用ep - p来获取要输出的字符数,并一次输出一个)

一个完整的示例(需要进行一些清理)可能是:

#include <unistd.h>

int my_isspace (const char c)
{
    if (c == ' ' || c == '\t' || c == '\n' || c == '\r')
        return 1;

    return 0;
}

void my_putstr (const char *str)
{
    size_t n = 0;

    for (n = 0; str[n]; n++) {}

    write (1, str, n);
}

void last_word (char *str)
{
    char *p = NULL,     /* your last */
        *ep = NULL;     /* end pointer to end of last */
    int in = 0;         /* flag - in/out of a word */

    while (*str) {                  /* loop over each char */
        if (my_isspace (*str)) {    /* if a space */
            if (in)                 /* if in a word */
                ep = str;           /* set endptr to current char */
            in = 0;                 /* set out of word */
        }
        else {                      /* not a space */
            if (!in)                /* if not in a word */
                p = str;            /* set start pointer */
            in = 1;                 /* set in word */
        }
        str++;          /* increment pointer */
    }

    if (p) {            /* if we have start of word */
        if (ep)         /* if we have endptr set */
            *ep = 0;    /* nul-terminate at endptr */
        my_putstr (p);  /* output last */
    }
}

int main (int argc, char **argv) {

    my_putstr ("'");
    if (argc >= 2)
        last_word (argv[1]);
    my_putstr ("'");
    my_putstr ("\n");

    return 0;
}

使用/输出示例

单字:

$ ./bin/write_last_argv1 "fleas"
'fleas'

带有结尾空格的单字:

$ ./bin/write_last_argv1 "fleas      "
'fleas'

多个单词:

$ ./bin/write_last_argv1 "my dog has fleas"
'fleas'

带有前导,尾随和多个中间空格的多个单词:

$ ./bin/write_last_argv1 "  my    dog  has fleas   "
'fleas'

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