BUAA 2019 数据结构第二次上机

BUAA 2019 数据结构第二次上机

这次作业可以用结构体的qsort,不了解的可以参考这篇博文: https://blog.csdn.net/qq_43803508/article/details/103977546
当然不用也是完全可以的

1 五子棋危险判断

【问题描述】

已知两人分别执白棋和黑棋在一个围棋棋盘上下五子棋,若同一颜色的棋子在同一条横行、纵行或斜线上连成5个棋子,则执该颜色棋子的人获胜。编写程序读入某一时刻下棋的状态,并判断是否有人即将获胜,即:同一颜色的棋子在同一条横行、纵列或斜线上连成4个棋子,且该4个棋子的两端至少有一端为空位置。
输入的棋盘大小是19×19,用数字0表示空位置(即没有棋子),用数字1表示该位置下了一白色棋子,用数字2表示该位置下了一黑色棋子。假设同一颜色的棋子在同一条横行、纵列或斜线上连成的棋子个数不会超过4个,并且最多有一人连成线的棋子个数为4。

【输入形式】

从控制台输入用来表示棋盘状态的数字0、1或2;每行输入19个数字,各数字之间以一个空格分隔,每行最后一个数字后没有空格;共输入19行表示棋盘状态的数字。

【输出形式】

若有人即将获胜,则先输出即将获胜人的棋子颜色(1表示白色棋子,2表示黑色棋子),然后输出英文冒号:,最后输出连成4个棋子连线的起始位置(棋盘横行自上往下、纵列自左往右从1开始计数,横行最小的棋子在棋盘上的横行数和纵列数作为连线的起始位置,若在同一行上,则纵列数最小的棋子位置作为起始位置,两数字之间以一个英文逗号,作为分隔符)。
若没有人获胜,则输出英文字符串:No。
无论输出什么结果,最后都要有回车换行符。

【输入样例1】

0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 2 0 1 1 2 0 0 0 0 0 0 0
0 0 0 0 0 2 1 1 1 1 2 2 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1 2 1 2 0 0 0 0 0 0 0 0
0 0 0 0 0 0 1 1 0 2 2 0 0 0 0 0 0 0 0
0 0 0 0 0 2 0 1 0 0 2 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 1 2 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

【输出样例1】

1:9,8

【输入样例2】

0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1 2 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1 2 2 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

【输出样例2】

No

【样例说明】

在输入的样例1中,执白棋(数字1表示)的人即将获胜,连成4个棋子且有一端为空的起始位置在第9行第8列,所以输出1:9,8。
在输入的样例2中,还没有同一颜色的棋子连成4个,所以无人即将获胜,直接输出No。

【评分标准】

该题要求判断五子棋的棋盘状态,提交程序文件名为chess.c。

思路:

模拟,暴力就完事了。。。。。。。

题解:

#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
int pan[20][20];
int i,j;
int willwin1(int a[20][20],int i,int j)
{
    if(a[i][j]==1&&a[i][j+1]==1&&a[i][j+2]==1&&a[i][j+3]==1&&(a[i][j-1]==0||a[i][j+4]==0)) return 1;
    else if(a[i][j]==1&&a[i+1][j]==1&&a[i+2][j]==1&&a[i+3][j]==1&&(a[i-1][j]==0||a[i+4][j]==0)) return 1;
    else if(a[i][j]==1&&a[i+1][j-1]==1&&a[i+2][j-2]==1&&a[i+3][j-3]==1&&(a[i-1][j+1]==0||a[i+4][j-4]==0)) return 1;
    else if(a[i][j]==1&&a[i+1][j+1]==1&&a[i+2][j+2]==1&&a[i+3][j+3]==1&&(a[i-1][j-1]==0||a[i+4][j+4]==0))return 1;
    else return 0;
}
int willwin2(int a[20][20],int i,int j)
{
    if(a[i][j]==2&&a[i][j+1]==2&&a[i][j+2]==2&&a[i][j+3]==2&&(a[i][j-1]==0||a[i][j+4]==0)) return 1;
    else if(a[i][j]==2&&a[i+1][j]==2&&a[i+2][j]==2&&a[i+3][j]==2&&(a[i-1][j]==0||a[i+4][j]==0)) return 1;
    else if(a[i][j]==2&&a[i+1][j-1]==2&&a[i+2][j-2]==2&&a[i+3][j-3]==2&&(a[i-1][j+1]==0||a[i+4][j-4]==0)) return 1;
    else if(a[i][j]==2&&a[i+1][j+1]==2&&a[i+2][j+2]==2&&a[i+3][j+3]==2&&(a[i-1][j-1]==0||a[i+4][j+4]==0))return 1;
    else return 0;
}
int main()
{
    int flag = 0;
    for(i = 0; i< 19; i++)
        for(j = 0; j< 19; j++) scanf("%d",&pan[i][j]);
    for(i = 0 ; i< 19; i++)
    {
    for(j = 0; j< 19;j++)
    {
        if(willwin1(pan,i,j))
        {
            printf("1:%d,%d\n",i+1,j+1);
            flag = 1;
        }
        if(willwin2(pan,i,j))
        {
            printf("2:%d,%d\n",i+1,j+1);
            flag = 1;
        }
        if(flag == 1) break;

    }
    if(flag == 1) break;
    }
    if(flag == 0) printf("No\n");
    return 0;
}

