C语言化学计算器(二)

上次已经写过C语言元素计算器,这次增加了一些功能(当然任很不完善,后续继续改进),并觉得改名叫化学计算器比较好。写这个纯属兴趣和热爱,并希望在化学领域找到一些志同道合的人。由于博主依然处于期末考试,因此代码并没有过多的介绍。有问题欢迎在评论区交流。


#define _CRT_SECURE_NO_WARNINGS   //这行代码确保vs可以使用scanf    

#include<stdio.h>
#include<string.h>
#include<ctype.h>
#include<time.h>
#include<Windows.h>
#include<math.h>
//声明元素结构体
typedef struct Element {
    
    
	char symbol[4];          //元素符号
	char name[4];            //元素名称
	float aram;              //精确相对原子质量
	float ram;               //相对原子质量
	float electronegativity; //电负性    
}Element;
Element element[57];
//存储元素的有关信息
char s[][4] = {
    
     "","H","He","Li","Be","B","C","N","O","F","Ne","Na","Mg","Al","Si","P","S",\
"Cl","Ar","K","Ca","Sc","Ti","V","Cr","Mn","Fe","Co","Ni","Cu","Zn","Ga","Ge","As","Se","Br","Kr",\
"Rb","Sr","Y","Zr","Nb","Mo","Tc","Ru","Rh","Pd","Ag","Cd","In","Sn","Sb","Te","I","Xe","Cs","Ba"};
char n[][4] = {
    
     "","氢","氦","锂","铍","硼","碳","氮","氧","氟","氖","钠","镁","铝","硅","磷",\
"硫","氯","氩","钾","钙","钪","钛" ,"钒","铬","锰","铁","钴","镍","铜","锌","镓","锗","砷","硒","溴","氪",\
"铷","锶","钇","锆","铌","钼","锝","钌","铑","钯","银","镉","铟","锡","锑","碲","碘","氙","铯","钡",};
float am[] = {
    
     0,1.008,4.003,6.941,9.012,10.81,12.01,14.01,16.00,19.00,20.18,22.99,24.31,26.98,28.09,30.97,32.06,\
35.45,39.95,39.10,40.08,44.96,47.87,50.94,52.00,54.94,55.85,58.93,58.69,63.55,65.41,69.72,72.64,74.92,78.96,79.90,83.80,\
85.47,87.62,88.91,91.22,92.91,95.94,97.91,101.1,102.9,106.4,107.9,112.4,114.8,118.7,121.8,127.6,126.9,131.3,132.9,137.3};
float m[] = {
    
     0,1,4,7,9,10.8,12,14,16,19,20,23,24,27,28,31,32,35.5,40,39,40,45,48,51,52,55,56,59,59,64,65,70,73,75,79,80,84,\
85,88,89,91,93,96,98,101,103,106,108,112,115,119,122,128,127,131,133,137};
float e[] = {
    
     0,2.20,3.89,0.98,1.57,2.04,2.55,3.04,3.44,3.98,3.67,0.93,1.31,1.61,1.90,2.19,2.58,3.16,3.3,0.82,1.00,1.36,1.54,\
1.63,1.66,1.55,1.83,1.88,1.91,1.90,1.65,1.81,2.01,2.18,2.55,2.96,3.00,0.82,0.95,1.22,1.33,1.6,2.16,1.9,2.2,2.28,2.20,1.93,\
1.69,1.78,1.96,2.05,2.1,2.66,2.67,0.79,0.89};

//声明函数
int search_num(char sym[]);  //根据元素符号返回原子序数
void print_info(void);       //打印元素信息
void count_mass(void);       //计算分子质量
void luckyelement(void);     //给出你的幸运元素
void elemenet_song(void);    //元素之歌
void search_formula(void);   //根据分子量计算化学式
void Permutation(int* a, int* b, int n, int cur, float molecular_mass, float dm,int y, char molecular_symbols[][4]);     //用于解决排列组合问题
void Use_formular_unsaturation(void);          //根据用户给出的分子式计算不饱和度
int Unsaturation(char a[][4],int b[],int n);   //计算饱和度函数
void sort(void);      //根据某性质对元素排序

