因为自己之前只学过java,C语言没有学,直接跟着紫书开始做题了,写这道题的时候发现自己对之前所做的题的一些细节部分的代码理解的不是很透彻,还是需要多加练习。提交后出现presentation error,改了得有一个多小时,真是让人抓狂。详细题目里的输出得好好理解什么意思!
题目
- 详细题目
- 简略题目:
- 输入一个r行c列(1<=r,c<=10)的网格,黑格用*表示,每个白格都填有一个字母。如果一个白格的左边相邻位置或者上边相邻位置没有白格(可能是黑格,也可能出了网格边界),则称这个白格是一个起始格。
- 首先把所有起始格按照从上到下、从左到右的顺序编号为1、2、3、······
- 接下来要找出所有横向单词(Across)。这些单词必须从一个起始格开始,向右延伸到一个黑格左边或者整个网格的最右列。最后找到所有竖向单词(Down).这些单词必须从一个起始格开始,向下延伸到一个黑格的上边或者整个网格的最下行。
思路
- 先是定义一个存储输入的字母的二维数组network_alpha[r][c],因为是按行输入的,有两种方式
- 直接用network_alpha[row]接收输入(这个虽然一条语句就行,但时间莫名的长,不知道为什么)
- 定义一个新的行数组network_row_alpha[c],用其接收输入的字母,然后再for循环赋值给network_alpha
- 然后定义一个存储起始格数字的二维数组network_num[][],因为是二维数组要一个一个赋值所以双层for循环赋值
- 如果不是起始格其值为0,可以实现用memset清零。
- 定义一个变量count,记录起始格数编号
- 分析题目,第一行和第一列总为起始格
- 当格子内是"*"或者其上方和左方都是字母时不是起始格
- 准备工作做好后,就要开始输出了,这里需要注意输出的格式,有两点需要注意
- 输出起始格的数字时是三位数
- 题目中的最后一句话Separate output for successive input puzzles by a blank line.
- 要准确理解这句话意思,我就是在这掉坑了。
- 除了第一个puzzle外,其他puzzle前都要有一个空行。
- 输出起始格的数字时是三位数
- 输出横向单词
- network_num编号如果是0则不是起始格,直接过。如果不是0,则输出。
- 注意输出过的字母,不再输出,访问过的字母对应的起始格编号置为0
- 从起始格开始,向右延伸到一个黑格的左边或者整个网格的最右边。
- 输出纵向单词
- 其单词按列排列,看输出的起始格编号由小到大可知是按行循环。
- 因为输出过的字母不能再输出,所以需要再定义一个变量row控制字母的输出,并把输出的字母对应的编号置为0。
代码
#include<stdio.h>
#include<string.h>
#include<ctype.h>
int main(){
int r,c;
int kase=0;
while(scanf("%d",&r)&&r){
scanf("%d",&c);
char network_alpha[r][c];
int row=0;
//输入的字母二维数组
while(row<r){
char network_row_alpha[c]; //char类型的数组,输出某个字符必须用putchar!!!!
scanf("%s",network_row_alpha); //注意 network_row_alpha是一个数组,其名字代表首地址,所以不用加"&"符号
int i;
for(i=0;i<c;i++)
network_alpha[row][i]=network_row_alpha[i];
row++;
}
//将字母二维数组转化为数字二维数组
int network_num[r][c];
memset(network_num,0,sizeof(network_num));
int i,j;
int count=1;
for(i=0;i<r;i++)
for(j=0;j<c;j++){
if(network_alpha[i][j] != '*'){
if(i==0 || j==0) network_num[i][j]=count++;
else if(!(isalpha(network_alpha[i-1][j]) && isalpha(network_alpha[i][j-1]))) network_num[i][j]=count++;
}
}
//Separate output for successive input puzzles by a blank line.
if(kase++) printf("\n");
//输出
printf("puzzle #%d:\n",kase);
//输出横向单词
printf("Across\n");
for(i=0;i<r;i++)
for(j=0;j<c;j++)
if(network_num[i][j] != 0){
printf("%3d.",network_num[i][j]);
while(isalpha(network_alpha[i][j]) && j<c){ //"||"有一个为真即为真 ,这里两个条件都得满足才能运行 .
putchar(network_alpha[i][j++]);
}
printf("\n");
}
//输出纵向单词
printf("Down\n");
for(i=0;i<r;i++)
for(j=0;j<c;j++)
if(network_num[i][j] != 0){
printf("%3d.",network_num[i][j]);
int row=i;
while(isalpha(network_alpha[row][j]) && row<r){
putchar(network_alpha[row][j]);
network_num[row++][j]=0;
}
printf("\n");
}
}
return 0;
}
注意
- 输入多组,每组是两个数字,但是可以分开接收,先接收第一个数字,判断是否为0,如果不为0,则继续接收第二个数字。如果为0则结束接收。
- while(scanf("%d",&c)==1 && c)
- while(scnaf("%d",&c) && c!=0 )
- 接收输入的一串字母,可以用char类型的数组,scanf("%s",network_row_alpha);用%s做占位符。数组名即为首地址。