2 字符串替换(新)

【问题描述】

编写程序将一个指定文件中某一字符串替换为另一个字符串。要求:(1)被替换字符串若有多个,均要被替换;(2)指定的被替换字符串,大小写无关。

【输入形式】

给定文件名为filein.txt。从控制台输入两行字符串(不含空格,行末尾都有回车换行符),分别表示被替换的字符串和替换字符串。

【输出形式】

将替换后的结果输出到文件fileout.txt中。

【样例输入】

从控制台输入两行字符串:

in

out

文件filein.txt的内容为:

#include <stdio.h>
void main()
{
    FILE * IN;
    if((IN=fopen("in.txt","r"))==NULL)
    {
       printf("Can&rsquo;t open in.txt!");
       return;
    }
    fclose(IN);
}

【样例输出】

文件fileout.txt的内容应为:

#outclude <stdio.h>
void maout()
{
    FILE * out;
    if((out=fopen("out.txt","r"))==NULL)
    {
       prouttf("Can&rsquo;t open out.txt!");
       return;
    }
    fclose(out);
}

【样例说明】

输入的被替换字符串为in,替换字符串为out,即将文件filein.txt中的所有in字符串(包括iN、In、IN字符串)全部替换为out字符串,并输出保存到文件fileout.txt中。

【评分标准】

该题要求得到替换后的文件内容,共有5个测试点。上传C语言文件名为replace.c。

思路:

这个题是涉及到了文件的操作

题解:

#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
char go[10001];
char togo[10001];
char s[10005];
char o[1023];
int main()
{
    scanf("%s",go);                                                     //读入被替换字符串
    scanf("%s",togo);                                                   //读入替换字符串
    int len1 = strlen(go);
    int len2 = strlen(togo);
    FILE *fp = fopen("filein.txt","r");                                 //设置文件指针
    FILE *fp2 = fopen("fileout.txt","w");
    char c;
    int p = 0;
    while((c=fgetc(fp))!=EOF) s[p++] = c;                               //读入文件中的字符,并存在数组s中
    s[p] = '\0';
    int len = strlen(s);
    int i=0,j;
    int k=0;
    while(i < len){
        for(j = i; j <(len1+i);j++)                                     //读入被替换字符串长度的代码
        {
            o[k] = s[j];
            k++;
        }
        if(!strcasecmp(go,o)){                                          //如果能和被替换字符串匹配,输出替换字符串,i往后走len1个单位
            int x;
            for(x = 0; x < len2;x++) fputc(togo[x],fp2);
            i+= len1;
            k = 0;
        }
        else{
            fputc(s[i],fp2);                                            //否则输出当前字符,i++
            k = 0;
            i++;
        }
    }
    fclose(fp);
    fclose(fp2);
    return 0;

}


3 加密文件

在这里插入图片描述

思路:

模拟,细心就行

题解:

#include <stdio.h>
#include <string.h>
#include <ctype.h>

