目录
P57_习题3-1_得分_UVa1585
P57_习题3-2_分子量_UVa1586
原子数范围0~99
书上给的代码
P57_习题3-3_数数字_UVa1225
P57_习题3-4_周期串_UVa455
P59_习题3-9_子序列_UVa10340
P57_习题3-1_得分_UVa1585
给出一个由O和X组成的串(长度为1~80),统计得分。每个O的得分为目前连续出现
 的O的个数,X的得分为0。例如,OOXXOXXOOO的得分为1+2+0+0+1+0+0+1+2+3。
#include<stdio.h>
#define maxn 85
#include<string.h>
char s[maxn];
int value = 0,score = 0;
int main(){
	scanf("%s",s);
	int len = strlen(s);
	for(int m =0 ; m<len;m++){
		if (s[m] == 'O') score+=1;
		else score = 0;
		value += score;
	}
	printf("%d",value);
	return 0;
} 
P57_习题3-2_分子量_UVa1586
给出一种物质的分子式(不带括号),求分子量。本题中的分子式只包含4种原子,分
   别为C, H, O, N,原子量分别为12.01, 1.008, 16.00, 14.01(单位:g/mol)。例如,C6H5OH的
   分子量为94.108g/mol。
   【分析】
   依次扫描即可,注意原子后面不带数目的情况。扫描过程中,维护一个当前已经输入的数字字符
   组成的数字cnt。一开始以及遇到一个新原子时,cnt = -1,表示“还未开始计数”的状态。方便遇
   到原子后不带数目以及数字后有多位的情况处理。
  
原子数范围0~99
#include<stdio.h>
#include<ctype.h>
#include<string.h>
#define maxn 20
char s[maxn];
int atomNumber_C = 0,atomNumber_H = 0,atomNumber_O = 0,atomNumber_N = 0;
//只考虑了0~99个原子
int atomNumber(char *s,int i){
	int atomNumber_temp = 0;
	int len = strlen(s);
	if(len-2 >= 0 && i <= len-2 && isdigit(s[i+1])){
		atomNumber_temp = s[i+1] - '0';
		if(len-3 >= 0 && isdigit(s[i+2])){
			atomNumber_temp = atomNumber_temp*10 + s[i+2] - '0'; 
		}
	} else {
		atomNumber_temp = 1;
	}
	return atomNumber_temp;
}
int main(){
	scanf("%s",s);
	int len = strlen(s);
	for(int i = 0;i < len;i++){
		switch (s[i]) {
		case 'C':
			atomNumber_C += atomNumber(s,i);
			//printf("C %d\n",atomNumber_C);
			break;
		case 'H':
			atomNumber_H += atomNumber(s,i);
			//printf("H %d\n",atomNumber_H);
			break;
		case 'O':
			atomNumber_O += atomNumber(s,i);
			//printf("O %d\n",atomNumber_O);
			break;
		case 'N':
			atomNumber_N += atomNumber(s,i);
			//printf("N %d\n",atomNumber_N);
			break;
		}
	}
	printf("%.3fg/mol\n",atomNumber_C*12.01 + atomNumber_H*1.008 + atomNumber_O*16.00 + atomNumber_N*14.01);
	return 0;
} 
最开始没有尝试输出每一个原子数量的时候,并没有发现问题

但是输出之后发现是:如果有相同的原子,那么重复调用函数的话,会覆盖式的更改原子数

其实是这里的问题
![]()
只需改成
![]()
最开始的时候我也想过用四个数组接收原子数目,然后为每一个原子创建一个数组的计数变量,在main函数中还要记录每一个原子是否出现过
书上给的代码
【分析】
   依次扫描即可,注意原子后面不带数目的情况。扫描过程中,维护一个当前已经输入的数字字符
   组成的数字cnt。一开始以及遇到一个新原子时,cnt = -1,表示“还未开始计数”的状态。方便遇
   到原子后不带数目以及数字后有多位的情况处理。
