东华oj-进阶题第66题-字符串统计

本文讲述了作者在解决一个字符串统计问题时遇到的挑战,包括需要统计四种不同关系的字母。通过举例展示了问题的具体需求,以及在实现和调试过程中遇到的困难,最终成功解决问题并反思编程风格。

在这里插入图片描述

66 字符串统计

作者: SunCiHai时间限制: 10S章节: 字符串

问题描述 :

明明最近在做一个有关字符串的统计工作。两个由小写字母组成的字符串s1和s2,明明需要统计出以下四种关系:

(1)在s1或s2中存在的字母(包括在s1和s2中都存在的字母);

(2)在s1中且在s2中的字母;

(3)在s1中但不在s2中的字母,在s2中但不在s1中的字母;

(4)不在s1中且也不在s2中的字母;

例如两个字符串s1为“lkjsvoahs”,s2为“qglhskjdfg”:

(1)在s1或者在s2或者s1、s2中都存在的字母:adfghjkloqsv;

(2)在s1中且在s2中的字母:hjkls;

(3)在s1中但不在s2中的字母,在s2中但不在s1中的字母:adfgoqv;

(4)不在s1中且也不在s2中的字母:bceimnprtuwxyz;

明明统计了很久,但是由于统计过程十分繁琐,且很容易出错,导致明明的进度非常慢,很有可能因为统计不完而错过了晚上的约会。因此明明想请你帮个忙,帮他写一个程序,用程序来统计出以上几项内容。

明明的问题可以归结为:

输入两串由小写字母组成的字符串s1和s2,比较其中的字母,输出以下四项,输出的字母以字典顺序排列:

(1)在s1或s2中存在的字母(包括在s1和s2中都存在的字母);

(2)在s1中且在s2中的字母;

(3)在s1中但不在s2中的字母,在s2中但不在s1中的字母;

(4)不在s1中且也不在s2中的字母;

例如字符串s1为sadf,s2为asdf,则需输出以下四行(注意输出的格式):

in s1 or s2:adfs

in s1 and s2:adfs

in s1 but not in s2 ,or in s2 but not in s1:

not in s1 and s2:bceghijklmnopqrtuvwxyz

输入说明 :

你写的程序要求从标准输入设备中读入测试数据作为你所写程序的输入数据。标准输入设备中有多组测试数据,每组测试数据两行,每组测试数据的第一行为字符串s1,每组测试数据的第二行为字符串s2;s1和s2都由小写英文字母组成,且长度不超过26个字符。测试数据与其后一组测试数据之间没有任何空行,第一组测试数据前面以及最后一组测试数据后面也都没有任何空行。
输出说明 :

对于每一组测试数据,你写的程序要求计算出一组相应的运算结果,并将这一组运算结果作为你所写程序的输出数据依次写入到标准输出设备中。

每组运算结果由四行组成:

第一行为在s1或者在s2或者s1、s2中都存在的字母;

第二行为在s1中且在s2中的字母;

第三行为在s1中但不在s2中的字母,在s2中但不在s1中的字母;

第四行为不在s1中且也不在s2中的字母;

具体格式请参考样例输出。

每组运算结果其行首和行尾都没有任何空格,每组运算结果与其后一组运算结果之间有一个空行,最后一组运算结果后面没有空行。

注:通常,显示屏为标准输出设备。 输入范例 : sadf asdf lkjsvoahs qglhskjdfg 输出范例 : in
s1 or s2:adfs in s1 and s2:adfs in s1 but not in s2 ,or in s2 but not
in s1: not in s1 and s2:bceghijklmnopqrtuvwxyz

in s1 or s2:adfghjkloqsv in s1 and s2:hjkls in s1 but not in s2 ,or in
s2 but not in s1:adfgoqv not in s1 and s2:bceimnprtuwxyz

原来的代码:

/*
	T66 字符串统计 
	第一种情况:即两字符串的并集。将两字符串连接起来后排序,再去重 
	第二种情况:即两字符串的交集。将两字符串分别去重,排序,再取前一段相同字符 
	第三种情况:str1去掉二者交集与str2去掉二者交集的并集
				也就是在第一种情况中去掉第二种情况 
	第四种情况:即在全部26个字母中抠掉第一种情况。
*/ 

#include<stdio.h>
#include<string.h>
#define MAX_SIZE 27

void sortByAlphabet(char str[]);
void removeDupl(char str[]); 