char s[505];
char encrypt[1005];
int flag[205];
int main()
{
    FILE *fp1 = fopen("encrypt.txt","r");
    FILE *fp2 = fopen("output.txt","w");
    char p;
    int lens = 0;
    while((p = getchar())!= EOF && p != '\n') s[lens++] = p;     //读入初始密钥
    int cnt = 0;
    for(int i = 0; i < lens; i++)
        if(flag[s[i]-'a'] == 0) {                                //去除初始密钥中重复的字母
            s[cnt++] = s[i];
            flag[s[i]-'a'] = 1;
        }
    for(int i = 25; i >=0; i--)
        if(flag[i] == 0) s[cnt++] = 'a'+i;                       //把除密钥之外的字母倒着加到密钥后面
    char c; int k = 0;
    while((c = fgetc(fp1))!= EOF) encrypt[k++] = c;
    for(int i = 0; i < k; i++)
        if(isalpha(encrypt[i])) fputc(s[encrypt[i] - 'a'],fp2);  //输出字母对于的密钥字符
        else fputc(encrypt[i],fp2);
    fclose(fp1);
    fclose(fp2);
    return 0;

}


4 通讯录整理

【问题描述】

读取一组电话号码簿(由姓名和手机号码组成),将重复出现的项删除(姓名和电话号码都相同的项为重复项,只保留第一次出现的项),并对姓名相同手机号码不同的项进行如下整理:首次出现的项不作处理,第一次重复的姓名后面加英文下划线字符_和数字1,第二次重复的姓名后面加英文下划线字符_和数字2,依次类推。号码簿中姓名相同的项数最多不超过10个。最后对整理后的电话号码簿按照姓名进行从小到大排序,并输出排序后的电话号码簿。

【输入形式】

先从标准输入读取电话号码个数,然后分行输入姓名和电话号码,姓名由不超过20个英文小写字母组成,电话号码由11位数字字符组成,姓名和电话号码之间以一个空格分隔,输入的姓名和电话号码项不超过100个。

【输出形式】

按照姓名从小到大的顺序分行输出最终的排序结果,先输出姓名再输出电话号码,以一个空格分隔。

【样例输入】

15
liping 13512345678
zhaohong 13838929457
qiansan 13900223399
zhouhao 18578294857
anhai 13573948758
liping 13512345678
zhaohong 13588339922
liping 13833220099
boliang 15033778877
zhaohong 13838922222
tianyang 18987283746
sunnan 13599882764
zhaohong 13099228475
liushifeng 13874763899
caibiao 13923567890

【样例输出】

anhai 13573948758
boliang 15033778877
caibiao 13923567890
liping 13512345678
liping_1 13833220099
liushifeng 13874763899
qiansan 13900223399
sunnan 13599882764
tianyang 18987283746
zhaohong 13838929457
zhaohong_1 13588339922
zhaohong_2 13838922222
zhaohong_3 13099228475
zhouhao 18578294857

【样例说明】

输入了15个人名和电话号码。其中第一项和第六项完全相同,都是“liping 13512345678”,将第六项删除,第一项保留;

第八项和第一项人名相同,电话不同,则将第八项的人民整理为liping_1;同样,第二项、第七项、第十项、第十三项的人名都相同,将后面三项的人名分别整理为:zhaohong_1、zhaohong_2和zhaohong_3。

最后将整理后的电话簿按照姓名进行从小到大排序,分行输出排序结果。

【评分标准】

该题要求编程实现通讯录的整理与排序,提交程序文件名为sort.c。

思路:

题解:

#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
typedef struct student{
    int flag;
    char name[20];
    char number[20];
    int cnt;
}stu[105];
int main()
{
    struct  student stu[105];
    int n;
    scanf("%d",&n);
    for(int i = 1; i<= n; i++)
        {scanf("%s%s",stu[i].name,stu[i].number); stu[i].flag = 0; stu[i].cnt = 0;}
        
    int fg = 1;
    for(int i = 1; fg; i++) {
		fg = 0;
		char temp1[25],temp2[25];
		for(int j = n; j >= i+1; j--) {
            if(strcmp(stu[j-1].name,stu[j].name)>0)
            {
                strcpy(temp1,stu[j].name);
                strcpy(stu[j].name,stu[j-1].name);
                strcpy(stu[j-1].name,temp1);
                strcpy(temp2,stu[j].number);
                strcpy(stu[j].number,stu[j-1].number);
                strcpy(stu[j-1].number,temp2);
                fg = 1;
            }
		}
	}
    for(int i = 1; i <= n; i++)
    {
        if(strcmp(stu[i].name,stu[i+1].name)==0)
        {
            if(strcmp(stu[i].number,stu[i+1].number)==0)
                stu[i+1].flag = 1;
            else stu[i+1].cnt = stu[i].cnt + 1;
        }
        if(stu[i].cnt >=1 &&stu[i].flag == 0) printf("%s_%d %s\n",stu[i].name,stu[i].cnt,stu[i].number);
        if(stu[i].cnt == 0 && stu[i].flag == 0) printf("%s %s\n",stu[i].name,stu[i].number);
        if(stu[i].flag == 1) continue;
    }
    return 0;
}
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
typedef struct student{
    int flag;
    char name[20];
    char number[20];
    int cnt;
    int num;
}stu[105];

int cmp(const void *a, const void *b) {
    struct student  *c = (struct student *)a;
    struct student 	*d = (struct student *)b;
    if(strcmp(c->name,d->name)!=0)
    return strcmp(c->name,d->name);
    else return c->num - d->num;
}


int main()
{
    struct  student stu[105];
    int n,i;
    scanf("%d",&n);
    for(i = 1; i<= n; i++)
        {scanf("%s%s",stu[i].name,stu[i].number); stu[i].flag = 0; stu[i].cnt = 0;stu[i].num = i;}
    qsort(stu+1,n,sizeof(stu[0]),cmp);
        
     for(i = 1; i<=n;i++)
     {
         if(strcmp(stu[i].name,stu[i+1].name)==0)
         {
             if(strcmp(stu[i].number,stu[i+1].number)==0)
                 stu[i+1].flag = 1;
             else stu[i+1].cnt = stu[i].cnt + 1;
         }
         if(stu[i].cnt >=1 &&stu[i].flag == 0) printf("%s_%d %s\n",stu[i].name,stu[i].cnt,stu[i].number);
         if(stu[i].cnt == 0 && stu[i].flag == 0) printf("%s %s\n",stu[i].name,stu[i].number);
         if(stu[i].flag == 1) continue;
     }
    return 0;
}

5 小型图书管理系统

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

思路:

模拟,细心点就行了

题解:

#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
struct books
{
    char name[51];
    char author[21];
    char publisher[41];
    char  date[11];
}book[505],t,enter;
int n = 0;
char s[1000004];


int cmpfuc(const void *a, const void *b) {
	struct books *c = (struct books*)a;
	struct books *d = (struct books*)b;
	return strcmp(c->name,d->name);
}

int main()
{
    FILE *fp = fopen("books.txt","r");
    FILE *fp2 = fopen("ordered.txt","w");
	struct books book[505];

    while( 4 == fscanf(fp,"%s %s %s %s\n",book[n].name,book[n].author,book[n].publisher,book[n].date))		//读入文件中的图书信息
    	n++;	
    qsort(book,n,sizeof(book[0]),cmpfuc);									
    int opt;
    char name[51];
    while(scanf("%d",&opt)==1)
    {
        switch(opt)
		{
			case 1:
			scanf("%s%s%s%s",book[n].name,book[n].author,book[n].publisher,book[n].date);
			n++;
			qsort(book,n,sizeof(book[0]),cmpfuc);

			break;
			case 2:
				scanf("%s",name);
				for(int i = 0; i < n; i++)
					if( strstr(book[i].name,name)!=NULL)
						printf("%-50s%-20s%-30s%-10s\n",book[i].name,book[i].author,book[i].publisher,book[i].date);
				break;
			case 3:
				scanf("%s",name);
				for(int i = 0; i < n; i++)
					if(strstr(book[i].name,name)!=NULL)
	
						for(int j = i; j < n; j++)
							book[j] = book[j+1];
						n--;i--;
					}
			default: break;
		}
		if(opt== 0)
			break;
    }
	for(int i = 0; i < n; i++)
		fprintf(fp2,"%-50s%-20s%-30s%-10s\n",book[i].name,book[i].author,book[i].publisher,book[i].date);
    fclose(fp2);
    fclose(fp);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值