int main(void)
{
    
    
	//将元素信息输入结构体变量
	for (int i = 1; i <= 36; i++)
	{
    
    
		strcpy(element[i].symbol, s[i]);
		strcpy(element[i].name, n[i]);
		element[i].aram = am[i];
		element[i].ram = m[i];
		element[i].electronegativity = e[i];
	}
	int w;
	printf("************欢迎你使用ZCX元素计算器*************\n");
	printf("************输入1进入元素查询******************\n");
	printf("************输入2进入分子量计算****************\n");
	printf("************输入3抽取幸运元素******************\n");
	printf("************输入4进入元素之歌******************\n");
	printf("************输入5计算化学式********************\n");
	printf("************输入6计算不饱和度******************\n");
	printf("************输入7对元素排序********************\n");
	printf("************输入0退出程序**********************\n");
	while (1 == scanf("%d", &w)) {
    
    
		switch (w)
		{
    
    
		case 1:
			print_info();
			break;
		case 2:
			count_mass();
			break;
		case 3:
			luckyelement();
			break;
		case 4:
			elemenet_song();
			break;
		case 5:
			search_formula();
			break;
		case 6:
			Use_formular_unsaturation();
			break;
		case 7:
			sort();
			break;
		case 0:
			printf("谢谢使用!\n");
			return 0;
		default:
			printf("输入有误!请重新输入:\n");
			break;
		}
		printf("请继续按主菜单输入:\n");
	}
}

int search_num(char sym[])
{
    
    

	for (int i = 1; i <= 36; i++)
		if (!strcmp(element[i].symbol, sym))
			return i;
	return 0;
}

void print_info(void)
{
    
    
	int k = 1, num = 0;
	char sym[4];
	while (k) {
    
    
		int j = 1;
		printf("请输入你要查询的元素的英文符号\n");
		scanf("%s", sym);
		num = search_num(sym);
		if (num)printf("你输入的元素已找到!\n");
		else {
    
    
			printf("你输入的元素不存在!\n请再次输入!\n");
			continue;
		}
		printf("请输入你要查询的信息:\n");
		printf("************1,原子序数***************\n");
		printf("************2.元素名称***************\n");
		printf("************3.精确相对原子质量*******\n");
		printf("************4.相对原子质量***********\n");
		printf("************5.电负性*****************\n");
		printf("************6.退出该元素查询*********\n");
		printf("************0.退出查询系统***********\n");
		while (j) {
    
    
			if (1 == scanf("%d", &k) && k >= 0 && k <= 6) {
    
    
				switch (k)
				{
    
    
				case 1:
					printf("原子序数:%d\n",num);
					break;
				case 2:
					printf("元素名称:%s\n", element[num].name);
					break;
				case 3:
					printf("精确相对原子质量:%g\n", element[num].aram);
					break;
				case 4:
					printf("相对原子质量:%g\n", element[num].ram);
					break;
				case 5:
					printf("电负性为:%g\n",element[num].electronegativity);
					break;
				case 6:
					j = 0;
					break;
				default:
					printf("谢谢使用!请您慢走!\n");
					goto help;
					break;
				}
			}
			else
			{
    
    
				printf("输入错误!请重新输入!\n");
			}
		}
	help:
		printf("已成功退出!\n");
	}
}

