穿越C字符串:获取字符串的最后一个单词

5

如何得到一个字符串中从 '\0' 换行字符开始到最右边的空格之间的最后一个单词?例如,我可能会有像这样的东西,其中 str 可以被赋予一个字符串:

char str[80];
str = "my cat is yellow";

我该怎么变成黄色?

5个回答

11

像这样:

char *p = strrchr(str, ' ');
if (p && *(p + 1))
    printf("%s\n", p + 1);

那个 + 1 可以在初始化中完成:char *p = strrchr(str, ' ') + 1; - LihO
2
@LihO:然后你只能检查返回值是否为1(表示未找到)。这不是一个胜利。 - John Zwinck
@LihO 谢谢 :-) 我添加了一些检查以确保空格不是最后一个字符。 - cnicutar
好的,如果空格是最后一个字符,那么不会发生什么坏事-+1指针将指向'\0'字符。 - Wookie88
@Wookie88 是的,但也许楼主想避免打印空行 :-? 无论如何,这个检查是可选的。 - cnicutar

1
如果你不想使用'strrchr'函数,这里提供了解决方案。
i = 0;
char *last_word;

while (str[i] != '\0')
{
    if (str[i] <= 32 && str[i + 1] > 32)
        last_word = &str[i + 1];
    i++;
}
i = 0;
while (last_word && last_word[i] > 32)
{
    write(1, &last_word[i], 1);
    i++;
}

0
我会使用函数strrchr()

-2
(沉重叹息) 原始代码在标准/K&R/ANSI C中是错误的!它没有初始化字符串(名为str的字符数组)!如果示例编译,我会感到惊讶。你的程序段真正需要的是:
if strcpy(str, "my cat is yellow")
    {
    /* everything went well, or at least one or more characters were copied. */
    }

或者,如果你承诺不尝试操作字符串,你可以在源代码中使用指向硬编码的“my cat is yellow”字符串的char指针。

如前所述,“单词”由空格字符或NULL字符界定,因此声明一个字符指针并从NULL之前的字符向后移动会更快。显然,首先必须确保有一个非空字符串....

#define NO_SPACE 20
#define ZERO_LENGTH -1

int iLen;
char *cPtr;

if (iLen=strlen(str) ) /* get the number of characters in the sting */
    { /* there is at least one character in the string */
    cPtr = (char *)(str + iLen); /* point to the NULL ending the string */
    cPtr--; /* back up one character */
    while (cPtr != str)
        { /* make sure there IS a space in the string
             and that we don't walk too far back! */
        if (' ' == *cPtr)
            { /* found a space */
/* Notice that we put the constant on the left?
   That's insurance; the compiler would complain if we'd typed = instead of == 
 */
            break;
            }
        cPtr--; /* walk back toward the beginning of the string */
        }
    if (cPtr != str)
        { /* found a space */
        /* display the word and exit with the success code */
        printf("The word is '%s'.\n", cPtr + 1);
        exit (0);
        }
    else
        { /* oops.  no space found in the string */
        /* complain and exit with an error code */
        fprintf(STDERR, "No space found.\n");
        exit (NO_SPACE);
        }
    }
else
    { /* zero-length string.  complain and exit with an error code. */
    fprintf(STDERR, "Empty string.\n");
    exit (ZERO_LENGTH);
    }

现在你可以争论任何非字母字符都应该标记一个单词边界,比如“Dogs-chase-cats”或“my cat:yellow”。在这种情况下,很容易说

if (!isalpha(*cPtr) )

在循环中寻找不仅仅是空格....


注释是为了帮助初学C语言的人以及在生产环境中维护代码的程序员而包含的。请记住,注释的长度与可执行文件的大小没有任何关系。 - Ernest_CT
如果您认为代码无法编译,可以随意解释出错的原因。抨击没有任何好处。 - Ernest_CT
对于任何正在学习编程的人来说,你的代码片段会教他们养成不好的习惯(例如使用printf在stdout上打印错误信息;使用任意的退出码;选择变量名不当;糟糕的while循环使用;减量的位置不正确(实际上是逻辑上的语义错误)。此外,它实际上没有捆绑在任何函数中,因此代码无法编译。对于生产环境:C程序员理解C;逐行解释代码是浪费时间的;简要描述函数即可;如果有一些黑科技的东西,大多数QA都会拒绝,除非绝对必要。 - Ahmed Masud
我并不是在抨击你,你正在尝试帮助我,这非常感激。我只是指出你的错误,以便你也可以纠正它们。 - Ahmed Masud
例如,如果我想要完全正确,我会使用#define定义特定的错误代码,并将其fprintf到STDERR。你需要例子吗? - Ernest_CT
显示剩余4条评论

-2
最好的方法是利用现有的解决方案。其中一个解决方案(针对更一般的问题)是Perl Compatible Regular Expressions,这是一个用于C的开源正则表达式库。因此,您可以使用正则表达式\b(\w+)$(在C中表示为"\b(\w+)$")匹配字符串"my cat is yellow"并保留第一个捕获组,即"yellow"。

一条规则:如果你能不使用正则表达式,就不要使用它们))) - mikithskegg
1
不需要为这么简单的东西使用正则表达式(我认为这是作业)。 - Ahmed Masud

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接