本文来自:https://mp.weixin.qq.com/s/_Z4fjXFJtEYSXVG2eXzR3Q
更多内容访问:https://mp.weixin.qq.com/s/rHpW_eVKQ7Xs3WfMghJwLw
一位老师看了2020年江苏省计算机对口单招考试中一道程序设计题的参考答案后,和我说他的学生写的程序很条理、便于理解。我看了他给的答案后,感觉这位中职生了不起,编程思路非常清晰。现将该题的参考答案和这位同学的答案分享给大家。
题目:已知半径为5,圆心为(6,9)的圆,字符串s给出一组以空格为分隔符的点的坐标,每个坐标的横、纵坐标值以逗号分隔,并以二进制字符串表示。求各点与圆的相对位置(在圆上,圆外,圆内),如果s格式错显示“参数错”。
例如:char s[]= {" 101,10 11,101 1001,1010 "} 表示3个点,其坐标分别为(5,2), (3,5), (9,10),其中点(5,2)在圆外,点(3,5)在圆上,(9,10)在圆内。
试编写以下两个函数:
1.int change(char s[],int num[][3])函数,将s中所有二进制数字字符子串转换为用整数表示的点的坐标,存放在num数组的同一行前2列。函数返回坐标的个数。如果s的格式错,返回0。
2.void calc(int num[][3],int n)函数,根据num数组中每行前2个元素所对应的点,判断点在圆的位置,其结果存放在第三列,若在圆上为0,圆外为1,圆内为2。
本题的难点是change函数的设计,将二进制字符串表示的坐标值转换为十进制数。转换算法可描述如下:
1. 跳过空格;
2. 接收‘0’和‘1’字符串作为横坐标;
3. 接收逗号;
4. 接收‘0’和‘1’字符串作为纵坐标;
5. 如果前面2-4步都正确,则转1继续处理下一组坐标,直到串结束,否则格式错。
参考答案如下:
#include <stdio.h>
#include <stdlib.h>
int change(char s[],int num[][3]) {
int i=0, n=0, flag=2; //flag=2表示格式正确
for (i=0; s[i]&&flag==2; i++) {
if (s[i]==' ') continue; // 跳过空格
flag=0;
num[n][0] = num[n][1] = 0;
if (s[i]=='1' || s[i]=='0') flag=1;
while(s[i]=='1' || s[i]=='0') // 处理横坐标
num[n][0]=num[n][0]*2+s[i++]-48;
if (flag!=1 || s[i++]!=',') break; // 逗号
if (s[i]=='1' || s[i]=='0') flag=2;
while(s[i]=='1' || s[i]=='0') // 处理纵坐标
num[n][1]=num[n][1]*2+s[i++]-48;
i--;
n++; //接收下一组坐标
}
if (flag!=2) n=0; // 格式错
return n;
}
void calc(int num[][3],int n) {
int i,y,x;
for(i=0; i<n; i++) {
x=num[i][0]-6; // 6 圆心横坐标
y=num[i][1]-9; // 9 圆心纵坐标
num[i][2] =x*x + y*y - 5*5; // 5 半径
if(num[i][2]>0) num[i][2]=1;
else if(num[i][2]<0) num[i][2]=2;
}
}
int main() {
char s[]= {" 11,10 11,101 1001,1010 "};
int num[10][3], i ,n;
char disp[][10]= {"上","外","内"};
n=change(s,num);
if (n==0) { printf("参数错\n") ;
} else { calc(num,n);
for(i=0; i<n; i++)
printf("点(%d,%d)在圆%s\n",num[i][0],
num[i][1],disp[num[i][2]]);
}
return 0;
}
- 程序运行结果:
下面是学生的答案,仅列出change函数的代码。
int change(char s[],int num[][3]) {
int i=0,n=0,sum1=0,sum2=0;
while(s[i]) {
// 在处理X坐标前,s[i]可以是空格、‘0’和‘1’,
// 否则“格式错”。
if(s[i]!='0'&&s[i]!='1'&&s[i]!=' ') {
n=0;
break;
}
// 若s[i]是'0'或'1'时,开始处理X坐标
if(s[i]=='0'||s[i]=='1') {
// 计算X坐标
while((s[i]=='0'||s[i]=='1')&& s[i]) {
sum1=sum1*2+s[i++]-'0';
}
//X坐标后应该为',',且','后面应该为'0'或'1',否则“格式错”
if((s[i]!=',')||(s[i+1])!='0'&&s[i+1]!='1') {
n=0;
break;
} else {
i++; // 跳过逗号
}
// 计算Y坐标
while((s[i]=='0'||s[i]=='1')&& s[i]) {
sum2=sum2*2+s[i++]-'0';
}
// Y坐标后应该为空格,或串结束符,否则“格式错”
if(s[i]==' ' || s[i]==0) {
// 格式正确,保存坐标
num[n][0]=sum1;
num[n++][1]=sum2;
sum1=0;
sum2=0;
} else {
n=0; // 格式错
break;
}
} else { // s[i]为空格,则处理下一个字符
i++;
}
}
return n;
}
代码虽然很长,但易于理解。