void count_mass(void)
{
    
    
	int k = 1;
	while (k) {
    
    
		int n = 0, q = 0;       //q表示括号的状态
		float m = 0, m1 = 0;    //m是分子量,m1是括号内分子量和
		char molecular[20], molecular_symbol[4], ch, th, * p = molecular;
		printf("请正确输入分子式(暂不支持某种原子个数超过10):\n");
		scanf("%s", molecular);
		while (ch = *p++) {
    
    
			th = *p;
			if (ch == '(') {
    
    
				q = 1;
				continue;
			}
			if (ch == ')') {
    
    
				q = 2;
				continue;
			}
			if (q == 2) {
    
    
				m += m1 * (ch - '0');
				m1 = 0;
				q = 0;
				continue;
			}
			molecular_symbol[0] = ch;
			molecular_symbol[1] = th;
			molecular_symbol[2] = '\0';
			n = search_num(molecular_symbol);
			if (n)
			{
    
    
				th = *(p + 1);
				if (!q) {
    
    
					if (isdigit(th)) {
    
    
						m += element[n].ram * (th - '0') + m1;
						m1 = 0;
						p += 2;
					}
					else {
    
    
						m += element[n].ram + m1;
						m1 = 0;
						p++;
					}
				}
				else {
    
    
					if (isdigit(th)) {
    
    
						m1 += element[n].ram * (th - '0');
						p += 2;
					}
					else {
    
    
						m1 += element[n].ram;
						p++;
					}
				}
			}
			else
			{
    
    
				molecular_symbol[1] = '\0';
				n = search_num(molecular_symbol);
				if (n)
				{
    
    
					if (!q) {
    
    
						if (isdigit(th)) {
    
    
							m += element[n].ram * (th - '0') + m1;
							m1 = 0;
							p++;
						}
						else {
    
    
							m += element[n].ram + m1;
							m1 = 0;
						}
					}
					else {
    
    
						if (isdigit(th)) {
    
    
							m1 += element[n].ram * (th - '0');
							p++;
						}
						else
							m1 += element[n].ram;
					}
				}
				else {
    
    
					printf("输入有误!请重新输入:\n");
					goto help;
				}
			}

		}
		printf("%s的相对分子质量为: %g\n", molecular, m);
		help:
		printf("您想计算下一个分子吗?输入1表示是,0表示否");
		scanf("%d", &k);
	}
}

void luckyelement(void)
{
    
    
	srand((unsigned)time(NULL));
	int x = rand() % 36 + 1;
	printf("今天你的幸运元素是:\n");
	Sleep(3000);
	printf("%s\n",element[x].symbol);
	printf("它的原子序数为:%d\n",x);
	printf("它的中文名是:%s\n",element[x].name);
	printf("它的精确相对分子质量是:%g\n",element[x].aram);
	printf("它的相对分子质量是:%g\n",element[x].ram);
	printf("它的故事可多呢,快去了解它吧!\n");
	printf("\n");
}

void elemenet_song(void)
{
    
    
	printf("元素之歌:\n");
	printf("我是氢,我最轻,火箭靠我运卫星;我是氦,我无赖,得失电子我最菜;\
我是锂,密度低,遇水遇酸把泡起;我是铍,耍赖皮,虽是金属难电离;\n");
	printf("我是硼,有点红,论起电子我很穷;我是碳,反应慢,既能成链又成环;\
我是氮,我阻燃,加氢可以合成氨;我是氧,不用想,离开我就憋得慌;\n");
	printf("我是氟,最恶毒,抢个电子就满足;我是氖,也不赖,通电红光放出来;\
我是钠,脾气大,遇酸遇水就火大;我是镁,最爱美,摄影烟花放光辉;\n");
	printf("我是铝,常温里,浓硫酸里把澡洗;我是硅,色黑灰,信息元件把我堆;\
我是磷,害人精,剧毒列表有我名;我是硫,来历久,沉淀金属最拿手;\n");
	printf("我是氯,色黄绿,金属电子我抢去;我是氩,活性差,霓虹紫光我来发;\
我是钾,把火加,超氧化物来当家;我是钙,身体爱,骨头牙齿我都在;\n");
	printf("我是钛,过渡来,航天飞机我来盖;我是铬,正六铬,酒精过来变绿色;\
我是锰,价态多,七氧化物爆炸猛;我是铁,用途广,不锈钢喊我叫爷;\n");
	printf("我是铜,色紫红,投入硝酸气棕红;我是砷,颜色深,三价元素夺你魂;\
我是溴,挥发臭,液态非金我来秀;我是铷,碱金属,沾水烟花钾不如;\n");
	printf("我是碘,升华烟,遇到淀粉蓝点点;我是铯,金黄色,入水爆炸容器破;\
我是钨,高温度,其他金属早呜呼;我是金,很稳定,扔进王水影无形;\n");
	printf("我是汞,有剧毒,液态金属我为独;我是铀,浓缩后,造原子弹我最牛;\
我是镓,易融化,沸点很高难蒸发;我是铟,软如金,轻微放射宜小心;\n");
	printf("我是铊,能脱发,投毒出名看清华;我是锗,可晶格,红外窗口能当壳;\
我是硒,补人体,口服液里有玄机;我是铅,能储电,子弹头里也出现。\n");
}

