目录
问题描述
知识点: 基础算法 简单模拟 上传者:CM01
问题描述:
小明是一个热爱字母的小学生,他喜欢研究字母的奇妙之处。最近,他发现了一种有趣的现象,并称之为“字母派对"。在这个字母派对中,字母按照特殊的规则进行着有趣的互动。规则是这样的:字符串中奇数位置(字符串的第1位、第3位、第5位.…)的字母都是“派对小伙伴",它们必须是小写英文字母;而偶数位置(字符串的第2位、第4位、第6位.….)的字母则是“派对大咖",它们必须是大写英文字母。 现在小明想要开一个真正热闹的字母派对,他需要你帮忙编写一个程序,判断给定的字符电是否适合成为字母派对的参与者。对于给定的多组测试数据,你需要分别判断每个字符串是否适合成为字母派对的参与者,并输出相应的结果。
输入格式:
从文件 party.in 中读入数据。
第一行包含一个正整数 T,表示测试数据的组数。
接下来的 T 行,每行包含一个字符串 S (长度|S|≤100,字符串只包含大小写英文字母),表示一个待判断的字符串。
输出格式:
输出到文件 party.out 中。
对于每组测试数据,输出一行,包含一个字符串,表示给定字符串是否适合成为字母派对的参与者。 如果是,输出 Yes;如果不是,输出 NO。
样例输入:
输入数据 1
4
a
A
aAa
aba
样例输出:
输出数据 1
Yes
No
Yes
No
样例解释
对于第三组测试数据,因为第一位和第三位的 a 是小写字母,第二位的 A 是大写字母,因此适合成为字母派对的参与者。而第四组测试数据中,第二位的 b 是小写字母,因此不适合成为字母派对的参与者。
数据范围
对于100%的数据,满足 1≤T≤103,1≤|S|≤102。
做题思路,解决过程
这题的难点在于输入格式是由文件 party.in 中的数据格式决定的,文件 party.in 并没有直接提供给我们,但我们可以参考题目中的样例输入自己创建一个文件 party.in 。
确定了输入文件 party.in,接着解决文件读写问题,读写时需要注意 “换行符” 的读写。
除了文件读写,还需要对字符串进行操作,题目中要求奇数位为小写,偶数位为大写,对于字母大小写判断我第一张时间想到 ASCII 码表,大小写字母的 ASCII 值是有范围的,大写字母 65-90,小写字母 97-122。对于奇偶的判断就用 for 循环。
核心代码
C / C++ 文件读写
读文件既可以一个一个字符读取 fgetc(FILE *stream)
,也可以读取一行字符串 fgets(char *str, int n, FILE *stream)
;
除了文中方法判断奇偶位大小写,还可以使用 for()
循环逐个字符读取并判断,如果不符合规则则中断本行读取,直接读取下一行,可能这样会比较节省内存,这里只是提供另一种解题思路,大家伙可以自行尝试。
FILE *fin=fopen("party.in", "r"); // r 读文件
char str[101]; //读取文件字符串
FILE *fout=fopen("party.out", "w"); // w 写文件
//读文件
printf("读取文件结果:\n");
printf("读取单个字符:%c\n", fgetc(fin)); //读取单个字符 fgetc
fgetc(fin); //读取 4 后换行符
/*
读取 101 个字符 fgets,如果都到换行则结束,为什么是 101,因为题目 “数据范围” 有规定 1≤|S|≤10^2
则字符有 100 个,加上行末的换行符 '\n' 就是 101 个字符
*/
printf("读取一行字符串(包括换行符):%s", fgets(str, 101, fin));
//写文件
fprintf(fout, "Yes\n");
fprintf(fout, "No\n");
party.in、party.out 都是和代码放同一文件夹的,用的是 “相对路径”
party.in 文件
读取结果:可以看出字符串 “a” 的后面是有换行的,记住这个换行,后面要处理掉它
写入结果 party.out :
C / C++ 判断奇偶字母大小写
整体思路:
读取文件字符串时会把换行符也当作一个字符,在获取字符串长度应注意实际值需要 -1。
1.先判断奇数位字母是否全小写:如果其中一个字母不是小写,则余下的字符(包括偶数位字母)都不用判断,字符串不符合 “奇数位小写”,返回 “No”;如果奇数位都是小写,则需要结合偶数位是否全大写的结果在返回 “Yes / No”;
2.判断偶数位字母是否全大写:如果其中一个字母不是大写,则余下的偶数位字符都不用判断,字符串不符合 “偶数位大写”,返回 “No”;如果奇数位都是小写、偶数位都是大写则返回 “Yes”。
发现了没有,返回 “Yes” 则奇数位与偶数位同时成立,返回 “No” 则奇数位与偶数位任一不成立,返回结果符合 “逻辑与” 运算。则写代码的时候添加 “奇数位标志”、“偶数位标志”,“奇数位标志” 或 “偶数位标志” 为 “0” 则退出判断,返回 “No”;“奇数位标志” 和 “偶数位标志” 同时为 “1” 则返回 “Yes”。
char str[3]="aAa"; //以字符串 aAa 为例(注意这里没有换行符),可以自行修改字符串以及添加换行符测试
char jishu=1, oushu=1;
//打印字符串
printf("%s\n", str);
// 判断奇数位小写
for(int j=0; j<strlen(str); j+=2) //如果字符串包含换行符则需要 j<strlen(str)-1
{
if(jishu && str[j]<=90)
{
jishu=0;
break;
}
}
// 判断偶数位大写
for(int j=1; j<strlen(str); j+=2) //如果字符串包含换行符则需要 j<strlen(str)-1
{
if(jishu && str[j]>=97)
{
oushu=0;
break;
}
}
//进行逻辑与运算,返回结果
if(jishu && oushu)
{
printf("Yes\n");
}
else
{
printf("No\n");
}
运行结果:
Python 文件读写
Python 读文件时使用 splitlines()
函数,按照分隔符(如:\n、\r、\r\n)将字符串分割成列表。
party_in=open('party.in', 'r') #读文件
party_out=open('party.out', 'w') #写文件
list=[] #用来存储读文件内容
answer=[] #用来存储写文件内容
# 读取文件
with party_in:
list = party_in.read().splitlines()
print(list)
# 写入文件
party_out.write("Yes"+'\n')
party_out.write("No"+'\n')
print(party_out)
party.in、party.out 也是和代码放同一文件夹的,用的是 “相对路径”
party.in 文件
读取结果:
写入结果 party.out :
Python 判断奇偶字母大小写
Python 的代码灵活很多,看起来十分的简短,写代码时需要更抽象的思维,从 C 转到 Python 时会觉得别扭,其实是对 Python 的函数、工具不够熟悉,用多了也就更灵活了。
Python 跟 C 语言不同的地方在于:Python 将奇数位、偶数位字符切片组合成新的字符串,再判断奇偶字符串是否全大小写;C 语言则是一个字符一个字符地判断
list="aCaCaCaCaCaCaCaCaCaCaCaCaCaCaCaCaCaCaCaCaCaCaCaCaCaCaCaCaCaCaCaC" #可自行更换字符串测试
print(list + "长度为:", len(list))
print("奇数位切片" + list[0::2])
print("偶数位切片" + list[1::2])
if list[0::2].islower() and list[1::2].isupper():
print("Yes")
else:
print("No")
运行结果:
完整代码
C 语言 完整代码
#include <stdio.h>
#include <string.h>
int main()
{
FILE *fin=fopen("party.in", "r");
FILE *fout=fopen("party.out", "w");
int n=fgetc(fin)-'0'; //将 n 从字符转换为整数
char str[100];
char jishu=1, oushu=1;
fgetc(fin); //读取首行换行符
// 获取字符串并判断奇偶数位大小写
for(int i=0; i<n; i++, jishu=1, oushu=1)
{
fgets(str, 100, fin); // 读取的字符串有换行符
// 判断奇数位小写
for(int j=0; j<strlen(str)-1; j+=2)
{
if(jishu && str[j]<=90)
{
jishu=0;
break;
}
}
// 判断偶数位大写
for(int j=1; j<strlen(str)-1; j+=2)
{
if(jishu && str[j]>=97)
{
oushu=0;
break;
}
}
if(jishu && oushu)
{
fprintf(fout, "Yes\n");
}
else
{
fprintf(fout, "No\n");
}
}
fclose(fin);
fclose(fout);
return 0;
}
C++ 完整代码
#include <iostream>
#include <string.h>
using namespace std;
int main()
{
FILE *fin=fopen("party.in", "r");
FILE *fout=fopen("party.out", "w");
int n=fgetc(fin)-'0';
char str[101];
char jishu=1, oushu=1;
fgetc(fin); //读取换行符
// 获取字符串并判断奇偶数位大小写
for(int i=0; i<n; i++, jishu=1, oushu=1)
{
fgets(str, 101, fin); // 读取一行字符串(含换行符)
// 判断奇数位小写
for(int j=0; j<strlen(str)-1; j+=2)
{
if(jishu && str[j]<=90)
{
jishu=0;
break;
}
}
// 判断偶数位大写
for(int j=1; j<strlen(str)-1; j+=2)
{
if(jishu && str[j]>=97)
{
oushu=0;
break;
}
}
if(jishu && oushu)
{
fprintf(fout, "Yes\n");
}
else
{
fprintf(fout, "No\n");
}
}
fclose(fin);
fclose(fout);
return 0;
}
Python 完整代码
party_in=open('party.in', 'r')
party_out=open('party.out', 'w')
n=0
list=[] #字符串列表
answer=[] #答案列表
# 读取文件
with party_in:
list = party_in.read().splitlines()
print("读取文件获得的数据:",list)
# 获得 n 的值,并将 n 从字符串列表移出
n=list[0]
list.remove(n)
print("移出 n 后的数据:",list)
# 判断奇偶数位大小写
for i in range(int(n)):
if len(list[i])==1 and list[i].islower(): #当只有一个字符时只需判断
answer.append("Yes")
elif list[i][0::2].islower() and list[i][1::2].isupper():
answer.append("Yes")
else:
answer.append("No")
# 答案列表
print("------\n\n答案列表")
print(answer)
for item in answer:
party_out.write(item+'\n')
print(party_out)
评测结果
可能题目需要读写文件导致评测出 bug 了,所以我们自己评测即可。
C / C++ 评测结果
C / C++ 输入文件 party.in,可自行修改字符串以及第一行参数 n 的值
输出文件 party.out
Python 评测结果
Python 输入文件 party.in,可自行修改字符串以及第一行参数 n 的值
Python 输出文件 party.out
Python 控制台输出
后记
通过本题的练习,更深入理解 “面向过程” 与 “面向对象” 的区别。“面向过程” 更侧重逻辑上每一步的精确步骤,而 “面向对象” 则更侧重对 “对象” 的处理。就像在判断 “奇偶位的字母大小写” 时,C / C++ 需要我们理解判断过程是怎样的再去写代码;而 Python 则把字符串按照奇偶位分成两串字符串,再判断所有字符是否符合大小写,一切操作都是为了方便处理 “对象”,当然 Python 所耗费的时间、内存也更多。
加油!加油!加油!每天进步一点点,慢慢地你就会变成大师!