设有n个人围坐一圈并按顺时针方向从1到n编号,从第s个人开始进行1到m的报数,报数到第m个人,此人出圈,再从他的下一个人重新开始1到m的报数,如此进行下去直到所有的人都出圈为止。现要求按出圈次序,每10人一组,给出这n个人的顺序表。请编写函数Josegh()实现此功能,并调用函数WriteDat(),把结果p输出到OUT.dat文件中。
设n=100,s=1,m=10。
①将1到n个人的序号存入一维数组p中;②若第i个人报数后出圈,则将p[i]置于数组的倒数第i个位置上,而原来第i+1个至倒数第i个元素依次向前移动一个位置;③重复第②步直至圈中只剩下p[1]为止。
注意:部分源程序已经给出。请勿改动主函数main()和输出数据函数WriteDat()的内容。
#include <stdio.h>
#define N 100
#define S 1
#define M 10
int p[100], n, s, m;
void WriteDat(void);
void Josegh(void)
{
}
void main()
{ m = M;
n = N;
s = S;
Josegh();
WriteDat();
}
void WriteDat(void)
{ int i;
FILE *fp;
fp = fopen("OUT.dat", "w");
for (i=N-1; i>=0; i--)
{ printf("%4d ", p[i]);
fprintf(fp, "%4d", p[i]);
if (i%10 == 0)
{ printf("\n");
fprintf(fp, "\n");
}
}
fclose(fp);
}
试题答案及详解
【审题分析】分析题目可知,本题只要实现Josegh()函数的功能即可。Josegh()要实现的功能是:根据指定的出圈方式,给出这n个人的出圈顺序表。因此解答本题的关键在于根据题目要求给出出圈顺序表的运算语句。
【解题思路】用变量s1记录报数的开始位置,第1个for循环语句将1到n个人的序号存入一维数组p中;第2个for循环语句从数组的最后一个元组开始,用表达式“(s1+m-1)%i;”求第i个人是否报数到m,如果这个表达式的值为零,说明第i个人报数到m,把p[i]存入变量w中,然后用for循环语句把原来第i+1个至倒数第i个元素依次向前移动一个位置,再把p[i]置于数组的倒数第i个位置上。
【参考答案】
void Josegh(void)
{ int i, j, s1, w;
s1 = s;
for (i=1; i<=n; i++)
p[i-1] = i;
for (i=n; i>=2; i--)
{ s1 = (s1+m-1)%i;
if (s1 == 0)
s1 = i;
w = p[s1-1];
for (j=s1; j<=i-1; j++)
p[j-1] = p[j];
p[i-1] = w;
}
}
【易错分析】第i个人是否报数到m,用表达式(s1+m-1)%i判断。
【考点链接】C语言for循环语句的用法。
责任编辑:小草