int main() {
	char str1[MAX_SIZE] = "";
	char str2[MAX_SIZE] = "";
	char res[MAX_SIZE] = "";// 每种情况的结果 
	char resTemp[MAX_SIZE] = "";
	char temp1[MAX_SIZE] = "";
	char temp2[MAX_SIZE] = "";
	int count = 0;
	int i = 0, j = 0, k = 0;
	int len1 = 0, len2 = 0, len = 0;
	int flag = 0;
	char characters[26] = "";
	
	while (scanf("%s", str1) != EOF) {
		scanf("%s", str2);// 注意输出还要加点东西 
		
		for (i = 0; i < 26; i++) {
			characters[i] = 'a' + i;
		}
		characters[26] = '\0';
		
		len1 = strlen(str1);
		len2 = strlen(str2);
		strcpy(temp1, str1);
		strcpy(temp2, str2);
		
		// 第一种 
		strcpy(res, strcat(str1, str2));// 连接
		sortByAlphabet(res);// 排序
		removeDupl(res);// 去重
		printf("in s1 or s2:%s\n", res);
		for (i = 0; i < strlen(res); i++)
			resTemp[i] = res[i];
		resTemp[i] = '\0';
		printf("resTemp=%s\n", resTemp);
		
		strcpy(resTemp, res);// 将res存下来 ******************************************	// 这里怎么会有问题???? 
		
		// 第二种 
		flag = 0;
		for (i = 0; i < len1; i++) {
			for (j = 0; j < len2; j++) {
				if (temp1[i] == temp2[j]) {// 有相同字符 
					flag = 1;
					break;
				}
			}
		}
		if (flag) {
			removeDupl(temp1);
			removeDupl(temp2);
			sortByAlphabet(temp1);
			sortByAlphabet(temp2);
			i = len1 <= len2 ? len1 : len2;
			temp1[i] = '\0'; 
			printf("in s1 and s2:%s\n", temp1);
		} 
		else {
			temp1[0] = '\0';
			printf("in s1 and s2:\n");
		} 
		
		// 第三种 
		if (strlen(temp1) == 0) {// 两字符串没有交集,则就是第一种情况 
			printf("in s1 but not in s2 ,or in s2 but not in s1:%s\n", resTemp);
		}
		else {
			len = strlen(resTemp);
			for (i = 0; i < strlen(resTemp); i++) {
				for (j = 0; j < strlen(temp1); j++) {
					if (resTemp[i] == temp1[j]) {// 将相同元素删除 
						for (k = i; k < len - 1; k++) {
							resTemp[k] = resTemp[k + 1];
						}
						resTemp[len - 1] = '\0';
						len--;
					}
				}
			}
			printf("in s1 but not in s2 ,or in s2 but not in s1:%s\n", resTemp);
		}
		
		// 第四种
		len = strlen(characters);
		for (i = 0; i < len; i++) {
			for (j = 0; j < strlen(res); j++) {
				if (characters[i] == res[j]) {// 将相同元素删除 
					for (k = i; k < len - 1; k++) {
						characters[k] = characters[k + 1];
					}
					characters[len - 1] = '\0';
				//	printf("%s\n", characters);
					len--;
				}
			}
		}
		printf("not in s1 and s2:%s\n", characters); // 怎么到最后还有个adfs????? 
		
	}
	
	return 0;
} 

// 按字典顺序对字符串进行排序 
void sortByAlphabet(char str[]) {
	int i = 0, j = 0;
	char ch = 'a';
	int len = strlen(str);
	
	for (i = len - 1; i > 0; i--) {
		for (j = 0; j < i; j++) {
			if (str[j] - 'a' > str[j + 1] - 'a') {
				ch = str[j];
				str[j] = str[j + 1];
				str[j + 1] = ch;
			}
		}
	}
} 

// 字符串去重
void removeDupl(char str[]) {
	char res[MAX_SIZE] = "";
	int i = 0, j = 0;
	int len =  strlen(str);
	
	for (i = 0; i < len - 1; i++) {
		if (str[i] != str[i + 1]) {
			res[j++] = str[i];
		}
	}
	if (res[j - 1] != str[len - 1]) {// 检查后面是否有相同字符 
		res[j] = str[len - 1];
		j++; 
	}
	res[j] = '\0';
		
	strcpy(str, res);
} 

唉,我也不晓得它是什么鬼,看起来明明没问题,最后总要加个尾巴……
参考了大佬的代码,把原来的四个模块换成了四个函数,经过修改后的代码:

