一个问题是设计功能的接口;你得到的界面太简单了,特别是如果你在找到第一个字符串后需要拾取它。所以,我提出了一个更复杂的界面:
int find_word_following(char *haystack, const char *needle, char **bgn, char **end);
干草堆是要扫描的字符串。针是被发现的词。参数bgn
和end
是指针(输出),函数将设置为针的后面的单词的开始,单词的结尾加1。返回值是0(没有找到单词)或1(找到一个单词)。如果返回时发现*bgn == *end
,并且找到一个单词,那么之后就没有另一个单词。我选择不在干草堆上指定const char *
,因为bgn
和end
将指向haystack中的位置,并且常量正确性变得杂乱;尽管如此,代码不会修改干草堆。
#include <assert.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
int find_word_following(char *haystack, const char *needle, char **bgn, char **end);
int main(void)
{
char *haystack = "ten hats 10 are cool";
char *needle = "hats";
char *bgn;
char *end;
while (find_word_following(haystack, needle, &bgn, &end))
{
printf("Found <<%*.*s>>\n", (int)(end - bgn), (int)(end - bgn), bgn);
needle = "are"; // Change search term
haystack = end; // Start where previous scan left off
}
return(0);
}
有这么大的规范,功能不可怕难写:
int find_word_following(char *haystack, const char *needle, char **bgn, char **end)
{
assert(haystack != 0 && needle != 0 && bgn != 0 && end != 0);
char *word = strstr(haystack, needle);
if (word == 0)
return(0);
word += strlen(needle);
// Skip to end of word (in case we found 'hatstand')
while (*word != '\0' && !isspace(*word))
word++;
while (isspace(*word)) // Skip spaces after word
word++;
*bgn = word; // Start of following word
while (*word != '\0' && !isspace(*word))
word++;
*end = word;
return(1);
}
你也许可以通过strspn()
和strcspn()
适当调用替换这些循环。
的程序的输出是:
Found <<10>>
Found <<cool>>
,看起来对于精确词语的变体是:
#include <assert.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
int find_word_following(char *haystack, const char *needle, char **bgn, char **end);
int find_word_following(char *haystack, const char *needle, char **bgn, char **end)
{
assert(haystack != 0 && needle != 0 && bgn != 0 && end != 0);
size_t length = strlen(needle);
char *word;
while ((word = strstr(haystack, needle)) != 0)
{
if ((word == haystack || (word > haystack && isspace(*(word - 1)))) &&
isspace(word[length]))
{
word += length;
while (isspace(*word)) // Skip spaces after word
word++;
*bgn = word; // Start of following word
while (*word != '\0' && !isspace(*word))
word++;
*end = word;
return(1);
}
haystack = word + length;
}
return(0);
}
int main(void)
{
char *haystack = "ten hatstands with hats on are OK";
char *needle = "hats";
char *bgn;
char *end;
while (find_word_following(haystack, needle, &bgn, &end))
{
printf("Found <<%*.*s>>\n", (int)(end - bgn), (int)(end - bgn), bgn);
needle = "are"; // Change search term
haystack = end; // Start where previous scan left off
}
return(0);
}
输出(注意不同的输入字符串)是:
Found <<on>>
Found <<OK>>
由于该函数只返回0,它可能我是'空'。您可以通过传递要找到的字符串(针)以及要搜索的字符串(干草堆)来概括该函数。如果命令长度为几百个字符并且匹配接近开始,则应该担心缓冲区溢出。您应该能够打印字符串而不需要复制子字符串('printf(“%*。* s \ n \ n”,nbytes,nbytes,str);''nbytes'的类型必须是'int'。目前还不清楚你在哪里跳过空格(例如,如果'帽子'和'10'之间有几个空格) –
'帽子'需要匹配一个单词还是可以匹配部分一个字? –
@JonathanLeffler这只是一个测试函数,当我创建真正的函数时,我会小心溢出,是的,它必须匹配整个单词,它也应该跳过所有的空格,直到下一个“单词找到“例如:如果我通过”十顶帽子10928很酷“输出仍应寻找”帽子“,并返回”10928“编辑:由于某种原因,空白不显示在我会通过什么引号...只是想象一下在“帽子”和“10928”之间有8-10个空格 –