void search_formula(void)
{
    
    
	int k = 1;
	printf("使用说明:\n分子组成元素不得超过8种\n");
	printf("由于本人还是编程小白,为降低难度,请输入要查询的相对分子质量后\n再输入可能的组成元素以帮助程序更好的计算。谢谢!");
	printf("So,let's go!\n");
	while (k) {
    
    
		int a[8] = {
    
     0,0,0,0,0,0,0,0 };    //数组a表示每种原子的个数  
		int b[8] = {
    
     0,0,0,0,0,0,0,0 };    //数组b表示每种原子的序数
		int  molecular_varietie = 0,y=0;
		float molecular_mass = 0,dm = 0;        //k用来计算输入元素的原子序数
		char molecular_symbols[8][4];
		printf("请输入相对分子质量和组成元素的种类数(例如:44 2):\n");
		if (2 == scanf("%f %d", &molecular_mass, &molecular_varietie) && molecular_varietie <= 8 && molecular_varietie > 0)
		{
    
    
			getchar();
			printf("请输入可能的组成元素,空格隔开相邻元素\n");
			for (int i = 0; i < molecular_varietie; i++)
			{
    
    
				scanf("%s",molecular_symbols[i]);
				b[i]=search_num(molecular_symbols[i]);
			}
			getchar();
			printf("请输入分子量的绝对误差:");
			scanf("%f",&dm);
			getchar();
			printf("是否使用不饱和度计算器排除不合理的分子式?输入1表示是,0表示否");
			scanf("%d",&y);
			getchar();
			Permutation(a,b,molecular_varietie,0,molecular_mass,dm,y,molecular_symbols);
		}
		else
		{
    
    
			printf("输入错误!请重新输入!");
			continue;
		}
		printf("感谢您的使用,您还想要继续计算吗?按1是,0否:");
		while (!scanf("%d", &k));
	}

}

void Permutation(int* a,int *b,int n, int cur,float molecular_mass,float dm,int y, char molecular_symbols[][4])
{
    
    
	static int t = 1;
	int i,k=0;   //k统计元素种数
	float m = 0;
	if (cur == n)          //递归边界,已取n个数
	{
    
    
		for (i = 0; i < n; i++)
			m =m+a[i] * element[b[i]].ram;
		if (fabs(molecular_mass - m) <= dm)
		{
    
    
			if (y) {
    
    
				if (Unsaturation(molecular_symbols, a, n)>=0) {
    
    
					printf("%-4d", t++);
					for (int i = 0; i < n; i++)
					{
    
    
						if (a[i] >= 2)
							printf("%s%d", element[b[i]].symbol, a[i]);
						else if (a[i] == 1)
							printf("%s", element[b[i]].symbol);
						else
							continue;
					}
					printf("\n");
				}
			}
			else {
    
    
				printf("%-4d", t++);
				for (int i = 0; i < n; i++)
				{
    
    
					if (a[i] >= 2)
						printf("%s%d", element[b[i]].symbol, a[i]);
					else if (a[i] == 1)
						printf("%s", element[b[i]].symbol);
					else
						continue;
				}
				printf("\n");
			}
		}
	}
	else
	{
    
    
		for (i = 0; i <14; i++)
		{
    
    
			a[cur] = i;
			Permutation(a,b,n,cur+1,molecular_mass,dm,y,molecular_symbols);
		}
	}

}