/*
	T66 字符串统计 
	第一种情况:即两字符串的并集。将两字符串连接起来后排序,再去重 
	第二种情况:即两字符串的交集。将两字符串分别去重,排序,再取前一段相同字符 
	第三种情况:str1去掉二者交集与str2去掉二者交集的并集
				也就是在第一种情况中去掉第二种情况 
	第四种情况:即在全部26个字母中抠掉第一种情况。
*/ 

#include<stdio.h>
#include<string.h>
#define MAX_SIZE 27

void sortByAlphabet(char str[]);
void removeDupl(char str[]); 
void case1(char str1[], char str2[]);
void case2(char str1[], char str2[]);
void case3(char str1[], char str2[]);
void case4(char str1[], char str2[]);

int main() {
	char str1[MAX_SIZE] = "";
	char str2[MAX_SIZE] = "";
//	char str1[MAX_SIZE] = "sadf";
//	char str2[MAX_SIZE] = "asdf";
//	char str1[MAX_SIZE] = "lkjsvoahs";
//	char str2[MAX_SIZE] = "qglhskjdfg";
	char temp1[MAX_SIZE] = "";
	char temp2[MAX_SIZE] = "";
	int count = 0;
	
	
	while (scanf("%s", str1) != EOF) {
		scanf("%s", str2);
		if (++count != 1) {
			printf("\n");
		}
		
		strcpy(temp1, str1);
		strcpy(temp2, str2);
		case1(temp1, temp2); 
		strcpy(temp1, str1);
		strcpy(temp2, str2);
		case2(temp1, temp2);
		strcpy(temp1, str1);
		strcpy(temp2, str2); 
		case3(temp1, temp2); 
		strcpy(temp1, str1);
		strcpy(temp2, str2);
		case4(temp1, temp2); 
	}
	
	return 0;
} 

// 按字典顺序对字符串进行排序 
void sortByAlphabet(char str[]) {
	int i = 0, j = 0;
	char ch = 'a';
	int len = strlen(str);
	
	for (i = len - 1; i > 0; i--) {
		for (j = 0; j < i; j++) {
			if (str[j] - 'a' > str[j + 1] - 'a') {
				ch = str[j];
				str[j] = str[j + 1];
				str[j + 1] = ch;
			}
		}
	}
} 

// 字符串去重
void removeDupl(char str[]) {
	char res[MAX_SIZE] = "";
	int i = 0, j = 0;
	int len =  strlen(str);
	
	for (i = 0; i < len - 1; i++) {
		if (str[i] != str[i + 1]) {
			res[j++] = str[i];
		}
	}
	if (res[j - 1] != str[len - 1]) {// 检查后面是否有相同字符 
		res[j] = str[len - 1];
		j++; 
	}
	res[j] = '\0';
		
	strcpy(str, res);
} 

// 第一种情况		没问题 
void case1(char str1[], char str2[]) {
	char res[MAX_SIZE] = "";
	
	strcpy(res, strcat(str1, str2));// 连接
	sortByAlphabet(res);// 排序
	removeDupl(res);// 去重
	printf("in s1 or s2:%s\n", res);
}

// 第二种情况		没问题了 
void case2(char str1[], char str2[]) {
	int len1 = strlen(str1);
	int len2 = strlen(str2);
	char res[MAX_SIZE] = "";
	int count = 0;// 公共字符计数 
	int i = 0, j = 0;
	
	removeDupl(str1);// 去重 
	
	for (i = 0; i < len1; i++) {
		for (j = 0; j < len2; j++) {
			if (str1[i] == str2[j]) {// 相同字符 
				res[count++] = str1[i];
			}
		}
	}
	res[count] = '\0'; 
	sortByAlphabet(res);// 排序 
	removeDupl(res);// 去重 
	
	printf("in s1 and s2:%s\n", res);
}

