求助带通配符的字符串匹配问题

Albert_derek 2015-12-17 10:19:55
【问题描述】
请你写个程序判断对于给定字符串A,字符串B是否能与其匹配。A串仅包含字母,B串可以包含字母和字符'?'、'*'。匹配的规则如下:
'?'可以匹配任意一位英文字母(不区分大小写)
'*'用于表示任意多位英文字母(不区分大小写,可以是0位)
例如,字符串“ab*ba*a*”和“a?b*abbbb”都可匹配字符串“abbababbbb”。

【输入格式】
输入共11行。
第1行包含一个字符串A;
第2-11行,每行一个字符串B。

【输出格式】
输出10行,对应每个B串,判断它是否与A串匹配,如果是则输出YES,否则输出NO。请注意,匹配时请忽略大小写!

【样例1 】
输入
GreedIsGood
greedisgood
Greed??Good
Gr*d*Good
GreedIsGood
G?e?d?s?o?d
G*e*d*s*o*d
Greed*Good
GreedIsB*d
Gr?dIsGood
输出
YES
YES
YES
YES
YES
YES
YES
NO
NO
NO
【我的代码】
#include<stdio.h>
#include<string.h>

#define N 10

int main(void)
{
int match(char* s1, char* s2);
int charicmp(char, char); //字符匹配函数

int i;
char Astr[60], Bstr[10][60];
scanf("%s", Astr);
for(i = 0;i < N;i++){
scanf("%s", Bstr[i]);
}

////以文件形式读入
//FILE *fp = NULL;
//fp = fopen("in.txt","r");
//fscanf(fp, "%s", Astr);
//for(i = 0;i < N;i++){
//fscanf(fp, "%s", Bstr[i]);
//}
//fclose(fp);

for(i = 0;i < N;i++){
if(0 == match(Astr, Bstr[i]))
printf("YES\n");
else
printf("NO\n");
}
return 0;
}


int match(char* s1, char* s2)//匹配返回0, s1为指定串,s2为含通配符串
{
int charicmp(char, char);


int i;
char t[60] = {'\0'};
if(strlen(s1) < strlen(s2))
return -1;
else{
while(1){
if('\0' == *s1)
return 0;
if(0 == charicmp(*s1, *s2))
{
s1++;
s2++;
}
else if(*s2 == '*') //跳过*, 比较所求串剩余部分
{
while(*s2 == '*') //多个连续的'*' 一起跳过
s2++;
if(*s2 == '\0') //s2 ends with '*',由于此前匹配成功,故s2和s1是匹配的
return 0;
else{
while(*s1 != '\0') //依次从指定串待比较串的
{
while(0 != charicmp(*s1, *s2))
s1++;
for(i = 0;i < strlen(t);i++) //每次赋值前将临时串t置零
t[i] = '\0';
strcpy(t, s1);
//printf("s2 = %s, t = %s\n", s2, t);
if(match(t, s2) == 0)
return 0;
else
s1++;
}
}

}
else
return -1;
}
}
return 0;
}


int charicmp(char c1, char c2)
{
if('?' == c1 || '?' == c2)
return 0;
if('A' <= c1 && c1 <= 'Z')
c1 += 32;
if('A' <= c2 && c2 <= 'Z')
c2 += 32;
if('a' <= c1 && c1 <= 'z' && 'a' <= c2 && c2 <= 'z' && c1 == c2)
return 0;
return -1;
}


【问题】
输入给的范例输出的结果是正确的,但在网上系统测试时有一半的结果是错误的,麻烦大神帮忙看一下代码存在的问题,谢谢!
...全文
277 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
赵4老师 2015-12-23
  • 打赏
  • 举报
回复
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

