C 将字符串与通配符进行比较
在C语言中,如何将包含C 将字符串与通配符进行比较,c,arrays,string,C,Arrays,String,在C语言中,如何将包含*(可以是任意字符组合)的字符串与二维字符串矩阵进行精确比较 例如,我有一个单词go*s。它可以生成单词“华丽”(*是“orgeou”)、“善良”、“山羊”、“goes”等。我应该从整本字典中阅读这些单词,并将它们与包含一个或多个星号的单词进行比较(*)。必须打印由带星号的单词生成的每个单词。如果两个单词的长度相同,则比较容易,因为*只能是一个字母 int fq(char *s1, char *s2){ int i, a=0, b=0, s=0; while (1){
*
(可以是任意字符组合)的字符串与二维字符串矩阵进行精确比较
例如,我有一个单词go*s
。它可以生成单词“华丽”(*
是“orgeou”)、“善良”、“山羊”、“goes”等。我应该从整本字典中阅读这些单词,并将它们与包含一个或多个星号的单词进行比较(*
)。必须打印由带星号的单词生成的每个单词。如果两个单词的长度相同,则比较容易,因为*
只能是一个字母
int fq(char *s1, char *s2){
int i, a=0, b=0, s=0;
while (1){
if (s1[a]=='\0')
break;
a++;
}
if (strlen(s1)==strlen(s2)){
for(i=0; i<a; i++){
if (s1[i]=='*'){
b++;
}
if (s1[i]==s2[i]){
b++;
}
}
}
if (b==a)
return 1;
intfq(字符*s1,字符*s2){
int i,a=0,b=0,s=0;
而(1){
如果(s1[a]='\0')
打破
a++;
}
if(strlen(s1)=strlen(s2)){
对于(i=0;i,以下内容将使用包含单个*
的输入字符串
开始在输入字的开头一次比较一个字符
如果遇到*
,请向后比较最后一个字符中的两个字符串
如果不匹配,则返回0
如果您遇到*
问题,您就完成了
如果不匹配,则返回0
(补充:此算法也适用于第一个或最后一个位置的*
。您可以检查前两个字符是否为“go”,最后一个字符是否为“s”
最简单的方法是使用一个简单的条件:
if (strncmp(str, "go", 2) == 0 && str[strlen(str) - 1] == 's')
strlen(str) >= 2
如果字符串匹配,则strncmp返回0
您还应确保字符串长度至少为2个字符,否则在比较字符串的2个字符时会出现分段错误,您可以在上述条件中添加:
if (strncmp(str, "go", 2) == 0 && str[strlen(str) - 1] == 's')
strlen(str) >= 2
通过逐个字符检查模式字符串并应用以下规则,您可以非常轻松地编写递归函数,将sting与另一个包含通配符的字符串进行比较:
- 如果模式[p]='\0':如果候选模式[c]='\0',则模式匹配
- 如果模式[p]='*':尝试将候选[c]…候选[c+n]与模式[p+1]匹配
- 如果模式[p]!=“?”和模式[p]!=候选者[c]:不匹配
- 否则,将模式[p+1]与候选[c+1]匹配
这几条规则可以轻松地编写为用于匹配的递归函数:
#include <stdbool.h>
bool match(const char *pattern, const char *candidate, int p, int c) {
if (pattern[p] == '\0') {
return candidate[c] == '\0';
} else if (pattern[p] == '*') {
for (; candidate[c] != '\0'; c++) {
if (match(pattern, candidate, p+1, c))
return true;
}
return match(pattern, candidate, p+1, c);
} else if (pattern[p] != '?' && pattern[p] != candidate[c]) {
return false;
} else {
return match(pattern, candidate, p+1, c+1);
}
}
这不是一种有效的方法,但我认为它很容易理解和实现。如果您需要更有效的方法,可以从以下方面入手:不久前有过同样的问题,并提出了这个问题。只传递一次主字符串就可以提高效率,而不必使用递归函数。如果您偶然发现了这个线程,hopef很高兴你发现这很有帮助
#include <stdio.h>
_Bool wildcard_strcmp(char *line, char *pattern)
{
_Bool wildcard = 0;
char *placeholder;
do
{
if ((*pattern == *line) || (*pattern == '?'))
{
line++;
pattern++;
}
else if (*pattern == '*')
{
if (*(++pattern) == '\0')
{
return 1;
}
wildcard = 1;
}
else if (wildcard)
{
if (pattern == placeholder)
{
line++;
}
else
{
pattern = placeholder;
}
}
else
{
return 0;
}
} while (*line);
if (*pattern == '\0')
{
return 1;
}
else
{
return 0;
}
}
int main()
{
char string[200] = "foobarfoobar";
char pattern[200] = "fo?*barfoo*";
if (wildcard_strcmp(string, pattern))
{
printf("Match\n");
}
else
{
printf("No Match\n");
}
return 0;
}
#包括
_布尔通配符\u strcmp(字符*行,字符*模式)
{
_布尔通配符=0;
字符*占位符;
做
{
如果((*pattern==*line)| |(*pattern=='?'))
{
line++;
模式++;
}
如果(*模式=='*'),则为else
{
如果(*(++模式)='\0')
{
返回1;
}
通配符=1;
}
else if(通配符)
{
if(模式==占位符)
{
line++;
}
其他的
{
模式=占位符;
}
}
其他的
{
返回0;
}
}而(*行);
如果(*模式=='\0')
{
返回1;
}
其他的
{
返回0;
}
}
int main()
{
字符字符串[200]=“foobarfoobar”;
字符模式[200]=“fo?*barfoo*”;
if(通配符\u strcmp(字符串、模式))
{
printf(“匹配\n”);
}
其他的
{
printf(“不匹配\n”);
}
返回0;
}
您确实应该查看正则表达式库,例如regcomp(3)
。man是您的朋友。glob是您的朋友。%man 3glob@CharlieBurns你是说。glob(3)
仅适用于文件名。哈。这很奇怪。我本可以发誓我使用glob来匹配字符串。但那是几年前的事了。也许我自己的库中有一个特殊版本。根据OP,该模式可能包含一个或多个星号。该算法是否适用于多个星号模式?@user4815162342:这是一个公平的问题。调用此函数会再次出现rsively可能有效,但这只是一个猜测。在这种情况下,只需向前检查(尽管对于单个星号,从末尾开始要快得多).我曾想过这样做,但当时我的脑海中似乎不太清楚。但现在我想这几乎是最好的方法。但当一个单词包含多个星号时会发生什么?(非常小的音符)<代码> Boo< <代码> >代码>真< /代码>和代码> false 是C++。请确保<代码>包含< <代码>。C。谢谢。我还有一个问题。如果一个单词中包含任意数量的(?),那么这个词是否也可以工作?问号可以是英文字母表中的任何字符。例如,“?”可以生成单词“poeters”,因此函数应该返回1。不是直接返回,但是您可以很容易地修改最后一个else if语句,如下所示:(pattern[p]!='?'&&pattern[p]!=candidate[c])。@imreal似乎您翻转了“pattern”和“candidate”最后两种情况的参数。当前,您询问*cdxcd
是否与模式zcdxcdxcd
匹配,而不是相反。@imreal近似为O(n^m),其中“n”是字符串中的字符数,“m”是模式中的星星数。如果你关心效率,你可能想要更高效的东西,这是为了简单而写的,不是为了速度。