// 第三种情况		没问题了 
void case3(char str1[], char str2[]) { 
	char res1[MAX_SIZE] = "";
	char res2[MAX_SIZE] = "";
	int len = 0;
	int i = 0, j = 0, k = 0;
	int len1 = strlen(str1);
	int len2 = strlen(str2);
	int count = 0;// 公共字符计数 
	
	// 重复第一种情况 
	strcpy(res1, strcat(str1, str2));// 连接
	sortByAlphabet(res1);// 排序
	removeDupl(res1);// 去重
	
	// 重复第二种情况
	removeDupl(str1);// 去重 
	for (i = 0; i < len1; i++) {
		for (j = 0; j < len2; j++) {
			if (str1[i] == str2[j]) {// 相同字符 
				res2[count++] = str1[i];
			}
		}
	}
	res2[count] = '\0'; 
	sortByAlphabet(res2);// 排序 
	removeDupl(res2);// 去重 
	 
	 
	if (strlen(res2) == 0) {// 两字符串没有交集,则就是第一种情况 
		printf("in s1 but not in s2 ,or in s2 but not in s1:%s\n", res1);
	}
	else {// 在第一种情况里面抠掉第二种情况 
		len = strlen(res1);
		for (i = 0; i < strlen(res1); i++) {
			for (j = 0; j < strlen(res2); j++) {
				if (res1[i] == res2[j]) {// 将相同元素删除 
					for (k = i; k < len - 1; k++) {
						res1[k] = res1[k + 1];
					}
					res1[len - 1] = '\0';
					len--;
				}
			}
		}
		printf("in s1 but not in s2 ,or in s2 but not in s1:%s\n", res1);
	}
}

// 第四种情况		没问题 
void case4(char str1[], char str2[]) {
	char characters[26] = "abcdefghijklmnopqrstvuwxyz";
	char res[MAX_SIZE] = "";
	int i = 0, j = 0, k = 0;
	int len = 0;
	
	strcpy(res, strcat(str1, str2));// 连接
	sortByAlphabet(res);// 排序
	removeDupl(res);// 去重
	
	len = strlen(characters);
	for (i = 0; i < len; i++) {
		for (j = 0; j < strlen(res); j++) {
			if (characters[i] == res[j]) {// 将相同元素删除 
				for (k = i; k < len - 1; k++) {
					characters[k] = characters[k + 1];
				}
				characters[len - 1] = '\0';
			//	printf("%s\n", characters);
				len--;
			}
		}
	}
	printf("not in s1 and s2:%s\n", characters);
} 

运行之后没问题了,可是到了oj出现这种情况:
在这里插入图片描述
在这里插入图片描述
我无语了,不晓得是oj错了还是我错了……先放着吧,明天再查下

DIY分割线++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++DIY分割线

今天我打算把四个函数里面的所有内容重写一遍,不用之前杂糅的方法,每种情况的结果独立,不参与其他情况的求解
改了一通,调了一通,总算AC了……

/*
	T66 字符串统计 
	第一种情况:即两字符串的并集。将两字符串连接起来后排序,再去重 
	第二种情况:即两字符串的交集。将两字符串分别去重,排序,再取前一段相同字符 
	第三种情况:str1去掉二者交集与str2去掉二者交集的并集
				也就是在第一种情况中去掉第二种情况 
	第四种情况:即在全部26个字母中抠掉第一种情况。
*/ 

#include<stdio.h>
#include<string.h>
#define MAX_SIZE 27

void sortByAlphabet(char str[]);
void removeDupl(char str[]); 
void case1(char str1[], char str2[]);
void case2(char str1[], char str2[]);
void case3(char str1[], char str2[]);
void case4(char str1[], char str2[]);

int main() {
	char str1[MAX_SIZE] = "";
	char str2[MAX_SIZE] = "";
//	char str1[MAX_SIZE] = "qwekljdfvoj";
//	char str2[MAX_SIZE] = "eriiigjigowjegojw";
//	char str1[MAX_SIZE] = "lkjsvoahs";
//	char str2[MAX_SIZE] = "qglhskjdfg";
	char temp1[MAX_SIZE] = "";
	char temp2[MAX_SIZE] = "";
	int count = 0;
	
	
	while (scanf("%s", str1) != EOF) {
		scanf("%s", str2);
		if (++count != 1) {
			printf("\n");
		}
		
		strcpy(temp1, str1);
		strcpy(temp2, str2);
		case1(temp1, temp2); 
		strcpy(temp1, str1);
		strcpy(temp2, str2);
		case2(temp1, temp2);
		strcpy(temp1, str1);
		strcpy(temp2, str2); 
		case3(temp1, temp2); 
		strcpy(temp1, str1);
		strcpy(temp2, str2);
		case4(temp1, temp2); 
	}
	
	return 0;
} 

// 按字典顺序对字符串进行排序 
void sortByAlphabet(char str[]) {
	int i = 0, j = 0;
	char ch = 'a';
	int len = strlen(str);
	
	for (i = len - 1; i > 0; i--) {
		for (j = 0; j < i; j++) {
			if (str[j] - 'a' > str[j + 1] - 'a') {
				ch = str[j];
				str[j] = str[j + 1];
				str[j + 1] = ch;
			}
		}
	}
} 