#include<stdio.h>
#include<ctype.h>
#include<string.h>
#include<assert.h>//如果它的条件返回错误,则终止程序执行
#define _for(i,a,b) for(int i = (a);i < (b);++i)
#define _rep(i,a,b) for(int i = (a);i <= (b);++i)
int main(){
	int T,cnt,sz;
	double W[256],ans;
	char buf[256],c,s;
	W['C'] = 12.01,W['H'] = 1.008,W['O'] = 16.0,W['H'] = 14.01;
	scanf("%d",&T);
	while(T--){
		scanf("%s",buf);
		ans = 0;
		s = 0;
		cnt = -1;
		sz = strlen(buf);
		_for(i,0,sz){
			char c = buf[i];
			if(isupper(c)){
				if(i){
					if(cnt == -1) cnt = 1;
					ans += W[s] * cnt;
				}
				s = c;
				cnt = -1;
			} else {
				assert(isdigit(c));
				if(cnt == -1) cnt = 0;
				cnt = cnt*10 + c - '0';
			}
		}
		if(cnt == -1) cnt = 1;
		ans += W[s] * cnt;
		printf("%.3f\n",ans);
	}
	return 0;
} 
 
P57_习题3-3_数数字_UVa1225
把前n(n≤10000)个整数顺次写在一起:123456789101112…数一数0~9各出现多少次(输出10个整数,分别是0,1,…,9出现的次数)。
#include<stdio.h>
#include<ctype.h>
#include<string.h>
#define _for(i,a,b) for(int i = (a);i < (b);++i)
#define _rep(i,a,b) for(int i = (a);i <= (b);++i)
int result[11] = {0};
int main(){
	int n = 11;
	_rep(i,0,n){
		if(i == 10000){
			++result[1];
			result[0] += 4;
		}
		else if(i >= 0 && i <= 9){
			++result[i];
		}
		else if(i > 9 && i <= 99){
			++result[i/10];
			++result[i%10];
		}
		else if(i > 99 && i <= 999){
			++result[i/100];
			++result[i%100/10];
			++result[i%100];
		}
		else if(i > 999 && i <= 9999){
			++result[i/1000];
			++result[i%1000/100];
			++result[i%1000%100/10];
			++result[i%1000];
		}
	}
	_for(i,0,10){
		printf("%d: %d\n",i,result[i]);
	}
	return 0;
} 
将for循环宏定义,用时比较法便
利用result[]数组,记录相应数字出现的次数
P57_习题3-4_周期串_UVa455
如果一个字符串可以由某个长度为k的字符串重复多次得到,则称该串以k为周期。
   例如,abcabcabcabc以3为周期(注意,它也以6和12为周期)。
   输入一个长度不超过80的字符串,输出其最小周期。
   
   【分析】
   字符串的周期p只可能是闭区间[1,k]内被k整除的数,然后从小到大遍历所有的p,
   判断对于每个i = 0~k-1是否符合line[i] = line[i%C]
#include<stdio.h>
#include<ctype.h>
#include<string.h>
#define _for(i,a,b) for(int i = (a);i < (b);++i)
#define _rep(i,a,b) for(int i = (a);i <= (b);++i)
int main(){
	int N;
	scanf("%d",&N);
	char line[256];
	bool first = true;
	while(N--){
		if(first) first = false;
		else puts("");
		scanf("%s",line);
		int sz = strlen(line);
		_rep(p,1,sz){
			if(sz % p) continue;//sz必然是最小周期的整数倍
			bool ans = true;
			_for(i,0,p){
				for(int j = i+p;j < sz;j += p){
					if(line[j] != line[i]) {
						ans = false;
						break;
					}
				}
			}
			if(ans) {
				printf("%d\n",p);
				break;
			}
		}
	}
	return 0;
} 
 
P59_习题3-9_子序列_UVa10340
输入两个字符串s和t,判断是否可以从t中删除0个或多个字符(其他字符顺序不变),得到字符串s。例如,abcde可以得到bce,但无法得到dc。
#include<stdio.h>
#include<string.h>
const int LEN = 100024;
char s[LEN],t[LEN];
int main(){
	while(scanf("%s%s",s,t) == 2){
		int sLen = strlen(s),tLen = strlen(t);
		bool ok = true;
		for(int i = 0,j = 0;i < sLen;i++,j++){
			while(j < tLen && t[j] != s[i]) j++;
			if(j == tLen){
				ok = false;
				break;
			}
		}
		printf("%s\n",ok ? "Yes" : "No");
	}
} 
 
 
 
 
 
                
