void Use_formular_unsaturation(void)
{
    
    
	char a[10][4];
	int b[10],k=1,m=0;       //m表示不饱和度
	printf("感谢您使用不饱和度计算工具\n");
	printf("请您输入你要计算的分子式:");
	printf("规则:先仅支持只含C,H,O,N,F,S,Cl的有机化合物的不饱和度计算。\n");
	while (k) {
    
    
		printf("请先输入元素的种数:(属于0表示退出程序)\n");
		scanf("%d", &k);
		getchar();
		if (!k)break;
		printf("再输入分子式,注意:元素和数字之间以空格隔开。\n");
		for (int i = 0; i < k; i++)
		{
    
    
			scanf("%s %d", a[i], &b[i]);
		}
		m = Unsaturation(a,b,k);
		if (m == -1)
			printf("输入错误!\n");
		else if (m == -2)
			printf("您输入的分子式可能不合理,因为不饱和度不是整数\n");
		else
			printf("该分子的不饱和度是%d\n",m);
		printf("欢迎继续使用!\n");
	}
}

int Unsaturation(char a[][4], int b[], int n)
{
    
    
	int s = 2;
	for (int i = 0; i < n; i++)
	{
    
    
		if (strcmp(a[i], "C")&&strcmp(a[i], "N")&&strcmp(a[i], "O")&&strcmp(a[i], "F")&&strcmp(a[i], "S")&&strcmp(a[i], "H")&&strcmp(a[i], "Cl"))
			return -1;
	}
	for (int i = 0; i < n; i++)
	{
    
    
		if (!strcmp(a[i], "C"))
			s += 2 * b[i];
		else if (!(strcmp(a[i], "H")&&strcmp(a[i], "Cl")&&strcmp(a[i], "F")))
			s -= b[i];
		else if (!strcmp(a[i], "N"))
			s += b[i];
		else
			continue;
	}
	if (s % 2)return -2;
	else return s / 2;
}

void sort(void)
{
    
    
	char a[40][4];
	int k = 1,t=1,b[40],temp=0;
	printf("欢迎使用元素排序器(默认升序)\n");
	while (t) {
    
    
		printf("请输入要排序元素的数目(不要太多哦): ");
		scanf("%d", &k); getchar();
		printf("请输入想要排序的元素(相邻元素以空格隔开): ");
		for (int i = 0; i < k; i++)
		{
    
    
			scanf("%s", a[i]);
			b[i] = search_num(a[i]);
		}
		printf("Go on!输入下列数字进行相应排序\n");
		printf("0.退出排序\n");
		printf("1.原子序数\n");
		printf("2.相对原子质量\n");
		printf("3.电负性\n");
		scanf("%d", &t); getchar();
		switch (t)
		{
    
    
		case 0:
			break;
		case 1:
			for (int i = 0; i < k - 1; i++)
				for(int j=0;j<k-i-1;j++)
					if (b[j] > b[j + 1])
					{
    
    
						temp = b[j];
						b[j] = b[j + 1];
						b[j + 1] = temp;
					}
			printf("排序后:\n");
			for (int i = 0; i < k; i++)
				printf("%s  ",element[b[i]].symbol);
			printf("\n");
			break;
		case 2:
			for (int i = 0; i < k - 1; i++)
				for (int j = 0; j < k - i - 1; j++)
					if (element[b[j]].aram > element[b[j+1]].aram)
					{
    
    
						temp = b[j];
						b[j] = b[j + 1];
						b[j + 1] = temp;
					}
			printf("排序后:\n");
			for (int i = 0; i < k; i++)
				printf("%s  ", element[b[i]].symbol);
			printf("\n");
			break;
		case 3:
			for (int i = 0; i < k - 1; i++)
				for (int j = 0; j < k - i - 1; j++)
					if (element[b[j]].electronegativity> element[b[j + 1]].electronegativity)
					{
    
    
						temp = b[j];
						b[j] = b[j + 1];
						b[j + 1] = temp;
					}
			printf("排序后:\n");
			for (int i = 0; i < k; i++)
				printf("%s  ", element[b[i]].symbol);
			printf("\n");
			break;
		default :
			printf("输入有误!请重新输入\n");
			break;
		}
	}
}

猜你喜欢

转载自blog.csdn.net/hexiechuangxin/article/details/112441768
今日推荐