【CODEMATE】CMT0018:字母派对(party) 粤港澳信息学创新大赛 C++/Python 小学组/初中组/高中组 文件读写/字符串/逻辑运算/数组/列表 C/C++/Python解题思路

问题描述

知识点: 基础算法 简单模拟  上传者: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 都是和代码放同一文件夹的,用的是 “相对路径”
c文件位置


  
  

  party.in 文件
party.in文件


  
  

  读取结果:可以看出字符串 “a” 的后面是有换行的,记住这个换行,后面要处理掉它
c读取结果


  
  

  写入结果 party.out :
c写入结果


  
  

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

  
  

  运行结果:
c奇偶断结果


  
  

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 也是和代码放同一文件夹的,用的是 “相对路径”
python文件位置


  
  

  party.in 文件
party.in文件


  
  

  读取结果:
python读取结果


  
  

  写入结果 party.out :
python写入结果


  
  

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")

  
  

  运行结果:
python奇偶判断结果


  
  

完整代码

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 的值
c/c++ party.in


  
  

  输出文件 party.out
c/c++ party.out


  
  

Python 评测结果

  Python 输入文件 party.in,可自行修改字符串以及第一行参数 n 的值
python party.in


  
  

  Python 输出文件 party.out

python party.out


  
  

  Python 控制台输出
python 控制台输出


  
  

后记

  通过本题的练习,更深入理解 “面向过程” 与 “面向对象” 的区别。“面向过程” 更侧重逻辑上每一步的精确步骤,而 “面向对象” 则更侧重对 “对象” 的处理。就像在判断 “奇偶位的字母大小写” 时,C / C++ 需要我们理解判断过程是怎样的再去写代码;而 Python 则把字符串按照奇偶位分成两串字符串,再判断所有字符是否符合大小写,一切操作都是为了方便处理 “对象”,当然 Python 所耗费的时间、内存也更多。

  加油!加油!加油!每天进步一点点,慢慢地你就会变成大师!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值