//摘自《代码之美》
//match2(regexp,text)
// 字符     含义
// .        匹配任意的单个字符
// ^        匹配输入字符串的开头
// $        匹配输入字符串的结尾
// *        匹配前一个字符的零个或者多个出现
int matchhere(char *regexp, char *text);
int matchstar(int c, char *regexp, char *text) {// matchstar: search for c*regexp at beginning of text
   do {// a * matches zero or more instances
       if (matchhere(regexp, text)) return 1;
   } while (*text != '\0' && (*text++ == c || c == '.'));
   return 0;
}
int matchhere(char *regexp, char *text) {// matchhere: search for regexp at beginning of text
   if (regexp[0] == '\0') return 1;
   if (regexp[1] == '*') return matchstar(regexp[0], regexp+2, text);
   if (regexp[0] == '$' && regexp[1] == '\0') return *text == '\0';
   if (*text!='\0' && (regexp[0]=='.' || regexp[0]==*text)) return matchhere(regexp+1, text+1);
   return 0;
}
int match2(char *regexp, char *text) {// match: search for regexp anywhere in text
    if (regexp[0] == '^') return matchhere(regexp+1, text);
    do {// must look even if string is empty
        if (matchhere(regexp, text)) return 1;
    } while (*text++ != '\0');
    return 0;
}

//match1(regexp,text)
// 字符     含义
// ?        匹配任意的单个字符
// *        匹配零个或者多个字符
int match_imp(const char *d,int dcur,const char *s,int scur) {
    if(!d[dcur]) return (!s[scur])?1:0;
    if (d[dcur]=='?') return match_imp(d,dcur+1,s,scur+1);
    else if(d[dcur]=='*') {
        do {
            if (match_imp(d,dcur+1,s,scur)) return 1;
        } while (s[scur++]);
        return 0;
    } else return (tolower(d[dcur])==tolower(s[scur]) && match_imp(d,dcur+1,s,scur+1))?1:0;
}
int match1(char* s1, char* s2) {
    return match_imp(s1,0,s2,0);
}

int main() {
    printf("%d==match1(abc ,abc)\n",match1("abc" ,"abc"));
    printf("%d==match1(a?c ,abc)\n",match1("a?c" ,"abc"));
    printf("%d==match1(a*c ,abc)\n",match1("a*c" ,"abc"));
    printf("-------------------\n");
    printf("%d==match1(abc ,abd)\n",match1("abc" ,"abd"));
    printf("%d==match1(a?c ,abd)\n",match1("a?c" ,"abd"));
    printf("%d==match1(a*c ,abd)\n",match1("a*c" ,"abd"));
    printf("\n");
    printf("%d==match2(abc ,abc)\n",match2("abc" ,"abc"));
    printf("%d==match2(^a  ,abc)\n",match2("^a"  ,"abc"));
    printf("%d==match2(c$  ,abc)\n",match2("c$"  ,"abc"));
    printf("%d==match2(a.c ,abc)\n",match2("a.c" ,"abc"));
    printf("%d==match2(a.*c,abc)\n",match2("a.*c","abc"));
    printf("-------------------\n");
    printf("%d==match2(ABC ,abc)\n",match2("ABC" ,"abc"));
    printf("%d==match2(^B  ,abc)\n",match2("^B"  ,"abc"));
    printf("%d==match2(A$  ,abc)\n",match2("A$"  ,"abc"));
    printf("%d==match2(a..c,abc)\n",match2("a..c","abc"));
    printf("%d==match2(a.*d,abc)\n",match2("a.*d","abc"));
    return 0;
}
//1==match1(abc ,abc)
//1==match1(a?c ,abc)
//1==match1(a*c ,abc)
//-------------------
//0==match1(abc ,abd)
//0==match1(a?c ,abd)
//0==match1(a*c ,abd)
//
//1==match2(abc ,abc)
//1==match2(^a  ,abc)
//1==match2(c$  ,abc)
//1==match2(a.c ,abc)
//1==match2(a.*c,abc)
//-------------------
//0==match2(ABC ,abc)
//0==match2(^B  ,abc)
//0==match2(A$  ,abc)
//0==match2(a..c,abc)
//0==match2(a.*d,abc)
//
fly_dragon_fly 2015-12-22
  • 打赏
  • 举报