// 字符串去重(建立在字符串有序的基础上) 
void removeDupl(char str[]) {
	char res[MAX_SIZE] = "";
	int i = 0, j = 0;
	int len =  strlen(str);
	
	for (i = 0; i < len - 1; i++) {
		if (str[i] != str[i + 1]) {
			res[j++] = str[i];
		}
	}
	if (res[j - 1] != str[len - 1]) {// 检查后面是否有相同字符 
		res[j] = str[len - 1];
		j++; 
	}
	res[j] = '\0';
		
	strcpy(str, res);
} 

// 第一种情况	
void case1(char str1[], char str2[]) {
	char res[MAX_SIZE] = "";
	int i = 0, j = 0;
	int len = 0;
	int flag = 0; 
	
	sortByAlphabet(str1);// 排序 
	sortByAlphabet(str2);
	removeDupl(str1);// 去重 
	removeDupl(str2);
	strcpy(res, str1);
	len = strlen(res);
	for (i = 0; i < strlen(str2); i++) {
		flag = 0;
		for (j = 0; j < strlen(str1); j++) {
			if (str2[i] == str1[j]) 
				flag = 1;
		}
		if (!flag) {
			res[len++] = str2[i];
		}
	}
	res[len] = '\0';
	sortByAlphabet(res);
	
	printf("in s1 or s2:%s\n", res);
}

// 第二种情况		
void case2(char str1[], char str2[]) {
	char res[MAX_SIZE] = "";
	int i = 0, j = 0;
	int count = 0;
	int flag = 0;
	
	for (i = 0; i < strlen(str1); i++) {
		for (j = 0; j < strlen(str2); j++) {
			if (str1[i] == str2[j]) {
				flag = 1;
				res[count++] = str1[i];
			}
		}
	}
	if (!flag) {// 没有相同元素 
		printf("in s1 and s2:\n");
		return ; 
	}
	res[count] = '\0';
	
	sortByAlphabet(res);// 先排序
	removeDupl(res);// 再去重 
	
	printf("in s1 and s2:%s\n", res);
}

// 第三种情况	
void case3(char str1[], char str2[]) { 
	char res[MAX_SIZE] = "";
	int i = 0, j = 0;
	int count = 0;
	int flag = 0;
	
	for (i = 0; i < strlen(str1); i++) {// 在s1中但是不在s2中 
		flag = 0;
		for (j = 0; j < strlen(str2); j++) {
			if (str1[i] == str2[j]) {
				flag = 1;
			}
		}
		if (!flag) {
			res[count++] = str1[i];
		}
	} 
	
	for (i = 0; i < strlen(str2); i++) {// 在s2中但是不在s1中 
		flag = 0;
		for (j = 0; j < strlen(str1); j++) {
			if (str2[i] == str1[j]) {
				flag = 1;
			}
		}
		if (!flag) {
			res[count++] = str2[i];
		}
	}
	if (count == 0) {// 没有满足条件的元素 
		printf("in s1 but not in s2 ,or in s2 but not in s1:\n");
		return ;	
	}
	res[count] = '\0'; 
	
	sortByAlphabet(res);// 先排序
	removeDupl(res);// 再去重 
	
	printf("in s1 but not in s2 ,or in s2 but not in s1:%s\n", res);	
}

// 第四种情况	
void case4(char str1[], char str2[]) {
	char characters[MAX_SIZE] = "abcdefghijklmnopqrstvuwxyz";
	char res[MAX_SIZE] = "";
	int count = 0;
	int i = 0, j = 0;
	int flag = 0;
	
	for (i = 0; i < strlen(characters); i++) {
		flag = 0;
		for (j = 0; j < strlen(str1); j++) {// 检查当前字符是否在s1中 
			if (characters[i] == str1[j])
				flag = 1; 
		}
		if (flag == 1)
			continue;
		for (j = 0; j < strlen(str2); j++) {// 检查当前字符是否在s2中 
			if (characters[i] == str2[j])
				flag = 1; 
		}
		if (!flag) {
			res[count++] = characters[i];
		}
	}
	res[count] = '\0';
	sortByAlphabet(res);// 先排序
	removeDupl(res);// 再去重 
	
	printf("not in s1 and s2:%s\n", res);
} 

在这里插入图片描述
我太菜了……以后不搞那么多花里胡哨的了。

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值