目录
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");
}
}