回复
应该是简单的递归
bool match_imp(const char *s,int scur,const char *d,int dcur)
{
    if(!d[dcur]) return !s[scur];
    if(d[dcur]=='?') return match_imp(s,scur+1,d,dcur+1);
    else if(d[dcur]=='*')
    {
        do{
            if(match_imp(s,scur,d,dcur+1)) return true;
        }while(s[scur++]);
        return false;
    }else return tolower(s[scur])==tolower(d[dcur])&&match_imp(s,scur+1,d,dcur+1);
}
int match(char* s1, char* s2)
{
    return match_imp(s1,0,s2,0);
}
布拉格曼 2015-12-22
  • 打赏
  • 举报
回复
MARK一个。。。。。
赵4老师 2015-12-21
  • 打赏
  • 举报
回复
2楼是说这个代码不支持多个* ? 你试运行过了?
lm_whales 2015-12-19
  • 打赏
  • 举报
回复
引用 1 楼 zhao4zhong1 的回复:
仅供参考:
//摘自《代码之美》
// 字符     含义
// .        匹配任意的单个字符
// ^        匹配输入字符串的开头
// $        匹配输入字符串的结尾
// *        匹配前一个字符的零个或者多个出现
#include <stdio.h>
int matchhere(char *regexp, char *text);

int matchstar(int c, char *regexp, char *text) {// matchstar: search for c*regexp at beginning of text
   do {// a * matches zero or more instances
       if (matchhere(regexp, text)) return 1;
   } while (*text != '\0' && (*text++ == c || c == '.'));
   return 0;
}
int matchhere(char *regexp, char *text) {// matchhere: search for regexp at beginning of text
   if (regexp[0] == '\0') return 1;
   if (regexp[1] == '*') return matchstar(regexp[0], regexp+2, text);
   if (regexp[0] == '$' && regexp[1] == '\0') return *text == '\0';
   if (*text!='\0' && (regexp[0]=='.' || regexp[0]==*text)) return matchhere(regexp+1, text+1);
   return 0;
}

int match(char *regexp, char *text) {// match: search for regexp anywhere in text
    if (regexp[0] == '^') return matchhere(regexp+1, text);
    do {// must look even if string is empty
        if (matchhere(regexp, text)) return 1;
    } while (*text++ != '\0');
    return 0;
}
void main() {
    printf("%d==match(abc ,abc)\n",match("abc" ,"abc"));
    printf("%d==match(^a  ,abc)\n",match("^a"  ,"abc"));
    printf("%d==match(c$  ,abc)\n",match("c$"  ,"abc"));
    printf("%d==match(a.c ,abc)\n",match("a.c" ,"abc"));
    printf("%d==match(a.*c,abc)\n",match("a.*c","abc"));
    printf("-------------------\n");
    printf("%d==match(ABC ,abc)\n",match("ABC" ,"abc"));
    printf("%d==match(^B  ,abc)\n",match("^B"  ,"abc"));
    printf("%d==match(A$  ,abc)\n",match("A$"  ,"abc"));
    printf("%d==match(a..c,abc)\n",match("a..c","abc"));
    printf("%d==match(a.*d,abc)\n",match("a.*d","abc"));
}
//1==match(abc ,abc)
//1==match(^a  ,abc)
//1==match(c$  ,abc)
//1==match(a.c ,abc)
//1==match(a.*c,abc)
//-------------------
//0==match(ABC ,abc)
//0==match(^B  ,abc)
//0==match(A$  ,abc)
//0==match(a..c,abc)
//0==match(a.*d,abc)
这个例子相当漂亮,不过 多个通配符(主要是多个*号),必须另外处理,因为中间的字符串是可伸缩的 最好的办法是两头向中间匹配 单个字符的通配符,以及固定个数个字符,都比较简单,因为只有相等才算匹配, 如果,采用近似匹配(模糊匹配?),那就更麻烦了,就必须知道如何近似才行。
赵4老师 2015-12-18
  • 打赏
  • 举报
回复
仅供参考:
//摘自《代码之美》
// 字符     含义
// .        匹配任意的单个字符
// ^        匹配输入字符串的开头
// $        匹配输入字符串的结尾
// *        匹配前一个字符的零个或者多个出现
#include <stdio.h>
int matchhere(char *regexp, char *text);

