目录
6-1 指针应用-查找数组元素
编写一个名为findX的函数,该函数的参数p指向一个int数组,数组的容量n由参数2指定。在该数组中,查找数据x所在的位置。如果数据x有出现多次,则返回其最后一次出现的位置对应的下标。如果没有找到,则固定返回-2。
int findX(int *p,int n,int x);
函数接口定义:
int findX(int *p,int n,int x);
在这里解释接口参数。例如:其中 p
和 n
以及x
都是用户传入的参数。 p
是一个指针,指向的数组中有 n
个元素,在该数组中查找数据 x
最后一次出现的位置。
如果找到数据,返回其在数组中的最后一次出现位置的下标;如果没有找到,函数固定返回-2。
裁判测试程序样例:
#include<stdio.h>
#define N 12
//p指向int数组,数组容量为n,要找的数据是x
int findX(int *p,int n,int x);
int main()
{
int a[N];//int数组
int i,x; //循环变量i,要查找的整数x
int iRet; //函数调用的返回值
//接收输入
for(i=0; i<N;i++)
iRet = scanf("%d", &a[i]);
iRet = scanf("%d",&x);
//处理,调用函数
iRet=findX(a,12,x); //在名为a的容量为12的数组中,寻找数据x是否存在
if ( iRet < 0)
printf("Not Found\n");
else
printf("index=%d,value=%d" ,iRet ,a[iRet]);
}
/* 请在这里填写答案 */
输入样例:
第一行是数组元素的值。第二行的3,表示要在数组中查找数据3出现位置。
1 2 3 4 5 6 7 8 9 10 11 12
3
输出样例:
数据3是数组的第3个元素,所对应的下标是2。
index=2,value=3
代码:
int findX(int *p,int n,int x)
{
int i;
for(i = n-1;i >= 0;i--)
{
if(p[i] == x)
return i;
else if(i == 0)
return -2;
}
}
6-2 请编写函数CHG(char *S)
请编写函数CHG(char S)实现程序功能:
把S字符串中的所有字符左移一个位置,串中的第一个字符移到最后,之后把已处理的字符串逆转后仍存入原字符数组中
函数接口定义:
在这里描述函数接口。 void CHG(char *s);
裁判测试程序样例:
在这里给出函数被调用进行测试的例子。例如:
#include <stdio.h>
#include <string.h>
void CHG(char *s);
int main()
{
char s[100], t[100];
scanf("%s", s);
CHG(s);
printf("%s", s);
return 0;
}
/* 请在这里填写答案 */
输入样例:
在这里给出一组输入。例如:
abcde
输出样例:
在这里给出相应的输出。例如:
aedcb
代码:
void CHG(char *s)
{
int n = strlen(s); //计算字符串长度(不算结尾的'\0')
char *ps, kong = *s; //定义一个存放第一个元素的空变量
for(ps = s; ps < s+n-1; ps++) //把依次把元素向前挪一位
{
*ps = *(ps + 1);
}
*(s+n-1) = kong; //然后把刚才空变量存储的值放到最后
char *pb; //定义一个指针指向字符数组的最后一个元素
for(ps = s, pb = s+n-1; ps < pb; ps++, pb--)
{
char m = *ps; //进行交换
*ps = *pb;
*pb = m;
}
}
7-1 秋天的第一杯奶茶
2020年入秋后,朋友圈和微博上疯狂转发着自己收到的“秋天的第一杯奶茶”。然而小明却什么也没有收到,但是学校举行了这样一场活动:通过5道编写程序题目中的3道即可获得一杯奶茶。小明也想喝到秋天的第一杯奶茶。下面就请你判断小明是否有机会拿到学校的奶茶。
输入格式:
两行,第一行给出一个整数N(1<=N<=100),随后N行,每行给出一个长度为5的字符串(仅包含Y和N,分别代表5个题目小明是否通过),Y代表本题通过,N代表本题未通过。
输出格式:
可以拿到奶茶输出“YES”,否则输出“NO”(输出不含双引号)。
输入样例:
3
NNNYN
NNYYY
YYYNN
输出样例:
NO
YES
YES
代码:
#include<stdio.h>
int main()
{
int n;
scanf("%d",&n);
while(n > 0)
{
int count = 0;
char str[6];//包含前一行有个回车
for(int i = 0; i < 6; i++)
{
scanf("%c",&str[i]);
if(str[i] == 'Y')
count++;
}
if(count >= 3)
printf("YES\n");
else printf("NO\n");
n--;
}
return 0;
}
7-2 统计单词
输入长度不超过80的英文文本,统计该文本中长度为n的单词总数(单词之间只有一个空格)。
输入格式:
首先输入一个正整数T,表示测试数据的组数,然后是T组测试数据。
每组数据首先输入1个正整数n(1≤n≤50),然后输入1行长度不超过80的英文文本(只含英文字母和空格)。注意:不要忘记在输入一行文本前吸收换行符。
输出格式:
对于每组测试数据,输出长度为n的单词总数。
输入样例:
2
5
hello world
5
acm is a hard game
输出样例:
2
0
代码:
#include <stdio.h>
#include <string.h> //字符的函数库
int main()
{
int T, n, i, j, times, count; //times用来记录出现要求长度的次数
char str[81];
scanf("%d",&T); //输入测试的组数
for(i = 1; i <= T; i++)
{
scanf("%d",&n); //输入要查找的长度
times = 0; //给次数和计数初始化
count=0;
getchar(); //吸收掉输入结束的回车字符,避免影响后面的字符输入
gets(str); //输入字符串存入数组str
for(j = 0; j <= strlen(str); j++) //从零循环到结束字符'\0',所以要<=,+1也行。
{
if(str[j] != ' ' && str[j] != '\0')
{
count++; //没读到空格或结束标志,计数+1
}
else //当读到空格或者结束标志时,代表单词结束
{
if(n == count) //如果单词长度为n
{
times++; //次数+1
}
count = 0; //重新开始下一个单词的计数
}
}
printf("%d\n",times);
}
}
7-3 找最大字符串
从键盘上输入4个字符串(每个字符串最多包含100个字符),求出其中的最大字符串并输出。
输入格式:
从键盘上输入4个字符串(每个字符串最多包含100个字符)。
输出格式:
输出最大字符串,最后换行。
输入样例1:
dddd
cccc
bbbb
aaaa
输出样例1:
dddd
输入样例2:
bbbb
cccc
dddd
aaaa
输出样例2:
dddd
输入样例3:
cccc
bbbb
aaaa
dddd
输出样例3:
dddd
输入样例4:
dddd
ddcc
ddbb
ddaa
输出样例4:
dddd
代码:
#include <stdio.h>
#include <string.h>
//用strcmp(a, b) 函数,作用是比较两个字符数组,a > b 返回1,小于返回-1,等于返回0
int main()
{
char a[101], b[101], c[101], d[101]; //定义四个字符数组
gets(a);
gets(b);
gets(c);
gets(d); //输入四次
//如果字符串1大于其他三组字符串,那么输出字符串1
if(strcmp(a, b)>0 && strcmp(a, c)>0 && strcmp(a, d)>0)
puts(a); //puts()自带换行功能
else if(strcmp(b, a)>0 && strcmp(b, c)>0 && strcmp(b, d)>0)
puts(b);
else if(strcmp(c, a)>0 && strcmp(c, b)>0 && strcmp(c, d)>0)
puts(c);
else
puts(d);
}
7-4 字符串排序
本题要求编写程序,读入5个字符串,按由小到大的顺序输出。
输入格式:
输入为由空格分隔的5个非空字符串,每个字符串不包括空格、制表符、换行符等空白字符,长度小于80。
输出格式:
按照以下格式输出排序后的结果:
After sorted:
每行一个字符串
输入样例:
red yellow blue black white
输出样例:
After sorted:
black
blue
red
white
yellow
代码:
#include<stdio.h>
#include<string.h>
#define MAX 80
#define N 5
int main()
{
int i,j;
char word[N][MAX],temp[MAX]; //二维数组word,每行存放一个字符串
for(i=0;i<N;i++)
scanf("%s",word[i]);
for(i=1;i<N;i++) //冒泡排序
{
for(j=0;j<N-i;j++)
if(strcmp(word[j],word[j+1])>0)
{
strcpy(temp,word[j]); //数组给数组赋值不能用=,所以改为strcpy()
strcpy(word[j],word[j+1]);
strcpy(word[j+1],temp);
}
}
printf("After sorted:\n");
for(i=0;i<N;i++)
printf("%s\n",word[i]);
return 0;
}
7-5 缩写期刊名
科研工作者经常要向不同的期刊投稿。但不同期刊的参考文献的格式往往各不相同。有些期刊要求参考文献所发表的期刊名必须采用缩写形式,否则直接拒稿。现对于给定的期刊名,要求按以下规则缩写:
(1)长度不超过4的单词不必缩写;
(2)长度超过4的单词仅取前4个字母,但其后要加“.”;
(3)所有字母都小写。
输入格式:
首先输入一个正整数T,表示测试数据的组数,然后是T组测试数据。
每组测试输入一个包含大小写字母和空格的字符串(长度不超过85),单词由若干字母构成,单词之间以一个空格间隔。
输出格式:
对于每组测试,在一行上输出缩写后的结果,单词之间以一个空格间隔。
输入样例:
2
Ad Hoc Networks
IEEE Transactions on Nanotechnology
输出样例:
ad hoc netw.
ieee tran. on nano.
代码:
#include <stdio.h>
#include <string.h>
#define l 4
int initial(char *a);//存储每个单词的长度
void abbr(char *a);
void lowercase(char *a);
int main()
{
int t, i, j, count;
char a[85]; //长度不超过85
scanf("%d",&t); //组数
getchar(); //吸收回车字符
for(i = 1; i <= t; i++)
{
gets(a);
char *pa, *pb;
pa = a; pb = a; //pa pb都从开头开始,pb用来定位每个单词的开头
while(*pa != '\0') //循环到结尾
{
if(initial(pb) > l) //长度大于L就缩写
{
abbr(pb);
}
if(*pa == ' ') //遇见空格代表单词切换
{
pb = pa+1; //让pb跑到下一个单词的开头
}
pa++;
}
lowercase(a); //把处理好的字符小写
puts(a);
}
}
int initial(char *a) //pb指向每个单词开头
{
char *pa;
int count = 0;
pa = a;
while(*pa != ' ' && *pa != '\0') //遇到空格或结束标志代表单词结束
{
count++;
pa++;
}
return count;//该单词的长度
}
void abbr(char *a)
{
char *pa;
*(a+l) = '.'; //把第五个字符换成点
int x = initial(a); //将单词长度赋给x
for(int i = 1; i < x-l; i++) //循环条件
{
for(pa = a+l+1; pa < a+strlen(a); pa++) //a+l+1是因为第五个字符是点
{
*pa = *(pa+1); //前移覆盖掉
}
}
}
void lowercase(char *a)
{
char *pa;
pa = a;
while(*pa != '\0')
{
if(*pa >= 'A' && *pa <= 'Z')//如果字母是大写
{
*pa += 32;//改为小写
}
pa++;
}
}
7-6 魔镜
传说魔镜可以把任何接触镜面的东西变成原来的两倍,不过增加的那部分是反的。例如,对于字符串XY,若把Y端接触镜面,则魔镜会把这个字符串变为XYYX;若再用X端接触镜面,则会变成XYYXXYYX。对于一个最终得到的字符串(可能未接触魔镜),请输出没使用魔镜之前,该字符串最初可能的最小长度。
输入格式:
测试数据有多组,处理到文件尾。每组测试输入一个字符串(长度小于100,且由大写英文字母构成)。
输出格式:
对于每组测试数据,在一行上输出一个整数,表示没使用魔镜前,最初字符串可能的最小长度。
输入样例:
XYYXXYYX
XYXX
输出样例:
2
4
代码:
#include <stdio.h>
#include <string.h>
#include <math.h>
void nixu(char *a);
int main()
{
char a[101], b[101], c[101], *pa; //a是原数组,b用来进行比较,c用来保留a的原型
int i, n, count; //n存放字符串长度,count代表魔镜做了几次
while(scanf("%s", a) != -1) //按照提议输入字符串,处理到文件尾
{
strcpy(c, a); //把a复制给c备用
strcpy(b, a); //把a复制给b比较
count = 0; //给count赋初值
while(strcmp(a,b) == 0) //当a和b字符串相等时,循环继续
{
n = strlen(a); //求出字符串长度
pa = a+n/2; //找到指针pa从a字符数组中间截断的位置
strcpy(b, pa); //把从pa位置以后的字符串复制到b字符数组上
*pa = '\0'; //再给a字符数组前半段加上结束标志
nixu(b); //调取函数逆序摆放b
count++; //计数加一,循环结束count会多加一次
}
int q = pow(2,count - 1); //用减半的次数来算出长度的倍数
printf("%d\n",strlen(c)/q); //用总长度减去倍数,就得到了最短长度
}
}
void nixu(char *a) //逆序字符数组的函数,之前的题有出现过
{
int n = strlen(a);
char *pa, *pb;
for(pa = a, pb = a+n-1; pa < pb; pa++,pb--)
{
char m = *pa;
*pa = *pb;
*pb = m;
}
}
7-7 书号判断与纠错
图书都有唯一的ISBN码(书号)标识,ISBN分为10位和13位两种。对于10位的ISBN码,包含9位数字和1位校验码,其格式如“a-bcd-efghi-j”,其中符号“-”是分隔符,字母a,b,……,i代表0,1,……,9中的某位数字,最后一位是校验码(可以为0,1,……,9中的某位数字,也可以是大写字母X)。
对于格式为“a-bcd-efghi-j”的书号,校验码的计算方法如下(参考自百度百科):
将去掉校验码后得到的9位数字依序分别乘以从10,9,8,……,3,2,将其乘积相加得到累加和sum,求余数r=sum%11;若r=0,则校验码为0;否则求11与r的差数d=11-r,若d=10,则以“X”来表示校验码,否则校验码为d。即:
sum=a×10+b×9+c×8+d×7+e×6+f×5+g×4+h×3+i×2,r=sum % 11,若r为0,则校验码为0,否则d=11-r,若d=10,则校验码为大写字母X,否则校验码为d。
例如,对于书号:7-302-56474-4,有
sum=7×10+3×9+0×8+2×7+5×6+6×5+4×4+7×3+4×2=216,r=216 % 11=7,d=11-7=4,因此校验码为4。
请判断输入书号中的校验码是否正确,若正确,则输出“OK”,否则输出更新校验码后的正确书号。
输入格式:
首先输入测试组数T,然后输入T组测试数据。每组测试输入一个字符串代表书号,格式为“a-bcd-efghi-j”。
输出格式:
对于每组测试,输出一行,若书号的校验码正确,则输出“OK”,否则输出更新校验码后的正确书号,格式为“a-bcd-efghi-j”。引号不必输出。
输入样例:
2
7-302-56474-4
6-302-57644-3
输出样例:
OK
6-302-57644-X
代码:
#include <stdio.h>
int main()
{
int t, i, j, k, sum, count;
char a[50], m;
scanf("%d",&t);
getchar(); //记得把scanf的回车吸收掉
for(i = 1; i <= t; i++)
{
gets(a);
sum = 0; j = 0;
k = 10; count = 0;
while(count < 9)
{
if(a[j] >= '0' && a[j] <= '9')
{ //因为结果askii码 要减去'0'
sum += k*(a[j]-'0');//比如字符'7'对应的ascii码37,'0'对应的ascii码30,37-30=7
k--;
count++;
}
j++;
}
int r = sum%11;
if(r == 0)
{
m = '0';
}
else
{
int d = 11-r;
if(d == 10)
{
m = 'X';
}
else
{
m = d+'0';//m为字符型,d整型,若d=4,字符是计算ascii码,
//'0'ascii码为30,34就是m的ascii码值 对应的字符为'4'
//所以整型转换为字符型加'0'
}
}
if(a[12] == m)
{
printf("OK\n");
}
else
{
a[12] = m;
printf("%s\n",a);
}
}
}
7-8 检查密码
本题要求你帮助某网站的用户注册模块写一个密码合法性检查的小功能。该网站要求用户设置的密码必须由不少于6个字符组成,并且只能有英文字母、数字和小数点 .
,还必须既有字母也有数字。
输入格式:
输入第一行给出一个正整数 N(≤ 100),随后 N 行,每行给出一个用户设置的密码,为不超过 80 个字符的非空字符串,以回车结束。
注意: 题目保证不存在只有小数点的输入。
输出格式:
对每个用户的密码,在一行中输出系统反馈信息,分以下5种:
- 如果密码合法,输出
Your password is wan mei.
; - 如果密码太短,不论合法与否,都输出
Your password is tai duan le.
; - 如果密码长度合法,但存在不合法字符,则输出
Your password is tai luan le.
; - 如果密码长度合法,但只有字母没有数字,则输出
Your password needs shu zi.
; - 如果密码长度合法,但只有数字没有字母,则输出
Your password needs zi mu.
。
输入样例:
5
123s
zheshi.wodepw
1234.5678
WanMei23333
pass*word.6
输出样例:
Your password is tai duan le.
Your password needs shu zi.
Your password needs zi mu.
Your password is wan mei.
Your password is tai luan le.
代码:
#include<stdio.h>
#include<string.h>
int main()
{
int x;
scanf("%d",&x);
getchar();//吃掉回车
while(x--)
{
char p[81];
gets(p);//包含像空格之类的字符也要记录其中,所以用gets而不用scanf
int num1=0,num2=0,num3=0;
if(strlen(p)<6)
{
printf("Your password is tai duan le.\n");
continue;
}
for(int i=0;i<strlen(p);i++)
{
if(p[i]<='z'&&p[i]>='a'||p[i]<='Z'&&p[i]>='A')
num1++;
if(p[i]>='0'&&p[i]<='9')
num2++;
if(p[i]=='.')
num3++;
}
if(num3+num1+num2==strlen(p))
{
if(num1==0&&num2!=0)
printf("Your password needs zi mu.\n");
if(num1!=0&&num2==0)
printf("Your password needs shu zi.\n");
if(num1!=0&&num2!=0)
printf("Your password is wan mei.\n");
}
else
printf("Your password is tai luan le.\n");
}
}
7-9 六大门派身份识别
武林中六大门派“少林派、武当派、昆仑派、峨嵋派、华山派、崆峒派”的弟子众多,他们行走江湖,需要能够互相识别身份,以免被邪门歪道的恶人冒充。
六大门派(以下简称“正派”)的掌门人聚在一起闭关半年,设计出来这样一个识别方式:
每名正派弟子均有一个身份验证码,并熟知验证规则。当一名正派弟子遇见另一名自称为正派弟子的人,就要求对方报出身份验证码。若验证无误,则交个朋友;若验证失败,说明对方为假冒的,立即开战(当然,如果打不过就溜……)
验证码是这样的:
- 由9位数字组成;
- 首位数字表示所在的门派编号,少林派、武当派、昆仑派、峨嵋派、华山派、崆峒派依次使用
0
-5
表示; - 接下来4位数字记为整数
a
,最后4位数字记为整数b
; (若a、b不满4位,则左边添0
补位)
例如:000100015
即表示少林派、a
是10
,b
是15
验证规则是这样的:
- 找出整数
a
和整数b
之间(包括a和b)的所有素数p1、p2、p3、... (提示: a、b均可以是0-9999
的任何数) - 计算所有这些素数的各位数字之和
sum
(若a、b之间没有素数,则sum
计为0
) - 求出
sum
除以6
的余数r
- 若余数r与首位门派编号相同,则验证通过,否则为验证失败
例如,验证码000100015
可以通过验证,因为10-15
之间的素数有11
、13
,其各位数字之和为(1+1+1+3) = 6
,6除以6的余数为0
,与门派编号0
相同。
现在给你一些身份验证码,请进行验证、判断是正派弟子还是恶人冒充。
输入格式:
第一行给出1个不超过100
的正整数N
;
接下来N
行,每行给出1个9位的验证码.
提示: C语言的scanf( )函数第一个参数若使用 "%d"
可以读取一个十进制整数,若使用 "%5d"
则可以读取一个5位十进制整数。这条提示或可帮助你对此题进行输入。
输出格式:
对每一个验证码,在一行中给出验证结果:
- 如果验证通过,先给出所在门派,然后是素数各位数字之和
sum
,中间空1格。 六大门派依次使用拼音表示:shaolin
,wudang
,kunlun
,emei
,huashan
,kongtong
; - 如果验证失败,则要开战了,输出
Fighting!
输入样例1:
3
000200022
219492021
202230666
输出样例1:
shaolin 0
Fighting!
kunlun 986
输入样例2:
3
500320050
400900105
500100002
输出样例2:
Fighting!
huashan 22
kongtong 17
代码:
#include <stdio.h>
int sushu(int n);
int gewei(int n);
int main()
{
int t, i, j, m, n, a, b, sum, r;
scanf("%d",&t);
for(i = 1; i <= t; i++)
{
scanf("%1d%4d%4d",&n, &a, &b);
if(a > b) //保证b>a的交换
{
m = a;
a = b;
b = m;
}
sum = 0; //sum赋初值
for(j = a; j <= b; j++) //求从a到b的素数
{
if(sushu(j)) //当j时素数时,用gewei函数求他每个位数和
sum += gewei(j);
}
r = sum % 6; //依照提议求r余数
if(r != n)
{
printf("Fighting!\n");
}
else
{
switch(r) //分支看起来简洁些
{
case 0: printf("shaolin %d\n", sum);break;//如果r=0时
case 1: printf("wudang %d\n", sum);break;
case 2: printf("kunlun %d\n", sum);break;
case 3: printf("emei %d\n", sum);break;
case 4: printf("huashan %d\n", sum);break;
case 5: printf("kongtong %d\n", sum);break;
}
}
}
}
int sushu(int n)
{
#include<math.h>
int i;
if(n == 0 || n == 1)
return 0;
else if(n == 2)
return 1;
for(i = 2; i < sqrt(n)+1; i++)
{
if(n%i == 0)
return 0;//返回0:不是素数
}
return 1;//返回1:是素数
}
int gewei(int n)
{
int sum = 0;
while(n > 0)
{
sum += n%10;
n /= 10;
}
return sum;
}