c++基于字符串匹配的垃圾邮件过滤系统

主要内容:

1.设计一个由敏感词所组成的词库,以字符串结构存储。
2.设计一个邮件过滤系统,对邮件内容与词库中的敏感词进行模式匹配,最终返回是否垃圾邮件的标记。
3.编写一个主函数,输入一段文字模拟邮件内容,测试系统功能。

实现方法:

程序主要使用了KMP算法进行字符串模式匹配:

#Knuth-Morris-Pratt 字符串查找算法,简称为 “KMP算法”,常用于在一个文本串S内查找一个模式串P 的出现位置,这个算法由Donald Knuth、Vaughan Pratt、James H. Morris三人于1977年联合发表,故取这3人的姓氏命名此算法。KMP算法的时间复杂度为O(m+n)。

​ # main函数:设置存储关键词的字符数组pattern,多个关键词组成敏感词词库。设置存储邮件的字符数组string,当用户输入关键词和邮件内容后,调用KMP函数,KMP函数会返回pattern在string中的位置,如果没有找到会返回notfound,根据返回值打印是否垃圾邮件。

​ # KMP函数:求string长度为n,pattern长度为m,申请空间分配给match数组,调用BuildMatch函数,然后从头开始向后比较,匹上就继续向后一位,匹配失败则pattern的指针回退,回退的位置和match值有关,然后重新比较。当pattern中字符全部匹配上,表示找到,返回它在string中对应的下标,否则返回notfound。

​ # BuildMatch函数:分析关键词pattern,对pattern的每一个字符得出它对应的match值存放在数组中。

程序:

#include <stdio.h>
#include <string.h> 
#include <stdlib.h>

typedef int Position;
#define NotFound -1

void BuildMatch(char *pattern, int *match)//关键词预分析函数
{	
	//分析pattern,对pattern的每一个字符得出它对应的match值
	Position i, j;
	int m = strlen(pattern); 
	match[0] = -1; //pattern的第一个字符match值为-1

	for (j = 1; j < m; j++) 
	{
		i = match[j - 1];  //用i替代 match[j - 1],方便后面表示
		while ((i >= 0) && (pattern[i + 1] != pattern[j]))
			i = match[i];  //回退再比较
		if (pattern[i + 1] == pattern[j])
			match[j] = i + 1;
		else match[j] = -1; 
	}
}

Position KMP(char *string, char *pattern) //字符串模式匹配函数
{
	int n = strlen(string);   //求字符串string长度
	int m = strlen(pattern);  //求字符串pattern长度
	Position s, p, *match;

	if (n < m) return NotFound;  //n < m 时一定不匹配
	match = (Position *)malloc(sizeof(Position) * m);  //申请m个整型数据的空间,首地址强制转换为int型指针
	BuildMatch(pattern, match); //调用BuildMatch函数分析pattern,对pattern的每一个字符得出它对应的match值
	s = p = 0; //两个标志设为0使两个字符串从头开始匹配(两个字符串数组的下标)
	while (s < n && p < m) 
	{
		if (string[s] == pattern[p]) 
		{
			s++; p++; //如果前面的字符匹配上了则继续向后比较
		}
		else if (p > 0) p = match[p - 1] + 1; //指针P回退,再开始比较(相当于pattern向后挪动)
		else s++; //既p=0的情况既第一个字母就匹配不上,此时指针s向后挪一位再比
	}
	return (p == m) ? (s - m) : NotFound; //pattern中字符全部匹配完表示匹配上,返回string中对应的下标,否则返回NotFound
}

int main()
{
	char pattern1[100]; //存储关键词的字符串数组
	char pattern2[100]; 
	char pattern3[100]; 
	int a = 0;
	printf("请设置3个垃圾邮件过滤关键词:\n");
	printf("(空格分开回车结束)\n");
	scanf_s("%s", pattern1, 100); 
	scanf_s("%s", pattern2, 100);
	scanf_s("%s", pattern3, 100);
	/*
	//vc++6.0支持的输入方式
	scanf("%s", pattern1); 
	scanf("%s", pattern2);
	scanf("%s", pattern3);
	*/
	printf("\n");
	while (a < 60) //设置测试次数
	{
		char string[9000]; //存储邮件的字符串数组
		printf("请输入邮件内容,按回车结束(支持中英文):\n");
		scanf_s("%s", string, 9000);
		Position p1 = KMP(string, pattern1); //调用模式匹配函数,得到pattern在string中的位置
		Position p2 = KMP(string, pattern2); //同上,返回数组下标赋值给p2
		Position p3 = KMP(string, pattern3);
		if (p1 == NotFound && p2 == NotFound&& p3 == NotFound) //当全部关键词都未匹配上为正常邮件否则只要有一个匹配则为垃圾邮件
			 printf("\033[0;32;40m正常邮件! \033[0m\n\n"); //格式符表示打印绿色字体
		else printf("\033[0;31;40m垃圾邮件! \033[0m\n\n"); //格式符表示打印红色字体
		/*
		//输出不带颜色
		if (p1 == NotFound && p2 == NotFound && p3 == NotFound)
			printf("正常邮件!\n\n");
		else printf("垃圾邮件!\n\n");
		*/
		a++;
	}
	return 0;
}

测试效果:

在这里插入图片描述
感觉不错的话请点个赞吧,感谢!

  • 3
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C++中,可以使用string类来进行字符串匹配C++的string类提了一系列成员函数和操作符来进行字符串的比较和匹。 一种常见的字符串匹配方法是使用string类的find函数。find函数可以在一个字符串中查找另一个字符串,并返回第一次出现的位置。例如,可以使用以下代码来查找字符串s中是否包含子串sub: ```cpp #include <iostream> #include <string> int main() { std::string s = "Hello, world!"; std::string sub = "world"; size_t found = s.find(sub); if (found != std::string::npos) { std::cout << "子串在位置 " << found << " 处找到了" << std::endl; } else { std::cout << "子串未找到" << std::endl; } return 0; } ``` 另外,还可以使用string类的compare函数来进行字符串的比较。compare函数可以比较两个字符串的大小关系,并返回一个整数值表示比较结果。如果两个字符串相等,则返回0;如果第一个字符串小于第二个字符串,则返回一个负数;如果第一个字符串大于第二个字符串,则返回一个正数。例如,可以使用以下代码来比较两个字符串s1和s2: ```cpp #include <iostream> #include <string> int main() { std::string s1 = "abc"; std::string s2 = "def"; int result = s1.compare(s2); if (result == 0) { std::cout << "两个字符串相等" << std::endl; } else if (result < 0) { std::cout << "s1 小于 s2" << std::endl; } else { std::cout << "s1 大于 s2" << std::endl; } return 0; } ``` 除了以上介绍的方法,C++还提供了其他一些字符串匹配的函数和算法,如正则表达式匹配、KMP算法等。具体使用哪种方法取决于你的需求和场景。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值