int matchstar(int c, char *regexp, char *text) {// matchstar: search for c*regexp at beginning of text
   do {// a * matches zero or more instances
       if (matchhere(regexp, text)) return 1;
   } while (*text != '\0' && (*text++ == c || c == '.'));
   return 0;
}
int matchhere(char *regexp, char *text) {// matchhere: search for regexp at beginning of text
   if (regexp[0] == '\0') return 1;
   if (regexp[1] == '*') return matchstar(regexp[0], regexp+2, text);
   if (regexp[0] == '$' && regexp[1] == '\0') return *text == '\0';
   if (*text!='\0' && (regexp[0]=='.' || regexp[0]==*text)) return matchhere(regexp+1, text+1);
   return 0;
}

int match(char *regexp, char *text) {// match: search for regexp anywhere in text
    if (regexp[0] == '^') return matchhere(regexp+1, text);
    do {// must look even if string is empty
        if (matchhere(regexp, text)) return 1;
    } while (*text++ != '\0');
    return 0;
}
void main() {
    printf("%d==match(abc ,abc)\n",match("abc" ,"abc"));
    printf("%d==match(^a  ,abc)\n",match("^a"  ,"abc"));
    printf("%d==match(c$  ,abc)\n",match("c$"  ,"abc"));
    printf("%d==match(a.c ,abc)\n",match("a.c" ,"abc"));
    printf("%d==match(a.*c,abc)\n",match("a.*c","abc"));
    printf("-------------------\n");
    printf("%d==match(ABC ,abc)\n",match("ABC" ,"abc"));
    printf("%d==match(^B  ,abc)\n",match("^B"  ,"abc"));
    printf("%d==match(A$  ,abc)\n",match("A$"  ,"abc"));
    printf("%d==match(a..c,abc)\n",match("a..c","abc"));
    printf("%d==match(a.*d,abc)\n",match("a.*d","abc"));
}
//1==match(abc ,abc)
//1==match(^a  ,abc)
//1==match(c$  ,abc)
//1==match(a.c ,abc)
//1==match(a.*c,abc)
//-------------------
//0==match(ABC ,abc)
//0==match(^B  ,abc)
//0==match(A$  ,abc)
//0==match(a..c,abc)
//0==match(a.*d,abc)
本课程详细讲解了以下内容:    1.jsp环境搭建及入门、虚拟路径和虚拟主机、JSP执行流程    2.使用Eclipse快速开发JSP、编码问题、JSP页面元素以及request对象、使用request对象实现注册示例    3.请求方式的编码问题、response、请求转发和重定向、cookie、session执行机制、session共享问题     4.session与cookie问题及application、cookie补充说明及四种范围对象作用域     5.JDBC原理及使用Statement访问数据库、使用JDBC切换数据库以及PreparedStatement的使用、Statement与PreparedStatement的区别     6.JDBC调用存储过程和存储函数、JDBC处理大文本CLOB及二进制BLOB类型数据     7.JSP访问数据库、JavaBean(封装数据和封装业务逻辑)     8.MVC模式与Servlet执行流程、Servlet25与Servlet30的使用、ServletAPI详解与源码分析     9.MVC案例、三层架构详解、乱码问题以及三层代码流程解析、完善Service和Dao、完善View、优化用户体验、优化三层(加入接口和DBUtil)    1 0.Web调试及bug修复、分页SQL(Oracle、MySQL、SQLSERVER)     11.分页业务逻辑层和数据访问层Service、Dao、分页表示层Jsp、Servlet     12.文件上传及注意问题、控制文件上传类型和大小、下载、各浏览器下载乱码问题     13.EL表达式语法、点操作符和中括号操作符、EL运算、隐式对象、JSTL基础及set、out、remove     14.过滤器、过滤器通配符、过滤器链、监听器     15.session绑定解绑、钝化活化     16.以及Ajax的各种应用     17. Idea环境下的Java Web开发

69,382

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